使用C++、opencv基于不同的颜色空间调节图像亮度

该博客简单介绍了RGB、YUV、HSI等颜色空间的相关知识,并附RGB转到另两个颜色空间的转换公式: https://www.cnblogs.com/justkong/p/6570914.html

https://blog.csdn.net/sinat_26917383/article/details/70860910及https://wenku.baidu.com/view/6273f20a581b6bd97f19ea99.html也都介绍了不同的颜色空间的相关知识。

该博客介绍了opencv中颜色转换的函数及RGBHSV空间的实际应用:https://blog.csdn.net/dieju8330/article/details/82465616


:opencv中HSI、HSV、HSL中的H分量的范围是0-180,剩下两个(SI、SL、SV)都是0-255;

V分量即是RGB中最大的那个分量,与图像亮度无关,所以选择HSL空间研究;

opencv中颜色空间转换函数在2.x与3.x版本中都是cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0),只是code的宏定义的写法有点区别(3.x中将2.x中的CV前缀变为COLOR前缀)。


该博客介绍了HSLHSV颜色空间的区别:https://blog.csdn.net/binglan520/article/details/56288135

 注:在公式上HSL、HSV、HSI的区别在于:L=(MAX(R,G,B)+MIN(R,G,B))/2;V=MAX(R,G,B));I=(R+G+B)/3。


该博客介绍了不同光照条件(即亮度条件)下几个颜色空间的色彩分量的区别及应用颜色阈值进行分割的相关知识:https://blog.csdn.net/wc781708249/article/details/78517463


本代码在不同颜色空间下(HSI、Lab、YCrCb),对跟亮度有关的颜色分量(I、L、Y)进行直方图均衡化,达到平衡亮度的效果,其次以YCrCb空间为例,展示利用滑动条调节图像整体Y值。

相关重要API:

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );

颜色空间转换函数

InputArray src: 输入图像即要进行颜色空间变换的原图像,可以是Mat类;

OutputArray dst: 输出图像即进行颜色空间变换后存储图像,也可以Mat类;

int code: 转换的代码或标识,即在此确定将什么制式的图片转换成什么制式的图片,具体见下图;

int dstCn = 0: 目标图像通道数,如果取值为0,则由src和code决定

void split(const Mat& src, Mat*mvbegin);

void split(InputArray m,OutputArrayOfArrays mv);

split()函数可以把一幅图像各个通道分离开

第一个参数为要进行分离的图像矩阵,第二个参数可以是Mat数组的首地址,或者一个vector<Mat>对象

void merge(const Mat* mv, size_tcount, OutputArray dst)
void merge(InputArrayOfArrays mv,OutputArray dst)

经过对各个通道单独操作后可以用merge()函数进行合并

第一种:第一个参数是图像矩阵数组,第二个参数是需要合并矩阵的个数,第三个参数是输出。

第二种:第一个参数是图像矩阵向量容器,第二个参数是输出,这种方法无需说明需要合并的矩阵个数,vector对象自带说明。

以上部分参考:https://blog.csdn.net/keith_bb/article/details/53470170、https://blog.csdn.net/u012819339/article/details/82222008、https://blog.csdn.net/xiexu911/article/details/79722535


#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <fstream>
#include <iterator>using namespace cv;
using namespace std;//定义一些变量及声明函数
Mat src = imread("C:\\Users\\lenovo\\Desktop\\1.jpg");Mat hsv, lab, ycrcb;
Mat hsvdst, labdst, ycrcbdst;
Mat dst(src.size(), src.type(), Scalar::all(0));
void balance_hsv(Mat & hsv);
void balance_lab(Mat & lab);
void balance_ycrcb(Mat & ycrcb);
void drawHist(Mat cur);int y_value = 0;
void on_changebright(int, void *);int main(int argc, char** argv)
{system("color 02");/*//获取图像每个像素点的RGBHSVLabYCrCb的值,并写入文件中cvtColor(src, hsv, COLOR_BGR2HSV);cvtColor(src, lab, COLOR_BGR2Lab);cvtColor(src, ycrcb, COLOR_BGR2YCrCb);FILE *fp;fopen_s(&fp, "C:\\Users\\lenovo\\Desktop\\RGB数据.xls", "a");for(int i=0;i<src.rows;i++)for (int j = 0; j < src.cols; j++){fprintf(fp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", src.at<Vec3b>(i, j)[2], src.at<Vec3b>(i, j)[1], src.at<Vec3b>(i, j)[0],hsv.at<Vec3b>(i, j)[0], hsv.at<Vec3b>(i, j)[1], hsv.at<Vec3b>(i, j)[2],lab.at<Vec3b>(i, j)[0], lab.at<Vec3b>(i, j)[1], lab.at<Vec3b>(i, j)[2], ycrcb.at<Vec3b>(i, j)[0], ycrcb.at<Vec3b>(i, j)[1], ycrcb.at<Vec3b>(i, j)[2]);}fclose(fp);*///平衡图像亮度balance_hsv(src);balance_lab(src);balance_ycrcb(src);//显示源图像namedWindow("src", WINDOW_NORMAL);imshow("src", src);//创建调节Y值的滑动条createTrackbar("y", "bright", &y_value, 200,on_changebright);//滑动条回调函数on_changebright(0, 0);waitKey(0);return 0;
}void balance_hsv(Mat & src)
{//将源图像转换到HSV颜色空间   cvtColor(src, hsv, COLOR_BGR2HSV);//分割为3通道Mat splitchannels[3], temp;split(hsv, splitchannels);if (splitchannels[2].channels() == 1){equalizeHist(splitchannels[2], temp);//直方图均衡化}/*drawHist(dst);//调用函数画直方图imshow("hist", yuvhist);//显示均衡化的直方图*/std::vector<Mat> dst_merge;dst_merge.push_back(splitchannels[0]);dst_merge.push_back(splitchannels[1]);dst_merge.push_back(temp);//合并修改过的3个通道图像merge(dst_merge, dst);//转换回RGB空间cvtColor(dst, hsvdst, COLOR_HSV2BGR);//显示经直方图均衡化的图像namedWindow("balance_V", WINDOW_NORMAL);imshow("balance_V", hsvdst);}void balance_lab(Mat & src)
{//将源图像转换到Lab颜色空间cvtColor(src, lab, COLOR_BGR2Lab);Mat splitchannels[3], temp;split(lab, splitchannels);if (splitchannels[0].channels() == 1){equalizeHist(splitchannels[0], temp);//直方图均衡化}/*drawHist(dst);//调用函数画直方图imshow("hist", yuvhist);//显示均衡化的直方图*/std::vector<Mat> dst_merge;dst_merge.push_back(temp);dst_merge.push_back(splitchannels[1]);dst_merge.push_back(splitchannels[2]);//合并修改过的3个通道图像merge(dst_merge, dst);//转换回RGB空间cvtColor(dst, labdst, COLOR_Lab2BGR);//显示经直方图均衡化的图像namedWindow("balance_L", WINDOW_NORMAL);imshow("balance_L", labdst);}void balance_ycrcb(Mat & src)
{//将源图像转换到YCrCb颜色空间cvtColor(src, ycrcb, COLOR_BGR2YCrCb);Mat splitchannels[3], temp;split(ycrcb, splitchannels);if (splitchannels[0].channels() == 1){equalizeHist(splitchannels[0], temp);//直方图均衡化}/*drawHist(dst);//调用函数画直方图imshow("hist", yuvhist);//显示均衡化的直方图*/std::vector<Mat> dst_merge;dst_merge.push_back(temp);dst_merge.push_back(splitchannels[1]);dst_merge.push_back(splitchannels[2]);//合并修改过的3个通道图像merge(dst_merge, dst);//转换回RGB空间cvtColor(dst, ycrcbdst, COLOR_YCrCb2BGR);//显示经直方图均衡化的图像namedWindow("balance_Y", WINDOW_NORMAL);imshow("balance_Y", ycrcbdst);}void on_changebright(int, void *)
{Mat src1;//将源图拷贝至目标图实现变化实时更新dst.copyTo(src1);//转换至YCrCb颜色空间cvtColor(src1, src1, COLOR_BGR2YCrCb);//调节每个点的Y值,这里也可以换成其他变化,如降低图像的亮度值或其他颜色值for(int i=0;i<src1.rows;i++)for (int j = 0; j < src1.cols; j++){//Y值增加一个给定值src1.at<Vec3b>(i, j)[2] += y_value;//溢出保护if (src1.at<Vec3b>(i, j)[2] > 255 )src1.at<Vec3b>(i, j)[2] = 255;}//转换回RGB空间观察变化cvtColor(src1, src1, COLOR_HSV2BGR);//显示亮度调节后的图像namedWindow("bright", WINDOW_NORMAL);imshow("bright", src1);}void drawHist(Mat cur)
{//需要计算图像的哪个通道(bgr空间需要确定计算 b或g或r空间)      const int channels[1] = { 0 };//直方图的每一个维度的 柱条的数目(就是将灰度级分组)    int histSize[] = { 256 };   //如果这里写成int histSize = 256;   那么下面调用计算直方图的函数的时候,该变量需要写 &histSize    //定义一个变量用来存储 单个维度 的数值的取值范围      float midRanges[] = { 0, 256 };//确定每个维度的取值范围,就是横坐标的总数      const float *ranges[] = { midRanges };//输出的结果存储的 空间 ,用MatND类型来存储结果    MatND dstHist;calcHist(&cur, 1, channels, Mat(), dstHist, 1, histSize, ranges, true, false);//calcHist  函数调用结束后,dstHist变量中将储存了 直方图的信息  用dstHist的模版函数 at<Type>(i)得到第i个柱条的值  at<Type>(i, j)得到第i个并且第j个柱条的值      //首先先创建一个白底的图像,为了可以显示彩色,所以该绘制图像是一个8位的3通道图像      yuvhist = Mat(Size(128, 128), CV_8UC3, Scalar::all(255));//一个图像的某个灰度级的像素个数(最多为图像像素总数),可能会超过显示直方图的所定义的图像的尺寸,因此绘制直方图的时候,让直方图最高的地方只有图像高度的90%来显示    //先用minMaxLoc函数来得到计算直方图后的像素的最大个数      double g_dHistMaxValue;minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0);//遍历直方图得到的数据      for (int i = 0; i < 128; i++){int value = cvRound(128 * 0.9 *(dstHist.at<float>(i) / g_dHistMaxValue));line(yuvhist, Point(i, yuvhist.rows - 1), Point(i, yuvhist.rows - 1 - value), Scalar(0, 255, 50));}
}

源图像:

平衡V后的图像:

平衡L后的图像:

平衡Y后的图像:

调节Y值的图像(其他变化,如降低图像的亮度值或其他颜色值等可自行根据需求尝试):

画出的直方图就不演示了。

调节彩色图像亮度(基于不同的颜色空间)相关推荐

  1. 图像目标检索:基于Opencv的颜色空间匹配法

    图像目标检索:基于Opencv的颜色空间匹配法 目标效果:近似于淘宝上--拍照搜索,检索商品的效果,在传统算法领域,也有一些优秀的算法能粗略的实现该效果,本文便基于传统算法中的颜色空间匹配法来实现,代 ...

  2. 基于matlab的pid调节论文,毕业论文 基于matlab的智能PID控制器的设计与仿真

    引 言 PID控制器以其结构简单.稳定性好.工作可靠.调整方便等优点被广泛应用于工业控制系统,但现代工业控制系统越来越复杂,被控对象往往表现出时滞.非线性.时变性,控制要求越来越高,传统的PID控制器 ...

  3. 【OpenCV 例程300篇】209. HSV 颜色空间的彩色图像分割

    OpenCV 例程200篇 总目录 [youcans 的 OpenCV 例程300篇]209. HSV 颜色空间的彩色图像分割 5.1 HSV 颜色空间的彩色图像分割 HSV 模型是针对用户观感的一种 ...

  4. 王亚楠:基于强化学习的自动码率调节

    本文来自 爱奇艺 技术产品中心 资深工程师 王亚楠在LiveVideoStackCon 2018热身分享,并由LiveVideoStack整理而成.在分享中,王亚楠分别介绍了自动码率调节的实现过程.现 ...

  5. 基于matlab的彩色图像分割,彩色图像分割MATLAB

    [实例简介] 基于HSV彩色空间的图像分割,包含测试图片,MATLAB源程序,可以参考一下 [实例截图] [核心代码] 彩色图像分割 └── 基于matlab的彩色图像的分割算法 └── 公园与青椒的 ...

  6. 计算机视觉基础——图像处理(彩色空间互转)cpp+python

    3.1 简介 图像彩色空间互转在图像处理中应用非常广泛,而且很多算法只对灰度图有效:另外,相比RGB,其他颜色空间(比如HSV.HSI)更具可分离性和可操作性,所以很多图像算法需要将图像从RGB转为其 ...

  7. 基于引导滤波的暗通道matlab,基于加权引导滤波的水下图像增强算法

    在水下环境中,由于水分子以及溶解的杂质对光线的吸收和散射作用,导致水下图像出现对比度低.噪声较大等严重的退化问题.这不仅降低了图像的整体视觉效果,而且给后续图像的自动处理和识别产生不利影响.因此,研究 ...

  8. 彩色图像分割方法的汇总

    [汇总]彩色图像分割 Menu   SkySeraph Oct.1st 2011  HQU   Email:zgzhaobo@gmail.com    QQ:452728574   Latest Mo ...

  9. 数字图像处理与Python实现笔记之彩色图像处理初步

    数字图像处理与Python实现笔记之彩色图像处理初步 摘要 绪论 1 数字图像处理基础知识 2 彩色图像处理初步 2.1 彩色图像的颜色空间 2.1.1 RGB颜色空间 2.1.2 HSI颜色空间 2 ...

最新文章

  1. 2022-2028年全球与中国乳胶丝市场研究及前瞻分析报告
  2. 通过cat /proc/cpuinfo看处理器特点
  3. 周立功:专注的力量成就梦想
  4. [MySQL]经常无故崩溃amd.dll , boot1.exe病毒
  5. js方式调用php_举例说明JS调用PHP和PHP调用JS的方法
  6. java boolean if_Java if(boolean)和if(boolean=true)区别解析
  7. 如何在Vue中添加百度统计代码?
  8. s8050三极管经典电路_电子电路-闪瞎你的眼!爆闪警示灯超简单原理介绍!
  9. 【opencv】左右两张图片实现全景拼接
  10. mysql之高性能索引
  11. android腾讯微博吹一吹实现原理
  12. lgv20刷twrp_TWRP 新增对 Realme C2, LG V20等设备的支持
  13. ubuntu内核升级导致显卡驱动丢失
  14. 硬件探索——2FSK通信系统调制解调综合实验电路设计
  15. Linux内核2:中断代码分析
  16. A1088 Rational Arithmetic (20 分)
  17. html表格方式实现商品详情
  18. 【12-06】A股主要指数的市盈率(PE)估值高度
  19. 有关AE2020中文版改为英文版的方法
  20. Java实现LDAP认证(上)

热门文章

  1. python requests爬虫——爬取李开复博客信息(包括javascript部分信息)
  2. 重审新消费品牌的长远发展
  3. 单片机c语言模块化实例程序设计,单片机C语言模块化编程方法
  4. 【M365运维】- 设定会议室预订的消息推送
  5. Python基础学习——Numpy包(1、数据类型及数组创建)
  6. 这次是真的被优化了。
  7. 简析条形图(bar plot)上的误差线(转载)
  8. 在一个疾驰的经济体下,我们能够为我们的怠慢买单吗?
  9. 练一练,嵌入式Linux工程师操作系统面试题三道
  10. python绘制两个圆柱体的交线