compareHist函数 例子
生活随笔
收集整理的這篇文章主要介紹了
compareHist函数 例子
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
功能是:打開攝像頭,鼠標選定一個框,框內圖像作為標準圖像,計算出其直方圖并顯示出來;然后繼續鼠標選定框,該框內的圖像的直方圖與標準圖像的進行相似度計算,計算結果在終端輸出,數值越大表示相似度越大。
opencv代碼:
// hist_test.cpp : 定義控制臺應用程序的入口點。 //#include "stdafx.h" #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> #include <stdio.h>using namespace cv; using namespace std;int nFrame_num=0; bool pause=false; bool tracking=false; Rect preselectROI,selectROI;//用于存放手選的矩形 bool comp=true;Mat rhist,ghist,bhist; int channels[]={0,1,2}; //const int histsize[]={256,256,256}; const int histsize[]={16,16,16}; const int histsize1=16; float rranges[]={0,255}; float granges[]={0,255}; float branges[]={0,255}; float range[]={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(event==CV_EVENT_LBUTTONDOWN){selectROI.x=x;selectROI.y=y;tracking=false;}else if(event==CV_EVENT_LBUTTONUP){selectROI.width=x-selectROI.x;selectROI.height=y-selectROI.y;tracking=true;comp=true;nFrame_num++;//選定后才算真正意義上的第一幀if(nFrame_num>=10)nFrame_num=10;//防止nFrame_num溢出} }int main(int argc, const char* argv[]) {Mat frame,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);/****打開攝像頭****/VideoCapture cam(0);if(!cam.isOpened())return -1;/****鼠標捕捉****/namedWindow("camera",1);namedWindow("rgb_hist",1);setMouseCallback("camera",onMouse,0);//這里用的是面向對象的思想,只要有鼠標動作就會調用鼠標響應函數while(1){if(!pause)//暫停按鈕只需控制視頻的讀取{ cam>>frame;if(frame.empty())break;//break此處跳出的是while語句,一般是跳出for或while語句,不要理解為跳出if語句}/* if(1==nFrame_num){}*/if(tracking){Mat RoiImage(frame,selectROI);/*************************************************************************************************************************//**** calcHist():計算圖像塊的直方圖矩陣 ****//****calcHist(),第1個參數為原數組區域列表;第二個參數為有計算幾個原數組;參數3為需要統計的通道索引數;參數4為操作掩碼****//****第5個參數為存放目標直方圖矩陣;參數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,取值范圍為//ranges,實際上計算出的目標矩陣類似一維矩陣。/*************************************************************************************************************************//**** normalize():根據某種范數或者數值范圍歸一化數組 ****//**** normalize(),參數1表示需要歸一化的數組;參數2為歸一化后的目的數組;參數3表示輸出數值的最小值/最大值或者輸出數值的范數;****//**** 參數4表示輸出數值的最小值/最大值;參數5表示歸一化數組使用的歸一化類型,默認值為使用L2范數;參數6為對應元素的掩膜矩陣 ****//**** 默認值為空,即不采用掩膜操作 ****//*************************************************************************************************************************/normalize(RoiHist,RoiHist);//使用L2范數將RoiHist直方圖原地歸一化vector<Mat> rgb_planes;//這里的vector為向量,向量的數據類型為Mat結構體,向量的長度為3split(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,&histsize1,&ranges1);normalize(ghist,ghist,0,DRAW_H,NORM_MINMAX);calcHist(&rgb_planes[2],1,0,Mat(),bhist,1,&histsize1,&ranges1);normalize(bhist,bhist,0,DRAW_H,NORM_MINMAX);if(nFrame_num==1){ // preselectROI=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():比較2個直方圖的相似度 ****//**** 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("與第1次選定的圖像區域相似度為:%f\n",distence);//數組越大,相似度越大//顯示直方圖for(int i=1;i<histsize1;i++){//畫直線中要注意2點,因為圖片的原點在左上角,而直方圖坐標系的原點在左下角,所以高度值都需要被直方圖圖紙高度減掉,另外取一維直方圖時只能用at運算符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);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);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);}imshow("rgb_hist",draw);draw=Mat::zeros(DRAW_W,DRAW_H,CV_8UC3);//每畫完一次直方圖后都進行一次清0操作comp=false;}rectangle(frame,selectROI,Scalar(0,255,0),2,8);//手動選定一次就顯示一次}//end trackingrectangle(frame,preselectROI,Scalar(0,0,255),5,8);//初始的選定目標一直不變imshow("camera",frame);//鍵盤響應char c = (char)waitKey(10);if( c == 27 )break;switch(c){case 'p'://暫停鍵pause = !pause;break;default:;}}//end while;return 0; }
總結
以上是生活随笔為你收集整理的compareHist函数 例子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: compareHist函数
- 下一篇: EqualizeHist函数