《2022年基础学习笔记之opencv直方图使用学习》由会员分享,可在线阅读,更多相关《2022年基础学习笔记之opencv直方图使用学习(8页珍藏版)》请在金锄头文库上搜索。
1、目的:直方图在cv 领域到处可见,因为其功能在cv 算法的实现中必不可少。Opencv库中也集成了关于直方图的不少函数,比如直方图的计算,均衡,归一化,相似度比较等等。为了体验这些函数,做了个小实验,功能是:打开摄像头,鼠标选定一个框,框内图像作为标准图像,计算出其直方图并显示出来;然后继续鼠标选定框,该框内的图像的直方图与标准图像的进行相似度计算,计算结果在终端输出,数值越大表示相似度越大。工程环境: opencv2.3.1+vs2010。工程代码: 1 / hist_test.cpp : 定义控制台应用程序的入口点。 2 / 3 4 #include stdafx.h 5 #include
2、 6 #include 7 #include 8 #include 9 #include 10 11 usingnamespace cv; 12 usingnamespace std; 13 14 int nFrame_num=0; 15 bool pause=false; 16 bool tracking=false; 17 Rect preselectROI,selectROI;/ 用于存放手选的矩形 18 bool comp= true; 19 20 Mat rhist,ghist,bhist; 21 int channels=0, 1, 2; 22 /const int histsiz
3、e=256,256,256; 23 constint histsize=16 , 16, 16 ; 24 constint histsize1=16; 25 float rranges=0, 255 ; 26 float granges=0, 255 ; 27 float branges=0, 255 ; 28 float range=0, 255 ; 29 constfloat *ranges1=range;/这里的 ranges就相当于一个双指针了 30 constfloat *ranges=rranges,granges,branges;/ranges是个双指针,且前面一定要用 cons
4、t,即不可改变常量,提高程序的可读性和稳健性 31 /const float *ranges=0,255,0,255,0,255;精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 1 页,共 8 页 32 33 void onMouse(intevent, int x,int y,int, void * ) 34 35 if( event=CV_EVENT_LBUTTONDOWN) 36 37 selectROI.x=x; 38 selectROI.y=y; 39 tracking=false; 40 41 elseif( event=CV_EVEN
5、T_LBUTTONUP) 42 43 selectROI.width=x-selectROI.x; 44 selectROI.height=y-selectROI.y; 45 tracking=true; 46 comp=true; 47 nFrame_num+;/ 选定后才算真正意义上的第一帧 48 if(nFrame_num=10)nFrame_num=10; / 防止 nFrame_num溢出 49 50 51 52 int main(int argc, constchar* argv) 53 54 Mat frame,img; 55 Mat staRoiHist; 56 MatND R
6、oiHist; 57 int DRAW_H=400 ,DRAW_W=400 ; 58 Mat draw(DRAW_W,DRAW_H,CV_8UC3,Scalar(0, 0, 0);/ 建立一个显示直方图的图片,背景为纯黑色 59 int DRAW_BIN_W=cvRound(DRAW_W/histsize1); 60 61 /*打开摄像头 */ 62 VideoCapture cam(0); 63 if(! cam.isOpened() 64 return - 1; 65 66 /*鼠标捕捉 */ 67 namedWindow(camera, 1); 68 namedWindow(rgb_hi
7、st, 1); 69 setMouseCallback(camera,onMouse,0); / 这里用的是面向对象的思想,只要有鼠标动作就会调用鼠标响应函数 70 71 while( 1) 72 73 if(!pause)/暂停按钮只需控制视频的读取精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 2 页,共 8 页 74 75 camframe; 76 if(frame.empty() 77 break; /break此处跳出的是while语句,一般是跳出for或 while语句,不要理解为跳出if语句 78 79 /* if(1=nFrame_
8、num) 80 81 82 */ 83 if(tracking) 84 85 Mat RoiImage(frame,selectROI); 8687/*/ 88 /* calcHist():计算图像块的直方图矩阵*/ 89 /*calcHist(),第 1 个参数为原数组区域列表;第二个参数为有计算几个原数组;参数 3 为需要统计的通道索引数;参数4 为操作掩码 */ 90 /*第 5 个参数为存放目标直方图矩阵;参数 6 为需要计算的直方图的维数;参数 7 为每一维的bin的个数;参数8 为每一维数值的取值范围*/ 91 /*参数 10 为每个 bin的大小是否相同的标志,默认为 1,即 b
9、in的大小都相同; 参数 11 为直方图建立时清除内存痕迹标志,默认为0,即清除 */92/*/ 93calcHist(&RoiImage,1 ,channels,Mat(),RoiHist,3,histsize,ranges);/原数组区域RoiImage,1个源,需要统计的通道索引为0,1,2, 94 /目标直方图RoiHist,3 维,每一维的bin数 histsize,取值范围为 95 /ranges,实际上计算出的目标矩阵类似一维矩阵。 96 9798/*/ 99 /* normalize():根据某种范数或者数值范围归一化数组*/100 /* normalize(),参数 1 表示
10、需要归一化的数组;参数2 为归一化后的目的数组; 参数 3 表示输出数值的最小值 / 最大值或者输出数值的范数;*/101 /* 参数 4 表示输出数值的最小值/ 最大值 ; 参数 5 表示归一化数组使用的归一化类型,默认值为使用 L2 范数 ; 参数 6 为对应元素的掩膜矩阵 */精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 3 页,共 8 页102 /* 默认值为空,即不采用掩膜操作*/103 /*/104 normalize(RoiHist,RoiHist);/使用 L2 范数将 RoiHist直方图原地归一化105106 vector r
11、gb_planes;/ 这里的 vector为向量,向量的数据类型为Mat 结构体,向量的长度为3107 split(RoiImage,rgb_planes);/将 rgb 图分解到 rgb_planes各个分量中108 calcHist(&rgb_planes0,1, 0,Mat(),rhist,1,&histsize1,&ranges1); 109 normalize(rhist,rhist,0,DRAW_H,NORM_MINMAX);/进行最大最小值归一化110 calcHist(&rgb_planes1,1, 0,Mat(),ghist,1,&histsize1,&ranges1);
12、111 normalize(ghist,ghist,0,DRAW_H,NORM_MINMAX); 112 calcHist(&rgb_planes2,1, 0,Mat(),bhist,1,&histsize1,&ranges1); 113 normalize(bhist,bhist,0,DRAW_H,NORM_MINMAX); 114 if(nFrame_num=1) 115 116 / preselectROI=selectROI;117 preselectROI.x=selectROI.x; 118 preselectROI.y=selectROI.y; 119 preselectROI.
13、width=selectROI.width; 120 preselectROI.height=selectROI.height; 121 staRoiHist=RoiHist.clone();/第一次选定目标,作为标准模板目标122 123 elseif(nFrame_num1&comp= true) 124 125 /*/126 /* compareHist():比较 2 个直方图的相似度*/127 /* compareHist(), 参数 1 为比较相似度的直方图1; 参数 2 为比较相似度的直方图2;参数 3 为相似度的计算方式。有四种, */128 /* 分别为CV_COMP_CORR
14、EL,CV_COMP_CHISQR,CV_COMP_INTERSECT,CV_COMP_BHATTACHARYYA */129 /*/130 double distence=compareHist(staRoiHist,RoiHist,CV_COMP_INTERSECT);/ 计算后面选定的与这次选定的相似度,使用INTERSECT ,值越大越相似131 printf( 与第 1 次选定的图像区域相似度为:%fn,distence);/ 数组越大,相似度越大132133 / 显示直方图134 for( int i=1;ihistsize1;i+) 精选学习资料 - - - - - - - -
15、- 名师归纳总结 - - - - - - -第 4 页,共 8 页135 136 / 画直线中要注意2 点,因为图片的原点在左上角,而直方图坐标系的原点在左下角,所以高度值都需要被直方图图纸高度减掉,另外取一维直方图时只能用at 运算符137line(draw,Point(DRAW_BIN_W*(i-1),DRAW_H-cvRound(rhist.at(i-1),Point(DRAW_BIN_W*(i),DRAW_H-cvRound(rhist.at(i),Scalar(255 , 0, 0),2, 8, 0); 138line(draw,Point(DRAW_BIN_W*(i-1),DRAW
16、_H-cvRound(ghist.at(i-1),Point(DRAW_BIN_W*(i),DRAW_H-cvRound(ghist.at(i),Scalar(0, 255 , 0),2, 8, 0); 139line(draw,Point(DRAW_BIN_W*(i-1),DRAW_H-cvRound(bhist.at(i-1),Point(DRAW_BIN_W*(i),DRAW_H-cvRound(bhist.at(i),Scalar(0, 0, 255 ),2, 8, 0); 140 141 imshow(rgb_hist,draw); 142 draw=Mat:zeros(DRAW_W
17、,DRAW_H,CV_8UC3);/每画完一次直方图后都进行一次清 0 操作143 comp=false; 144 145 rectangle(frame,selectROI,Scalar(0, 255 , 0), 2, 8); /手动选定一次就显示一次146 /end tracking147 rectangle(frame,preselectROI,Scalar(0, 0, 255 ), 5, 8 ); / 初始的选定目标一直不变148 imshow(camera,frame); 149150 / 键盘响应151 char c = (char )waitKey(10); 152 if( c
18、= 27 ) 153 break; 154 switch(c) 155 156 case p: / 暂停键157 pause = !pause; 158 break; 159 default: 160 ; 161 162 /end while;163 return0; 164 实验结果:精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 5 页,共 8 页选定框内的模板用红色框标出,其他待比较的模板用绿色框标出。模板图像块的简单直方图(rgb分开画的 ) 显示如下:第一次比较结果图:第二次比较结果图:精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 6 页,共 8 页第三次比较结果图(2 个框选定的基本重合):三次比较相似度结果:精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 7 页,共 8 页可以看出,第三次的框与标准框内图像( 即第 1 次选定的图像区域)的相似度值最大。精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 8 页,共 8 页