精华内容
下载资源
问答
  • 灰度差分统计法计算图像的对比度

    千次阅读 2019-01-11 21:44:10
    灰度差分统计法计算图像的对比度插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式...

    灰度差分统计法计算图像的对比度
    本文采用灰度差分统计法计算图像的对比度、角度方向二阶矩、熵、平均值来描述纹理图像的特征,具体原理如下:
    设(x,y)为图像中的一点,该点与和它只有微小距离的点(x+△x,y+△y)的灰度差分值为
    g△(x,y)=g(x,y)-g(x+△x,y+△y)
    式中,g△为灰度差分。设灰度差分的所有可能取值共有m级,令点(x,y)在整幅图像上移动,累计出g△(x,y)取各个数值的次数,由此便可以做出g△(x,y)的直方图。由直方图可以知道g△(x,y)取值的概率p△(i),i在1~m之间取值
    当较小的i值的概率p△(i)较大时,说明纹理较粗糙,当p△(i)的各个取值较接近时,即概率分布较平坦时,说明纹理较细。
    对比度计算公式
    CON = ∑i^2PΔ(i)
    角度方向计算公式
    ASM=CON = ∑i[PΔ(i)]^2,

    ENT= -∑iPΔ(i)lg PΔ(i)
    平均值
    MEAN = 1/m ∑iPΔ(i)

    结果如下:
    以LINA作为示例
    原图像
    图像直方图
    在这里插入图片描述

    插入链接与图片

    计算结果
    在这里插入图片描述

    #include<opencv2/opencv.hpp>
    #include<opencv2/core/core.hpp>
    #include<iostream>
    #include<math.h>
    using namespace std;
    using namespace cv;
    /*绘制直方图函数*/
    void show_his(Mat &Image,Mat &HI)
    {
    	int channels = 0;    //计算图像的通道
    	MatND disHist;        //配置输出的结果
    	int histSize[] = { 256 };//将数值分组,每个灰度范围一组
    	float midRanges[] = { 0, 256 };  //确定每个维度的取值范围
    	const float *ranges[] = { midRanges };
    	//调用calcHist函数,将直方图的信息存储到disHist
    	calcHist(&Image, 1, &channels, Mat(), disHist, 1, histSize, ranges, true, false);
    	Mat drawImage = Mat::zeros(Size(256, 256), CV_8SC3);//黑底的图像
    	//计算直方图后像素的最大个数
    	double g_dHistMaxValue;
    	minMaxLoc(disHist, 0, &g_dHistMaxValue, 0, 0);
    	for (int i = 0; i < 256; i++)  //遍历直方图数据
    	{
    		int value = cvRound(disHist.at<float>(i) * 256 * 0.9 / g_dHistMaxValue);
    
    		line(drawImage, Point(i, drawImage.rows - 1), Point(i, drawImage.rows - 1 - value), Scalar(255, 255, 255));
    		//参数   要绘制的线段的图像  线段的起点      线段的终点                               线段的颜色
    	}
    	 HI = drawImage.clone();
    }
    int main()
    {
    	Mat img = imread("lena.bmp");
    	imshow("Lena", img);
    	Mat mi;
    	int row = img.rows;
    	int col = img.cols;
    	//CON=i*i*P(I)
    	//计算i
    	mi.create(row, col, img.type());
    	for (int i = 0; i < row-1; i++)
    		for (int j = 0; j < col; j++)
    		{   
    			//cout << "BEF" << int(img.ptr<uchar>(i)[j]) << endl;
    			mi.at<Vec3b>(i, j) = img.at<Vec3b>(i + 1, j) - img.at<Vec3b>(i, j);
    			//cout << "IMF:" << int(mi.ptr<uchar>(i)[j]) << endl;
    		}
    	//计算p(I)  差值的概率
    	int new_cols = mi.cols;
    	int new_rows = mi.rows;
    	int gray[256] = { 0 };
    	double gray_prob[256] = { 0 };
    	int num = 0;// 像素的总个数
    	//统计直方图各个像素灰度值
    	for (int i = 0; i < mi.rows; i++)
    	{
    		uchar *p = mi.ptr<uchar>(i);
    		for (int j = 0; j < mi.cols; j++)
    		{
    			int value = p[j];
    			gray[value]++;
    			num++;
    		}
    	}
    	//计算直方图概率分布
    	for (int i = 0; i < 256; i++)
    	{
    		gray_prob[i] = ((double)gray[i] / num);
    	}
    	double CON = 0;
    	double ASM = 0;
    	double ENT = 0;
    	double MEAN = 0;
    	double v = 1.0/ 255.0;
    	for (int i = 0; i <= 255; i++)
    	{
    		CON += i*i*gray_prob[i];//计算CON
    		ASM += gray_prob[i] * gray_prob[i];//计算角度方向二阶矩
    		if (gray_prob[i]!=0)
    		ENT += (0-gray_prob[i] * log10(gray_prob[i]));//计算熵
    		MEAN += v*i*gray_prob[i];//计算平均值
    	}
    	Mat HI;
    	show_his(mi,HI);
    	imshow("差值i的直方图", HI);
    	cout << "灰度差分统计法求得的对比度为:" << CON << endl;
    	cout << "灰度差分统计法求得的角度方向二阶矩为" << ASM << endl;
    	cout << "灰度差分统计法求得的熵" << ENT << endl;
    	cout << "灰度差分统计法求得的平均值" << MEAN << endl;
    	waitKey(0);
    	return 0;
    }
    
    展开全文
  • 今天我们来看一下如何访问图像的像素,以及如何改变图像的亮度与对比度。在之前我们先来看一下图像矩阵数据的排列方式。我们以一个简单的矩阵来说明:对单通道图像排列如下:对于双通道图像排列如下:那么对于三通道...

    今天我们来看一下如何访问图像的像素,以及如何改变图像的亮度与对比度。

    在之前我们先来看一下图像矩阵数据的排列方式。我们以一个简单的矩阵来说明:

    对单通道图像排列如下:

    对于双通道图像排列如下:

    那么对于三通道的RGB图像则为:

    知道了排列方式之后我们来讨论一下访问图像像素常用的三种方式:

    1.使用指针访问;

    2.使用迭代器访问;

    3.使用动态地址访问;

    为了比较一下三种方式的效率,我们介绍两个函数来统计一下每种方式所需的时间。

    int64 getTickCount()函数:返回CPU自某个时间(如开启电脑)以来走过的时钟周期数。

    double getTickFrequency()函数:返回每秒钟CPU走过的时钟周期数。

    然后我们来看第一种方式。

    1.使用指针访问图像像素:我们将输入图像img_src的每一个像素值加上50后赋值给输出图像img_dst。

    1 intmain()2 {3 intc;4 Mat img_src = imread("1.jpg");5 Mat img_dst;6

    7 namedWindow("原图");8 namedWindow("处理图");9

    10 int channels = img_src.channels();//获取图像通道数

    11 img_dst =img_src.clone();12

    13 double time1 = static_cast(getTickCount());//获取开始处理前时间

    14

    15 for (int i = 0; i < img_src.rows; i++)//访问图像行数据

    16 {17 uchar* p_data1 = img_src.ptr(i);//获取图像行首地址

    18 uchar* p_data2 = img_dst.ptr(i);//获取图像行首地址

    19 for (int k = 0; k < img_src.cols*channels; k++)//获取图像列(含通道)

    20 {21 p_data2[k] = saturate_cast(p_data1[k] + 50);//图像处理22

    23 //*p_data2++ = saturate_cast((*p_data1++) + 100);//与上一行图像处理的等效方式24 //*(p_data2 + k) = saturate_cast(*(p_data1 + k) + 50);//同上

    25 }26 }27

    28 double time2 = static_cast(getTickCount());//获取结束处理时间

    29

    30 time1 = (time2 - time1) / getTickFrequency();//计算处理所用时间

    31 cout << "指针访问像素时间(S):" << time1 <

    33 while (1)34 {35 imshow("原图", img_src);//显示图像

    36 imshow("处理图", img_dst);//显示图像

    37 c = waitKey(0);38 if (c == 27 || char(c) == 'q' || char(c) == 'Q')//按下Q键或者ESC键退出程序

    39 break;40 }41 return 0;42 }

    2.使用迭代器方式:

    1 intmain()2 {3 intc;4 Mat img_src = imread("1.jpg");5 Mat img_dst;6

    7 namedWindow("原图");8 namedWindow("处理图");9

    10 int channels = img_src.channels();//获取图像通道数

    11 img_dst =img_src.clone();12

    13 double time1 = static_cast(getTickCount());//获取开始处理前时间

    14

    15 Mat_::iterator it = img_src.begin();//获取原图开始地址

    16 Mat_::iterator itend = img_src.end();//获取原图结束地址

    17 Mat_::iterator it2 = img_dst.begin();//获取输出图开始地址

    18 for (; it != itend; ++it, ++it2)19 {20 for (int i = 0; i < 3; i++)21 {22 (*it2)[i] = saturate_cast((*it)[i] + 50);//图像处理

    23 }24 }25

    26 double time2 = static_cast(getTickCount());//获取结束处理时间

    27

    28 time1 = (time2 - time1) / getTickFrequency();//计算处理所用时间

    29 cout << "指针访问像素时间(S):" << time1 <

    31 while (1)32 {33 imshow("原图", img_src);//显示图像

    34 imshow("处理图", img_dst);//显示图像

    35 c = waitKey(0);36 if (c == 27 || char(c) == 'q' || char(c) == 'Q')//按下Q键或者ESC键退出程序

    37 break;38 }39 return 0;40 }

    3.动态地址方式:

    1 intmain()2 {3 intc;4 Mat img_src = imread("1.jpg");5 Mat img_dst;6

    7 namedWindow("原图");8 namedWindow("处理图");9

    10 int channels = img_src.channels();//获取图像通道数

    11 img_dst =img_src.clone();12

    13 double time1 = static_cast(getTickCount());//获取开始处理前时间

    14

    15 for (int i = 0; i < img_src.rows; i++)16 {17 for (int k = 0; k < img_src.cols; k++)18 {19 for (int j = 0; j < channels; j++)20 {21 img_dst.at(i, k)[j] = saturate_cast(img_src.at(i, k)[j] + 50);22 }23 }24 }25

    26 double time2 = static_cast(getTickCount());//获取结束处理时间

    27

    28 time1 = (time2 - time1) / getTickFrequency();//计算处理所用时间

    29 cout << "指针访问像素时间(S):" << time1 <

    31 while (1)32 {33 imshow("原图", img_src);//显示图像

    34 imshow("处理图", img_dst);//显示图像

    35 c = waitKey(0);36 if (c == 27 || char(c) == 'q' || char(c) == 'Q')//按下Q键或者ESC键退出程序

    37 break;38 }39 return 0;40 }

    我们来看一下处理的结果吧:

    实例

    下面我们来看一个完整调用三种方式的例子,我们定义三个函数Mat image_bright1(Mat src);Mat image_bright2(Mat src);Mat image_bright3(Mat src);分别用来用三种方式处理图片。

    1 //************头文件包含*************

    2 #include "stdafx.h"

    3 #include

    4 #include//包含opencv的头文件5 //***********************************6

    7

    8 //************命名空间***************

    9 using namespace cv;//使用opencv命名空间

    10 using namespacestd;11 //***********************************12

    13

    14 //************全局变量***************15

    16 //***********************************17

    18

    19 //************全局函数***************

    20 Mat image_bright1(Mat src);//使用指针访问像素

    21

    22 Mat image_bright2(Mat src);//使用迭代器访问像素

    23

    24 Mat image_bright3(Mat src);//使用动态地址访问像素25 //***********************************26

    27

    28 //************主函数*****************

    29 intmain()30 {31 intc;32 Mat img_src = imread("1.jpg");33 Mat img_dst1, img_dst2, img_dst3;34

    35 namedWindow("原图",0);36 namedWindow("指针访问像素",0);37 namedWindow("迭代器访问像素",0);38 namedWindow("动态地址访问像素",0);39

    40 double time1 = static_cast(getTickCount());41 img_dst1 = image_bright1(img_src);//使用指针访问像素

    42

    43 double time2 = static_cast(getTickCount());44 img_dst2 = image_bright2(img_src);//使用迭代器访问像素

    45

    46 double time3 = static_cast(getTickCount());47 img_dst3 = image_bright3(img_src);//使用动态地址访问像素

    48

    49 double time4 = static_cast(getTickCount());50

    51 time1 = (time2 - time1) /getTickFrequency();52 time2 = (time3 - time2) /getTickFrequency();53 time3 = (time4 - time3) /getTickFrequency();54

    55 cout << "指针访问像素时间(S):"<

    59 while (1)60 {61 imshow("原图", img_src);//显示图像

    62 imshow("指针访问像素", img_dst1);//显示图像

    63 imshow("迭代器访问像素", img_dst2);//显示图像

    64 imshow("动态地址访问像素", img_dst3);//显示图像

    65

    66 c = waitKey(0);67 if (c == 27 || char(c) == 'q' || char(c) == 'Q')//按下Q键或者ESC键退出程序

    68 break;69 }70

    71 return 0;72 }73

    74

    75 //使用指针访问像素

    76 Mat image_bright1(Mat src)77 {78 Mat dst;79 int channels =src.channels();80 dst =src.clone();81

    82 for (int i = 0; i < src.rows; i++)83 {84 uchar* p_data1 =src.ptr(i);85 uchar* p_data2 =dst.ptr(i);86

    87 for (int k = 0; k < src.cols*channels; k++)88 {89 //*p_data2++ = saturate_cast((*p_data1++) + 100);90 //*(p_data2 + k) = saturate_cast(*(p_data1 + k) + 50);

    91 p_data2[k] = saturate_cast(p_data1[k] + 50);//输出图像像素=原图像像素+50

    92 }93 }94 returndst;95 }96

    97

    98 //使用迭代器访问像素

    99 Mat image_bright2(Mat src)100 {101 Mat dst;102 dst =src.clone();103

    104 Mat_::iterator it = src.begin();105 Mat_::iterator itend = src.end();106 Mat_::iterator it2 = dst.begin();107 for (; it != itend; ++it, ++it2)108 {109 for (int i = 0; i < 3; i++)110 {111 (*it2)[i] = saturate_cast(2*(*it)[i]);//输出图像像素=2*原图像像素

    112 }113 }114 returndst;115 }116

    117

    118 //使用动态地址访问像素

    119 Mat image_bright3(Mat src)120 {121 Mat dst;122 int channels =src.channels();123 dst =src.clone();124 for (int i = 0; i < src.rows; i++)125 {126 for (int k = 0; k < src.cols; k++)127 {128 for (int j = 0; j < channels; j++)129 {130 dst.at(i, k)[j] = saturate_cast(2*src.at(i, k)[j] + 50);//输出图像像素=2*原图像像素+50

    131 }132 }133 }134 returndst;135 }

    结果:

    从时间上我们可以看出来,使用指针的速度是最快的。

    有些童鞋应该已经看出来了,在三种方法中我们将图像像素的处理方法变了一下,得出的图像也不一样了。在三种方法中我们处理像素的计算方式分别为:

    输出图像像素=原图像像素+50;

    输出图像像素=2*原图像像素;

    输出图像像素=2*原图像像素+50;

    其实这就是处理亮度与对比度的方法,从图像上也能看出来。

    总结一下:g(x)=k*f(x)+b;其中g(x)为输出图像,f(x)为输入图像;

    调节k的值则可以改变图像的对比度;

    调节b的值则可以改变图像的亮度;

    下载

    功能很简单,代码很少,建议自己写一下或者在博文中复制一下,当然实在是懒的不要不要的土豪可以去下面的连接直接下载。

    展开全文
  • 本示例说明如何使用粒度分析来计算图像中雪花大小分布。粒度测定法确定图像中对象大小分布,而无需先明确分割(检测)每个对象。读入图像阅读“ ”图像,它是雪花照片。I=imread('');imshow(I)增强对比度第一...

    本示例说明如何使用粒度分析来计算图像中雪花的大小分布。粒度测定法确定图像中对象的大小分布,而无需先明确分割(检测)每个对象。

    读入图像

    阅读“ ”图像,它是雪花的照片。

    I=imread('');imshow(I)

    增强对比度

    第一步是使图像中的强度对比度最大化。您可以使用adapthisteq函数来执行此操作,该函数执行对比度限制的自适应直方图均衡。使用imadjust函数重新缩放图像强度,以使其填充数据类型的整个动态范围。

    claheI=adapthisteq(I,'NumTiles',[1010]);claheI=imadjust(claheI);imshow(claheI)

    确定增强图像中的强度表面积分布

    粒度测定法估计雪花的强度表面积分布与尺寸的关系。粒度分析法将图像对象比作石头,其大小可以通过在尺寸增大的筛子上进行筛分并在每次通过后收集剩余物来确定。通过使用大小增加的结构元素做图像开操作并计数每次开操作后剩余的强度表面积(图像中像素值的总和)来筛选图像对象。

    选择一个反极限,以使强度表面积在您增加结构元素的大小时变为零。出于显示目的,将表面积数组中的第一个条目保留为空。

    radius_range=0:22;intensity_area=zeros(size(radius_range));forcounter=radius_rangeremain=imopen(claheI,strel('disk',counter));intensity_area(counter+1)=sum(remain(:));endfigureplot(intensity_area,'m - *')gridontitle('Sum of pixel values in opened image versus radius')xlabel('radius of opening (pixels)')ylabel('pixel value sum of opened objects (intensity)')

    计算分布的一阶导数

    两个连续的开操作之间的强度表面积的显著下降,表示图像包含与较小的开操作可比较大小的对象。这等效于强度表面积数组的一阶导数,其中包含图像中雪花的大小分布。使用diff函数计算一阶导数。

    intensity_area_prime=diff(intensity_area);plot(intensity_area_prime,'m - *')gridontitle('Granulometry (Size Distribution) of Snowflakes')ax=gca;ax.XTick=[0246810121416182022];xlabel('radius of snowflakes (pixels)')ylabel('Sum of pixel values in snowflakes as a function of radius')

    提取具有特定半径的雪花

    请注意图中的最小值和半径。最小值告诉您图像中的雪花具有这些半径。最小点越趋向负向,则该半径处的雪花累积强度越高。例如,最负的最小值出现在5像素半径标记处。您可以按照以下步骤提取半径为5像素的雪花。

    open5=imopen(claheI,strel('disk',5));open6=imopen(claheI,strel('disk',6));rad5=imsubtract(open5,open6);imshow(rad5,[])

    注:本文根据MATLAB官网内容修改而成。

    以下的免费视频教程,特点是没有PPT,不掺水,直接编程环境下的实操课程:

    用100分钟了解MATLAB编程

    知乎 - 安全中心

    欢迎您进一步了解以下MATLAB系列文章:

    吃小羊:MATLAB作图实例:00:索引
    e392b6cbe5d45b5668d361b91ecc98c3.png
    吃小羊:MATLAB金融工具箱:00:索引
    ab1df7649061fa27cb9452ec575f71c0.png
    吃小羊:MATLAB图像处理:00:索引
    44172e301e08805722ac860b83b6e2e7.png
    展开全文
  • 这篇文章中我们一起学习了如何在OpenCV中用createTrackbar...然后讲解图像的对比度、亮度值调整的细节,最后放出了一个利用createTrackbar函数创建轨迹条来辅助进行图像对比度、亮度值调整的程序源码。依然是先放...

    这篇文章中我们一起学习了如何在OpenCV中用createTrackbar函数创建和使用轨迹条,以及图像对比度、亮度值的动态调整。

    文章首先详细讲解了OpenCV2.0中的新版创建轨迹条的函数createTrackbar,并给上一个详细注释的示例。

    然后讲解图像的对比度、亮度值调整的细节,最后放出了一个利用createTrackbar函数创建轨迹条来辅助进行图像对比度、亮度值调整的程序源码。

    依然是先放一张运行截图:

    bf38894b7eba16b624fea2214795ded2.png

    好了,下面正式开始我们的讲解。

    一、OpenCV中轨迹条(Trackbar)的创建和使用

    <1>创建轨迹条——createTrackbar函数详解

    createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便。首先大家要记住,它往往会和一个回调函数配合起来使用。先看下他的函数原型:

    C++: int createTrackbar(conststring& trackbarname, conststring& winname, int* value, int count, TrackbarCallback onChange=0,void* userdata=0);
    • 第一个参数,const string&类型的trackbarname,表示轨迹条的名字,用来代表我们创建的轨迹条。
    • 第二个参数,const string&类型的winname,填窗口的名字,表示这个轨迹条会依附到哪个窗口上,即对应namedWindow()创建窗口时填的某一个窗口名。
    • 第三个参数,int* 类型的value,一个指向整型的指针,表示滑块的位置。并且在创建时,滑块的初始位置就是该变量当前的值。
    • 第四个参数,int类型的count,表示滑块可以达到的最大位置的值。PS:滑块最小的位置的值始终为0。
    • 第五个参数,TrackbarCallback类型的onChange,首先注意他有默认值0。这是一个指向回调函数的指针,每次滑块位置改变时,这个函数都会进行回调。并且这个函数的原型必须为void XXXX(int,void*);其中第一个参数是轨迹条的位置,第二个参数是用户数据(看下面的第六个参数)。如果回调是NULL指针,表示没有回调函数的调用,仅第三个参数value有变化。
    • 第六个参数,void*类型的userdata,他也有默认值0。这个参数是用户传给回调函数的数据,用来处理轨迹条事件。如果使用的第三个参数value实参是全局变量的话,完全可以不去管这个userdata参数。

    这个createTrackbar函数,为我们创建一个具有特定名称和范围的轨迹条(Trackbar,或者说是滑块范围控制工具),指定一个和轨迹条位置同步的变量。而且要指定回调函数onChange(第五个参数),在轨迹条位置改变的时候来调用这个回调函数。并且我们知道,创建的轨迹条显示在指定的winname(第二个参数)所代表的窗口上。

    看完函数讲解,先给大家一个函数使用小示例

     //创建轨迹条createTrackbar("对比度:", "【效果图窗口】",&g_nContrastValue,300,ContrastAndBright );// g_nContrastValue为全局的整型变量,ContrastAndBright为回调函数的函数名(即指向函数地址的指针)

    然给大家一个完整的使用示例。这是OpenCV官方的sample示例程序,一个演示了用轨迹条来控制轮廓检测,轮廓填充的程序。浅墨将其修改、代码简洁化和详细注释,放出来供大家消化研习。稍后更新的博文会有关于轮廓检测更详细的讲解。

    //-----------------------------------【头文件包含部分】---------------------------------------//描述:包含程序所依赖的头文件//---------------------------------------------------------------------------------------------- #include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include  //-----------------------------------【命名空间声明部分】---------------------------------------//描述:包含程序所使用的命名空间//-----------------------------------------------------------------------------------------------   using namespace cv;using namespace std; //-----------------------------------【全局函数声明部分】--------------------------------------//描述:全局函数声明//-----------------------------------------------------------------------------------------------Mat img;int threshval = 160;//轨迹条滑块对应的值,给初值160 //-----------------------------【on_trackbar( )函数】------------------------------------//描述:轨迹条的回调函数//-----------------------------------------------------------------------------------------------static void on_trackbar(int, void*){Mat bw = threshval < 128 ? (img < threshval) : (img > threshval); //定义点和向量vector > contours;vector hierarchy; //查找轮廓findContours( bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );//初始化dstMat dst = Mat::zeros(img.size(), CV_8UC3);//开始处理if( !contours.empty() && !hierarchy.empty() ){//遍历所有顶层轮廓,随机生成颜色值绘制给各连接组成部分int idx = 0;for( ; idx >= 0; idx = hierarchy[idx][0] ){Scalar color( (rand()&255), (rand()&255), (rand()&255) );//绘制填充轮廓drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );}}//显示窗口imshow( "Connected Components", dst );}  //-----------------------------------【main( )函数】--------------------------------------------//描述:控制台应用程序的入口函数,我们的程序从这里开始//-----------------------------------------------------------------------------------------------int main(  ){system("color 5F");  //载入图片img = imread("1.jpg", 0);if( !img.data ) { printf("Oh,no,读取img图片文件错误~! "); return -1; } //显示原图namedWindow( "Image", 1 );imshow( "Image", img ); //创建处理窗口namedWindow( "Connected Components", 1 );//创建轨迹条createTrackbar( "Threshold", "Connected Components", &threshval, 255, on_trackbar );on_trackbar(threshval, 0);//轨迹条回调函数 waitKey(0);return 0;}

    原图:

    d2026f87c189919f1726cde53389e9c5.png

    运行效果图:

    56d279d2c6d0c764ad962b03775a73ba.png

    拖动滚动条,改变threshval(阈值)的值,得到效果迥异的图片:

    acfa7409903f85014565a567f9eb1589.png

    另外,在OpenCV路径opencv_source_code/samples/cpp/connected_components.cpp下,可以找到原版的官方代码。

    接着顺便讲一个配合createTrackbar使用的函数,用于获取当前轨迹条的位置的getTrackbarPos函数吧。

    <2>获取当前轨迹条的位置——getTrackbarPos函数

    这个函数用于获取当前轨迹条的位置并返回。

    C++: int getTrackbarPos(conststring& trackbarname, conststring& winname);
    • 第一个参数,const string&类型的trackbarname,表示轨迹条的名字。
    • 第二个参数,const string&类型的winname,表示轨迹条的父窗口的名称。

    这部分大概就是这些了。马不停蹄地向下一部分进发吧:)

    二、亮度和对比度调整的理论依据

    首先我们给出算子的概念。一般的图像处理算子都是一个函数,它接受一个或多个输入图像,并产生输出图像。下式给出了算子的一般形式

    4fe98153dda7fe6cea1616ef2a6b7f6f.png

    或者

    177b81e083c80106315d09dcbe69bcdb.png

    今天我们所讲解的图像亮度和对比度的调整操作,其实属于图像处理变换中比较简单的一种——点操作(pointoperators)。点操作有一个特点,仅仅根据输入像素值(有时可加上某些全局信息或参数),来计算相应的输出像素值。这类算子包括亮度(brightness)和对比度(contrast)调整,以及颜色校正(colorcorrection)和变换(transformations)。

    最两种常用的点操作(或者说点算子),很显然,是乘上一个常数(对应对比度的调节)以及加上一个常数(对应亮度值的调节)。用公式表示出来就是这样:

    1b8ba9076bef3cb3ab6727552f63a5d9.png

    看到这个式子,我们关于图像亮度和对比度调整的策略就呼之欲出了。

    其中:

    参数f(x)表示源图像像素。

    参数g(x) 表示输出图像像素。

    参数a(需要满足a>0)被称为增益(gain),常常被用来控制图像的对比度。

    参数b通常被称为偏置(bias),常常被用来控制图像的亮度。

    而更近一步,我们这样改写这个式子:

    b3caf94438d58b839e82859ed9acddc2.png

    其中,i 和 j 表示像素位于第i行 和 第j列 。

    那么,这个式子就可以用来作为我们在OpenCV中控制图像的亮度和对比度的理论公式了。

    三、关于访问图片中的像素

    访问图片中的像素有很多种方式,以后有机会浅墨会用个专题来讲解。目前我们可以先了解下面的这一种。

    而为了执行

    cae42ff67284949666eb9dc7b56fb217.png

    这个运算 ,我们需要访问图像的每一个像素。因为是对GBR图像进行运算,每个像素有三个值(G、B、R),所以我们必须分别访问它们(PS:OpenCV中的图像存储模式为GBR)。以下是访问像素的代码片段,三个for循环解决问题:

           //三个for循环,执行运算 new_image(i,j) =a*image(i,j) + b       for(int y = 0; y < image.rows; y++ )       {              for(int x = 0; x < image.cols; x++ )              {                     for(int c = 0; c < 3; c++ )                     {                            new_image.at(y,x)[c]= saturate_cast( (g_nContrastValue*0.01)*(image.at(y,x)[c] ) + g_nBrightValue );                     }              }       }

    让我们分三个方面进行讲解:

    • 为了访问图像的每一个像素,我们使用这样的语法: image.at(y,x)[c]
    • 其中,y是像素所在的行, x是像素所在的列, c是R、G、B(对应0、1、2)其中之一。
    • 因为我们的运算结果可能超出像素取值范围(溢出),还可能是非整数(如果是浮点数的话),所以我们要用saturate_cast对结果进行转换,以确保它为有效值。
    • 这里的a也就是对比度,一般为了观察的效果,取值为0.0到3.0的浮点值,但是我们的轨迹条一般取值都会整数,所以在这里我们可以,将其代表对比度值的nContrastValue参数设为0到300之间的整型,在最后的式子中乘以一个0.01,这样就可以完成轨迹条中300个不同取值的变化。所以在式子中,我们会看到saturate_cast( (g_nContrastValue*0.01)*(image.at(y,x)[c] ) + g_nBrightValue )中的g_nContrastValue*0.01。

    四、图像对比度、亮度值调整示例程序

    依然是每篇文章都会配给大家的一个详细注释的博文配套示例程序,把这篇文章中介绍的知识点以代码为载体,展现给大家。

    这个示例程序用两个轨迹条分别控制对比度和亮度值,有一定的可玩性。废话不多说,上代码吧:

    //-----------------------------------【程序说明】----------------------------------------------//  程序名称::【OpenCV入门教程之四】 创建Trackbar&图像对比度、亮度值调整 配套博文源码// VS2010版  OpenCV版本:2.4.8//  2014年3月18 日 Create by 浅墨//------------------------------------------------------------------------------------------------  //-----------------------------------【头文件包含部分】---------------------------------------//     描述:包含程序所依赖的头文件//----------------------------------------------------------------------------------------------#include #include#include"opencv2/imgproc/imgproc.hpp"#include  //-----------------------------------【命名空间声明部分】---------------------------------------//     描述:包含程序所使用的命名空间//-----------------------------------------------------------------------------------------------  using namespace std;using namespace cv;  //-----------------------------------【全局函数声明部分】--------------------------------------//     描述:全局函数声明//-----------------------------------------------------------------------------------------------static void ContrastAndBright(int, void *); //-----------------------------------【全局变量声明部分】--------------------------------------//     描述:全局变量声明//-----------------------------------------------------------------------------------------------int g_nContrastValue; //对比度值int g_nBrightValue;  //亮度值Mat g_srcImage,g_dstImage;//-----------------------------------【main( )函数】--------------------------------------------//     描述:控制台应用程序的入口函数,我们的程序从这里开始//-----------------------------------------------------------------------------------------------int main(  ){       //改变控制台前景色和背景色       system("color5F");         //读入用户提供的图像       g_srcImage= imread( "pic1.jpg");              if(!g_srcImage.data ) { printf("Oh,no,读取g_srcImage图片错误~!"); return false; }       g_dstImage= Mat::zeros( g_srcImage.size(), g_srcImage.type() );        //设定对比度和亮度的初值       g_nContrastValue=80;       g_nBrightValue=80;        //创建窗口       namedWindow("【效果图窗口】", 1);        //创建轨迹条       createTrackbar("对比度:", "【效果图窗口】",&g_nContrastValue,300,ContrastAndBright );       createTrackbar("亮   度:","【效果图窗口】",&g_nBrightValue,200,ContrastAndBright );             //调用回调函数       ContrastAndBright(g_nContrastValue,0);       ContrastAndBright(g_nBrightValue,0);             //输出一些帮助信息       cout<(y,x)[c]= saturate_cast( (g_nContrastValue*0.01)*(g_srcImage.at(y,x)[c] ) + g_nBrightValue );                     }              }       }        //显示图像       imshow("【原始图窗口】", g_srcImage);       imshow("【效果图窗口】", g_dstImage);}

    最后看一下运行截图,运行这个程序会得到两个图片显示窗口。第一个为原图窗口,第二个为效果图窗口。在效果图窗口中可以调节两个轨迹条,来改变当前图片的对比度和亮度。

    原图:

    a46d704880719fdd86387727071a4410.png

    可调节的效果图:

    02803cdc94ee47020084ef51223300e3.png
    2211ef82c16085bee9cdc26d1be7a155.png

    本文转载于https://blog.csdn.net/zhmxy555/category_9262318.html

    作者:浅墨_毛星云

    对OpenCV感兴趣的可以去看原作者的其他文章

    展开全文
  • 目标在本教程中,将学习如何:访问像素值用零初始化矩阵获取关于像素变换的一些很酷的信息在实际的例子中提高图像的亮度理论下面的解释属于Richard Szeliski 的“ 《计算机视觉:算法与应用》 ”一书图像处理一般的...
  • 目标在本教程中,您将学习如何:访问像素值用零初始化矩阵获取有关像素变换的一些很酷的信息在一个实际的例子中提高图像的亮度理论注意下面的解释属于Richard Szeliski的“计算机视觉:算法与应用”一书图像处理一般...
  • 图像对比度增强,即增强图像中的有用信息,抑制无用信息,从而改善图像的视觉效果。图像色调增强,即改善图像的色调效果,创造色彩更加丰富以及突出主题的效果。 摄影师,尤其是专业摄影师,基本上都会对拍摄的作品...
  • 直方图就是对数据进行统计,将统计值组织...灰度图像的直方图的性质: (1) 直方图是一幅图像中各像素灰度出现频次的统计结果,它只反映图像中不同灰度值出现的次数,而没反映某一灰度所在的位置。也就是说,它只包含了
  • 编辑 | 言有三 1 图像美学增强基础1.1 什么是美学增强一幅图像要有更好美感,最基本要求就是对比度分布合理,饱和度以及色调符合图像主题,本次我们从图像对比度增强和色调增强两个方面来谈论自动地美学增强问题...
  • 编辑 | 言有三1 图像美学增强基础1.1 什么是美学增强一幅图像要有更好美感,最基本要求就是对比度分布合理,饱和度以及色调符合图像主题,本次我们从图像对比度增强和色调增强两个方面来谈论自动地美学增强问题...
  • 编辑 | 言有三 1 图像美学增强基础1.1 什么是美学增强一幅图像要有更好美感,最基本要求就是对比度分布合理,饱和度以及色调符合图像主题,本次我们从图像对比度增强和色调增强两个方面来谈论自动地美学增强问题...
  • 直方图就是对数据进行统计,将统计值组织到...灰度图像的直方图的性质: (1) 直方图是一幅图像中各像素灰度出现频次的统计结果,它只反映图像中不同灰度值出现的次数,而没反映某一灰度所在的位置。也就是说,它只包
  • 看了几遍不是很明白具体是怎么操作,我理解是:将原来的图像划分为不重叠几个区域(一般是8*8)然后在每个区域内,限制对比度如何限制?不明白),并且把一部分特别 这是原来博文截图,这个图我...
  • 首先什么是 SSIM 算法,该算法主要用于检测两张尺寸相同的图像的相似度,但注意到论文标题结构信息,所以实际上它主要通过两个图像的亮度(l)、对比度(c)、结构(s)这三个要素的测量,而在论文中这三个要...
  • 可以调节图像的明暗程度,增强区域的对比度,同时给出了一种选择最优参数的方法"通过调整直方图均衡化后像素的灰度值,给出了保留灰度级的直方图均衡化方法,丰富了图像的灰度层次,一定程度上消除了灰阶合并现象对图像...
  • 重点讨论了如何利用多计算单元加速计算最耗时梯度计算部分。详细介绍了多方向直方图并行统计机制及χ2并行计算中访存冲突避免机制。对比实验表明,在GPU上基于该并行方法轮廓提取相比传统CPU方式具有明显加速...
  • 系列文章目录 C++ OpenCV4.5环境搭建(一) C++ OpenCV4.5常用API查询手册(二) C++ OpenCV4.5 图像处理(三) C++ OpenCV4.5 绘制形状与文字(四) ...本篇介绍如何调整图像亮度和对比度的方法,效果
  • 如何定量计算和预测在不同条件下偏振滤波抑制大气背景光效果,目前缺乏合适性能表征量及其计算模型,为此提出了偏振滤波抑制大气背景光性能计算模型。...ARR指标值越大,图像对比度提高越明显。
  • 将学习如何在图像中建模不同类型的噪声,以及如何从图像中去除噪声,这样可以增强图像的对比度。还将学习边缘检测和静态对象分割的方法。 增强图片对比度 读一下图片‘lena.gif’ (with imread);、 下面是如何增加...
  • GLSL实现图像处理

    万次阅读 2015-05-06 21:02:23
    今天晚上没事将以前弄的OPENGL着色语言实现滤镜效果的实现和大家分享一下,滤镜主要包括图像的对比度调整、浮雕效果、彩色图片灰度化、卷积等操作。 这些操作其本质上是属于图像处理的东西,OpenGL实现图像处理主要...
  • 该方法对几种非理想情况具有鲁棒性,例如对比度差,遮挡,凝视偏差,瞳Kong扩张,运动模糊,聚焦差,帧交错,图像分辨率差异,镜面反射和阴影。 与文献中大多数技术不同,所提出方法在恶劣条件下使用不同成像...
  • 2.1.2 如何计算图像对角化所需的矩阵U,V和Λ.? 44 B2.2 如果矩阵ggT 的本征值为负会如何? 44 2.1.3 什么是对一幅图像的奇异值分解? 47 2.1.4 能将一幅本征图像分解成多幅本征图像吗? 48 2.1.5 如何可用SVD...
  • 本文作者:小嗷 微信公众号:aoxiaoji 关键词:颜色空间缩减和计时函数【两个简便的计时函数—getTickCount()和... 请看第8篇代码【更正曝光不足的图像(图像的对比度和亮度及轨迹条)】 OpenCv的矩阵...
  • GLSL实现图像处理(FBO方法)

    千次阅读 2017-03-22 18:01:18
    今天晚上没事将以前弄的OPENGL着色语言实现滤镜效果的实现和大家分享一下,滤镜主要包括图像的对比度调整、浮雕效果、彩色图片灰度化、卷积等操作。  这些操作其本质上是属于图像处理的东西,OpenGL实现图像处理...
  • 图像的基本处理:图像的二值化、图像的亮度和对比度的调整、图像的边缘增强、如何得到图像的直方图、图像直方图的修正、图像的平滑、图像的锐化等、图像的伪彩色、彩色图像转换为黑白图像、物体边缘的搜索等等;...
  • 理解并掌握灰度直方图概念、计算灰度直方图方法以及如何应用直方图均衡化来增强图像对比度。 二、实验环境: 计算机、WindowsXP操作系统,Matlab7.0 三、实验内容: 以灰度图像pout.tif为例,运用Matlab编程...

空空如也

空空如也

1 2 3 4 5 6
收藏数 101
精华内容 40
关键字:

如何计算图像的对比度