使用直方图比较图像的相似度
来源:互联网 发布:js 微信分享demo 编辑:程序博客网 时间:2024/05/16 10:09
http://blog.csdn.net/vblittleboy/article/details/7763919
目的:
直方图在cv领域到处可见,因为其功能在cv算法的实现中比不可少。Opencv库中也集成了关于直方图的不少函数,比如直方图的计算,均衡,归一化,相似度比较等等。
为了体验这些函数,做了个小实验,功能是:打开摄像头,鼠标选定一个框,框内图像作为标准图像,计算出其直方图并显示出来;然后继续鼠标选定框,该框内的图像的直方
图与标准图像的进行相似度计算,计算结果在终端输出,数值越大表示相似度越大。
工程环境:opencv2.3.1+vs2010。
工程代码:
1 // hist_test.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <opencv2/core/core.hpp> 6 #include <opencv2/imgproc/imgproc.hpp> 7 #include <opencv2/highgui/highgui.hpp> 8 #include <iostream> 9 #include <stdio.h> 10 11 using namespace cv; 12 using namespace 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 histsize[]={256,256,256}; 23 const int histsize[]={16,16,16}; 24 const int histsize1=16; 25 float rranges[]={0,255}; 26 float granges[]={0,255}; 27 float branges[]={0,255}; 28 float range[]={0,255}; 29 const float *ranges1={range};//这里的ranges就相当于一个双指针了 30 const float *ranges[]={rranges,granges,branges};//ranges是个双指针,且前面一定要用const,即不可改变常量,提高程序的可读性和稳健性 31 //const float *ranges[]={{0,255},{0,255},{0,255}}; 32 33 void onMouse(int event,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 else if(event==CV_EVENT_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, const char* argv[]) 53 { 54 Mat frame,img; 55 Mat staRoiHist; 56 MatND RoiHist; 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_hist",1); 69 setMouseCallback("camera",onMouse,0);//这里用的是面向对象的思想,只要有鼠标动作就会调用鼠标响应函数 70 71 while(1) 72 { 73 if(!pause)//暂停按钮只需控制视频的读取 74 { 75 cam>>frame; 76 if(frame.empty()) 77 break;//break此处跳出的是while语句,一般是跳出for或while语句,不要理解为跳出if语句 78 } 79 /* if(1==nFrame_num) 80 { 81 82 }*/ 83 if(tracking) 84 { 85 Mat RoiImage(frame,selectROI); 86 87 /*************************************************************************************************************************/ 88 /**** calcHist():计算图像块的直方图矩阵 ****/ 89 /****calcHist(),第1个参数为原数组区域列表;第二个参数为有计算几个原数组;参数3为需要统计的通道索引数;参数4为操作掩码****/ 90 /****第5个参数为存放目标直方图矩阵;参数6为需要计算的直方图的维数;参数7为每一维的bin的个数;参数8为每一维数值的取值范围****/ 91 /****参数10为每个bin的大小是否相同的标志,默认为1,即bin的大小都相同;参数11为直方图建立时清除内存痕迹标志,默认为0,即清除****/ 92 /*************************************************************************************************************************/ 93 calcHist(&RoiImage,1,channels,Mat(),RoiHist,3,histsize,ranges);//原数组区域RoiImage,1个源,需要统计的通道索引为{0,1,2}, 94 //目标直方图RoiHist,3维,每一维的bin数histsize,取值范围为 95 //ranges,实际上计算出的目标矩阵类似一维矩阵。 96 97 98 /*************************************************************************************************************************/ 99 /**** normalize():根据某种范数或者数值范围归一化数组 ****/100 /**** normalize(),参数1表示需要归一化的数组;参数2为归一化后的目的数组;参数3表示输出数值的最小值/最大值或者输出数值的范数;****/101 /**** 参数4表示输出数值的最小值/最大值;参数5表示归一化数组使用的归一化类型,默认值为使用L2范数;参数6为对应元素的掩膜矩阵 ****/102 /**** 默认值为空,即不采用掩膜操作 ****/103 /*************************************************************************************************************************/104 normalize(RoiHist,RoiHist);//使用L2范数将RoiHist直方图原地归一化105 106 vector<Mat> rgb_planes;//这里的vector为向量,向量的数据类型为Mat结构体,向量的长度为3107 split(RoiImage,rgb_planes);//将rgb图分解到rgb_planes各个分量中108 calcHist(&rgb_planes[0],1,0,Mat(),rhist,1,&histsize1,&ranges1);109 normalize(rhist,rhist,0,DRAW_H,NORM_MINMAX);//进行最大最小值归一化110 calcHist(&rgb_planes[1],1,0,Mat(),ghist,1,&histsize1,&ranges1);111 normalize(ghist,ghist,0,DRAW_H,NORM_MINMAX);112 calcHist(&rgb_planes[2],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.width=selectROI.width;120 preselectROI.height=selectROI.height;121 staRoiHist=RoiHist.clone();//第一次选定目标,作为标准模板目标122 }123 else if(nFrame_num>1&&comp==true)124 {125 /*************************************************************************************************************************/126 /**** compareHist():比较2个直方图的相似度 ****/127 /**** compareHist(),参数1为比较相似度的直方图1;参数2为比较相似度的直方图2;参数3为相似度的计算方式。有四种, ****/128 /**** 分别为CV_COMP_CORREL,CV_COMP_CHISQR,CV_COMP_INTERSECT,CV_COMP_BHATTACHARYYA ****/129 /*************************************************************************************************************************/130 double distence=compareHist(staRoiHist,RoiHist,CV_COMP_INTERSECT);//计算后面选定的与这次选定的相似度,使用INTERSECT,值越大越相似131 printf("与第1次选定的图像区域相似度为:%f\n",distence);//数组越大,相似度越大132 133 //显示直方图134 for(int i=1;i<histsize1;i++)135 {136 //画直线中要注意2点,因为图片的原点在左上角,而直方图坐标系的原点在左下角,所以高度值都需要被直方图图纸高度减掉,另外取一维直方图时只能用at运算符137 line(draw,Point(DRAW_BIN_W*(i-1),DRAW_H-cvRound(rhist.at<float>((i-1)))),Point(DRAW_BIN_W*(i),DRAW_H-cvRound(rhist.at<float>(i))),Scalar(255,0,0),2,8,0);138 line(draw,Point(DRAW_BIN_W*(i-1),DRAW_H-cvRound(ghist.at<float>((i-1)))),Point(DRAW_BIN_W*(i),DRAW_H-cvRound(ghist.at<float>(i))),Scalar(0,255,0),2,8,0);139 line(draw,Point(DRAW_BIN_W*(i-1),DRAW_H-cvRound(bhist.at<float>((i-1)))),Point(DRAW_BIN_W*(i),DRAW_H-cvRound(bhist.at<float>(i))),Scalar(0,0,255),2,8,0);140 }141 imshow("rgb_hist",draw);142 draw=Mat::zeros(DRAW_W,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);149 150 //键盘响应151 char c = (char)waitKey(10);152 if( c == 27 )153 break;154 switch(c)155 {156 case 'p'://暂停键157 pause = !pause;158 break;159 default:160 ;161 }162 }//end while;163 return 0;164 }
实验结果:
选定框内的模板用红色框标出,其他待比较的模板用绿色框标出。
模板图像块的简单直方图(rgb分开画的)显示如下:
第一次比较结果图:
第二次比较结果图:
第三次比较结果图(2个框选定的基本重合):
三次比较相似度结果:
可以看出,第三次的框与标准框内图像(即第1次选定的图像区域)的相似度值最大。
0 0
- 使用直方图比较图像的相似度
- 使用直方图比较图像的相似度
- 基于直方图比较的图像相似度计算
- 通过直方图比较图像相似度
- 图像相似度--直方图方法
- 图像相似度比较
- OpenCV 2 学习笔记(21): 使用直方图比较检索相似图像
- 图像相似度检测之直方图相交
- 图像相似度检测之直方图相交
- 图像相似度(测试)--基于直方图特征的图像搜索
- 图像相似度(借鉴)--『原创』+『参考』基于PPC的图像对比程序——使用直方图度量
- 计算图像的梯度及梯度直方图相似度(Matlab代码)
- 图像相似度计算之直方图方法OpenCV实现
- 图像相似度计算之直方图方法OpenCV实现
- 图像相似度计算之直方图方法OpenCV实现
- opencv学习笔记(六)直方图比较图片相似度
- 直方图相似度算法
- opencv2通过比较直方图检索相似图片
- 项目3-用结构体数组作计算
- hadoop常用命令笔记
- openjtag 调试 u-boot
- K-means特征学习
- C++ boost智能指针详解
- 使用直方图比较图像的相似度
- Fedora 16下python连接MySQL环境配置
- iOS-多线程(模拟火车票售票系统)
- 研发与测试
- WebGL相关概念
- 搭建android开发环境
- Linux上构建freeradius
- matlab与python 语言区别总结
- Smarty----变量操作符