首页 - 通讯 - vs2010直方图定义参数_OpenCV学习(十六)直方图均衡与绘制直方图

vs2010直方图定义参数_OpenCV学习(十六)直方图均衡与绘制直方图

2023-10-08 14:51

opencv版本:2.3.1

配置环境:openCV学习笔记(一):opencv2.3.1和vs2010安装配置

#包括

#包括

#包括

#包括

使用命名空间 cv;

使用命名空间 std;

int main()

{

char *imageSrc = "I:\\OpenCV Learning\\picture\\sumpalace.jpg";

垫图像 = imread(imageSrc,1);

/****************************************/

//Mat greyImage = imread(imageSrc,0);

/****************************************/

if(!www.gsm-guard.net)

{

cout<<"错误"<

返回-1;

}

imshow("原图",图片);

矢量 rgb平面;

split(图像,rgbPlanes);

/****************************************/

/*rgbPlanes向量(递增数组),通过split()函数,将图像的R、G、B通道分别添加到rgbPlanes[0]、rgbPlanes[1]、rgbPlanes[2]

/****************************************/

//Mat *grayImage = &grayImage0;

/****************************************/

int histSize = 256;

//R、G、B取值范围为[0,255]

浮点范围[] = {0,255};

const float *histRange = {范围};

//三个矩阵,分别保存R、G、B直方图

垫红色Hist、绿色Hist、蓝色Hist;

/****************************************/

//Mat greyHist;

/****************************************/

//计算R、G、B直方图,见下文calcHist()函数的参数分析

calcHist( &rgbPlanes[0], 1, 0, Mat(), redHist, 1, &histSize, &histRange,true,false);

calcHist( &rgbPlanes[1], 1, 0, Mat(), greenHist, 1, &histSize, &histRange,true,false);

calcHist( &rgbPlanes[2], 1, 0, Mat(), blueHist, 1, &histSize, &histRange,true,false);

/****************************************/

//calcHist(&grayImage,1,0,Mat(),grayHist,1,&histSize,&histRange,true,false);

/****************************************/

//定义显示直方图的画布

int histWidth = 400;

int histHeight = 400;

int binWidth = cvRound((double)histWidth/histSize);

Mat histImage(histWidth,histHeight,CV_8UC3,标量(0,0,0));

//后面进行归一化处理参见normalize()函数的参数分析

标准化(redHist,redHist,0,histImage.rows,NORM_MINMAX,-1,Mat());

标准化(greenHist,greenHist,0,histImage.rows,NORM_MINMAX,-1,Mat());

标准化(blueHist,blueHist,0,histImage.rows,NORM_MINMAX,-1,Mat());

/****************************************/

//标准化(grayHist,grayHist,0,histImage.rows,NORM_MINMAX,-1,Mat());

/****************************************/

//绘制直方图

for( int i = 1; i < histSize; i++ )

{

line( histImage, Point( binWidth*(i-1), histHeight - cvRound(www.gsm-guard.net(i-1)) ) ,

点( binWidth*(i), histHeight - cvRound(www.gsm-guard.net(i)) ),

标量( 0, 0, 255), 2, 8, 0 );

// 矩形(histImage,Point( binWidth*(i-1), histHeight),

// 点( binWidth*(i-1), histHeight - cvRound(www.gsm-guard.net(i))), 标量(0,0,255), CV_FILLED);

line( histImage, Point( binWidth*(i-1), histHeight - cvRound(www.gsm-guard.net(i-1)) ) ,

点( binWidth*(i), histHeight - cvRound(www.gsm-guard.net(i)) ),

标量( 0, 255, 0), 2, 8, 0 );

line( histImage, Point( binWidth*(i-1), histHeight - cvRound(www.gsm-guard.net(i-1)) ) ,

点( binWidth*(i), histHeight - cvRound(www.gsm-guard.net(i)) ),

标量( 255, 0, 0), 2, 8, 0 );

/****************************************/

/*line( histImage, Point( binWidth*(i-1), histHeight - cvRound(www.gsm-guard.net(i-1)) ) ,

点( binWidth*(i), histHeight - cvRound(www.gsm-guard.net(i)) ),

标量( 255, 255, 255), 2, 8, 0 );*/

/****************************************/

}

// 显示直方图

imshow("直方图", histImage );

waitKey();

返回0;

}

运行结果:

说明(此部分来自http://www.gsm-guard.net/opencvdoc/2.3.2/html/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html)

——calcHist()函数

参数说明如下:

&rgbPlanes[0]:?输入数组(或数组集) 1:输入数组的数量(这里我们使用单通道图像,也可以输入数组集) 0:需要的通道(dim)索引要统计,这里只统计灰度(而且每个数组都是单通道),所以就写0即可。 Mat(): Mask(0表示忽略像素),如果不定义则不使用mask redHist: Matrix存储直方图1:直方图维度histSize:?每个维度的 bin 数量 histRange:?各尺寸的取值范围是否一致?和?accumulate:bin大小相同,直方图痕迹清晰

——normalize()函数

该函数接受以下参数:

redhist:?输入数组 redhist:?归一化输出数组(支持就地计算)0?和?histImage.rows:这里是归一化后的值限制?redhist?NORM_MINMAX:?归一化方法(示例中指定的方法将值缩放到上面指定的范围) -1:?表示归一化输出数组与输入数组 Mat() 类型相同:?可选面罩

实验环境:VS2010 + OpenCV2.4.9.0

#包括

#include "opencv2/highgui/highgui.hpp"

#include "opencv2/imgproc/imgproc.hpp"

使用命名空间 std;

使用命名空间 cv;

void showHistogram(Mat &src, int bins,char* wndName)

{

int histSize[] = {bins};

浮点范围[] = {0,bins};

const float* 范围[] = {范围};

MatND 历史记录;

int 通道[] = {0};

calcHist(&src, 1, 通道, Mat(), hist, 1, histSize, 范围, true, false);

双 maxVal;

minMaxLoc(hist, 0, &maxVal, 0, 0);

int 比例 = 2; //直方图大小(宽度)

int histHeight = 256;

Mat histImage = Mat::zeros(histHeight,bins * scale,CV_8UC1);

for(int i = 0; i < bin; i++)

{

float binVal = www.gsm-guard.net(i);

int 强度 = cvRound(binVal * histHeight/maxVal);

矩形(histImage,Point(i * 尺度,histHeight - 1),

点((i + 1)*尺度 - 1,histHeight - 强度),CV_RGB(255,255,255));

}

namedWindow(wndName,CV_WINDOW_AUTOSIZE);

imshow(wndName,histImage);

}

int main(int argc,char** argv)

{

垫 src,dst;

char* source_window = "源图像";

char* equalized_window = "均衡图像";

src = imread("lena.jpg");

if(!www.gsm-guard.net)

{

cerr <<“读取图像失败!” <<结束;

出口(1);

}

cvtColor(src,src,CV_BGR2GRAY);

equalizeHist(src,dst);

namedWindow(source_window,CV_WINDOW_AUTOSIZE);

imshow(source_window,src);

namedWindow(equalized_window,CV_WINDOW_AUTOSIZE);

imshow(equalized_window,dst);

//显示直方图

int bin = 256;

showHistogram(src, bins,"原始图像历史");

showHistogram(dst, bins,"均衡图像历史");

waitKey(0);

返回0;

}

实验结果:

原图:

原始直方图:

直方图均衡结果:

均衡后直方图:

原始来源:http://www.gsm-guard.net/tornadomeet/archive/2012/05/03/2480824.html

直方图在CV领域随处可见,因为它们的功能在CV算法的实现中至关重要。 Opencv库还集成了很多关于直方图的功能,比如直方图计算、均衡、归一化、相似度比较等。

为了体验这些功能,我做了一个小实验。功能为:打开相机,用鼠标选中一个方框,将方框内的图像作为标准图像,计算其直方图并显示;然后继续用鼠标选中方框,方框内图像的直方图

计算图像与标准图像的相似度,并在终端输出计算结果。值越大,相似度越大。

  项目环境:opencv2.3.1+vs2010。

// hist_test.cpp:定义控制台应用程序的入口点。

//

#include "stdafx.h"

#包括

#包括

#包括

#包括

#包括

使用命名空间 cv;

使用命名空间 std;

int nFrame_num=0;

布尔暂停=假;

布尔跟踪= false;

Rect preselectROI,selectROI;//用于存储手选的矩形

bool comp=true;

Mat rhist,ghist,bhist;

int 通道[]={0,1,2};

//const int histsize[]={256,256,256};

const int histsize[]={16,16,16};

const int histsize1=16;

浮动排列[]={0,255};

浮动田庄[]={0,255};

浮动范围[]={0,255};

浮点范围[]={0,255};

const float *ranges1={range};//这里的ranges相当于双指针

const float *ranges[]={rranges,granges,branges};//ranges是双指针,前面必须加const,即常量不能改变,提高了可读性和鲁棒性节目

//const float *ranges[]={{0,255},{0,255},{0,255}};

void onMouse(int event,int x,int y,int,void *)

{

if(事件==CV_EVENT_LBUTTONDOWN)

{

selectROI.x=x;

selectROI.y=y;

跟踪=假;

}

else if(事件==CV_EVENT_LBUTTONUP)

{

selectROI.width=x-selectROI.x;

selectROI.height=y-selectROI.y;

跟踪=true;

comp=true;

nFrame_num++;//选择后第一帧才是真实的

if(nFrame_num>=10)nFrame_num=10;//防止nFrame_num溢出

}

}

int main(int argc, const char* argv[])

{

垫架,img;

Mat staRoiHist;

MatND RoiHist;

int DRAW_H=400,DRAW_W=400;

Mat draw(DRAW_W,DRAW_H,CV_8UC3,Scalar(0,0,0));//创建一张图片来显示直方图,纯黑色背景

int DRAW_BIN_W=cvRound(DRAW_W/histsize1);

/****打开相机****/

视频采集摄像头(0);

if(!cam.isOpened())

返回-1;

/****鼠标捕捉****/

namedWindow("相机",1);

namedWindow("rgb_hist",1);

setMouseCallback("camera",onMouse,0);//这里使用了面向对象的思想。只要有鼠标移动,就会调用鼠标响应函数

同时(1)

{

if(!pause)//暂停键只控制视频的读取

{

凸轮>>框架;

if(frame.empty())

断裂; //break这里是一个while语句,一般是for或者while语句,不要理解为if语句

}

/* if(1==nFrame_num)

{

}*/

if(追踪)

{

Mat RoiImage(frame,selectROI);

/**************************************************** ****************************************************** *************************/

/**** calcHist():计算图像块的直方图矩阵****/

/****calcHist(),第一个参数为原数组区域列表;第二个参数是要计算的原始数组的数量;参数3为需要统计的通道索引个数;参数4为操作掩码****/

/****第五个参数是存储目标直方图矩阵;参数6为需要计算的直方图的维度;参数7是每个维度的bin数;参数8为各维度的值****/

的取值范围

/****参数10是一个标志,表示各个bin的大小是否相同,默认为1,即各个bin的大小都相同;参数11是直方图建立时清除内存痕迹的标志,默认为0,即清除****/

/**************************************************** ****************************************************** *************************/

calcHist(&RoiImage,1,channels,Mat(),RoiHist,3,histsize,ranges);//原始数组区域RoiImage,1个源,要统计的通道索引为{0,1,2},

//目标直方图RoiHist,3个维度,每个维度的bin数histsize,取值范围为

//范围,实际上计算出的目标矩阵类似于一维矩阵。

/**************************************************** ****************************************************** *************************/

/**** Normalize():按照一定的范数或数值范围对数组进行归一化****/

/**** Normalize(),参数1代表需要归一化的数组;参数2为归一化后的目标数组;参数3表示输出值的最小值/最大值或输出值的范数;****/

/**** 参数4代表输出值的最小值/最大值;参数 5 表示标准化数组中使用的标准化类型。默认值是使用L2范数;参数6是相应元素的掩码。矩阵****/

/**** 默认值为空,即不使用掩码操作****/

/**************************************************** ****************************************************** *************************/

normalize(RoiHist,RoiHist);//使用L2范数对RoiHist直方图进行就地归一化

vector rgb_planes;//这里的向量是向量,向量的数据类型是Mat结构,向量的长度为3

split(RoiImage,rgb_planes);//将rgb图像分解为rgb_planes的各个分量

calcHist(&rgb_planes[0],1,0,Mat(),rhist,1,&histsize1,&ranges1);

normalize(rhist,rhist,0,DRAW_H,NORM_MINMAX);//对最大值和最小值进行归一化

calcHist(&rgb_planes[1],1,0,Mat(),ghist,1,&histize1,&ranges1);

标准化(ghist,ghist,0,DRAW_H,NORM_MINMAX);

calcHist(&rgb_planes[2],1,0,Mat(),bhist,1,&histize1,&ranges1);

标准化(bhist,bhist,0,DRAW_H,NORM_MINMAX);

if(nFrame_num==1)

{

//预选ROI=selectROI;

preselectROI.x=selectROI.x;

preselectROI.y=selectROI.y;

preselectROI.width=selectROI.width;

preselectROI.height=selectROI.height;

staRoiHist=RoiHist.clone();//第一次选择目标作为标准模板目标

}

else if(nFrame_num>1&&comp==true)

{

/**************************************************** ****************************************************** *************************/

/****compareHist():比较两个直方图的相似度****/

/****compareHist(),参数1为直方图1,用于比较相似度;参数2为直方图2,用于比较相似度;参数3是相似度的计算方法。有四种类型,****/

/**** 分别为 CV_COMP_CORREL、CV_COMP_CHISQR、CV_COMP_INTERSECT、CV_COMP_BHATTACHARYYA ****/

/**************************************************** ****************************************************** *************************/

double distence=compareHist(staRoiHist,RoiHist,CV_COMP_INTERSECT);//计算后面的选择与本次选择的相似度,使用INTERSECT,值越大越相似

printf("与第一个选定图像区域的相似度为:%f\n",distence);//数组越大,相似度越大

//显示直方图

for(int i=1;i

{

//画直线要注意两点。因为图片的原点在左上角,而直方图坐标系的原点在左下角,所以需要从直方图绘制的高度中减去高度值,一维直方图为采取。绘图时只能使用 at 运算符

线(绘制,点(DRAW_BIN_W*(i-1),DRAW_H-cvRound(www.gsm-guard.net((i-1)))),点(DRAW_BIN_W*(i),DRAW_H-cvRound(rhist .at(i))),标量(255,0,0),2,8,0);

线(绘制,点(DRAW_BIN_W*(i-1),DRAW_H-cvRound(www.gsm-guard.net((i-1)))),点(DRAW_BIN_W*(i),DRAW_H-cvRound(ghist .at(i))),标量(0,255,0),2,8,0);

线(绘制,点(DRAW_BIN_W*(i-1),DRAW_H-cvRound(www.gsm-guard.net((i-1)))),点(DRAW_BIN_W*(i),DRAW_H-cvRound(bhist .at(i))),标量(0,0,255),2,8,0);

}

imshow("rgb_hist",draw);

draw=Mat::zeros(DRAW_W,DRAW_H,CV_8UC3);//每次绘制直方图后清0

comp=false;

}

矩形(frame,selectROI,Scalar(0,255,0),2,8);//手动选择一次显示一次

}//结束追踪

矩形(frame,preselectROI,Scalar(0,0,255),5,8);//初始选定目标不变

imshow("相机",frame);

//键盘响应

char c = (char)waitKey(10);

if( c == 27 )

断裂;

开关(c)

{

case 'p'://暂停键

暂停=!暂停;

断裂;

默认:

;

}

}//结束同时;

返回0;

}

实验结果:

  所选框中的模板用红色框标记,其他要比较的模板用绿色框标记。

  模板图像块的简单直方图(rgb单独绘制)如下所示:

第一张对比结果图: 第二张对比结果图   第三张对比结果图(选中的两个框基本重叠):   第三张对比相似度结果

0条大师的评论