《学习OpenCV》练习7-3

来源:互联网 发布:apache监控工具 编辑:程序博客网 时间:2024/05/06 07:52
#include "cv.h"#include "highgui.h"#include "stdio.h"//*****************************************************//画直方图函数:根据输入图像,显示HSV二维直方图//src        :指向输入图像的指针//h_bins     :H分量(hue色调)在直方图里划分的等级//s_bins     :S分量(saturation饱和度)在直方图里划分的等级//scale      :直方图每个矩形的宽度//width      :直方图的宽度//height     :直方图的高度//srcname[]  :用于储存载入源图像窗口的名字//histname[] :用于储存显示直方图图像的窗口的名字//返回值hist  :指向生成的直方图的指针//*****************************************************CvHistogram* myHSVHistogram( IplImage* src, int h_bins, int s_bins, int scale, int width, int height, const char srcname[], const char histname[] ){if (src==NULL || src->nChannels!=3){return NULL;}/*hsv图像初始化*/IplImage* hsv = cvCreateImage( cvGetSize(src), 8, 3 );IplImage* h_plane = cvCreateImage( cvGetSize(src), 8, 1 );IplImage* s_plane = cvCreateImage( cvGetSize(src), 8, 1 );IplImage* v_plane = cvCreateImage( cvGetSize(src), 8, 1 );IplImage* planes[] = { h_plane, s_plane };/*H分量(hue色调)划分等级,S分量(saturation饱和度)划分等级*/int hist_size[] = { h_bins, s_bins }; /*H分量、S分量的变化范围*/float h_ranges[] = { 0, 180 }; float s_ranges[] = { 0, 255 };float* ranges[] = { h_ranges, s_ranges }; /*输入图像转换到HSV颜色空间,并将h、s、v分别分割到各自的单通道图像上*/cvCvtColor( src, hsv, CV_BGR2HSV );cvSplit( hsv, h_plane, s_plane, v_plane, 0 ); /*创建直方图,二维, 每个维度上均分*/CvHistogram * hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1 );/*根据H、S两个平面数据统计planes图像的直方图*/cvCalcHist( planes, hist, 0, 0 ); /*获取直方图统计的最大值,用于动态显示直方图*/float max_value;cvGetMinMaxHistValue( hist, 0, &max_value, 0, 0 );/*设置直方图显示图像的高度、宽度*/IplImage* hist_img = cvCreateImage( cvSize(width,height), 8, 3 );cvZero( hist_img ); /*用来进行HSV到RGB颜色转换的临时单位图像*/IplImage* hsv_color = cvCreateImage(cvSize(1,1),8,3);//单位图像,相当于一个8bit、3通道的像素点IplImage* rgb_color = cvCreateImage(cvSize(1,1),8,3);/*for循环显示矩形*/for (int h=0; h<h_bins; h++)//循环画色调直方图{for (int s=0; s<s_bins; s++)//在每个画色调直方图循环中,循环画饱和度直方图{int i = h*s_bins+s;//直方图中某一矩形的序号(从左到右,由大到小,从0开始)float bin_val = cvQueryHistValue_2D( hist, h, s );//获得某一直方图矩形的数值,即统计数值int intensity = cvRound( bin_val*height/max_value );//四舍五入,计算显示在图像中的矩形高度cvSet2D( hsv_color, 0, 0, cvScalar( h*180.f/h_bins, s*255.f/s_bins, 255, 0));cvCvtColor( hsv_color, rgb_color, CV_HSV2BGR );//为hsv像素点设置颜色(颜色设置使用了归一化),并转换为rgb格式CvScalar color = cvGet2D( rgb_color, 0, 0 );cvRectangle(//画矩形hist_img, cvPoint( i*scale, height ),//起点横坐标为第i个矩形乘以每个矩形宽度,纵坐标为图像高度,即图像底部cvPoint( (i+1)*scale, height-intensity ),//终点横坐标为矩形宽度,纵坐标为图像底减去矩形高度,令矩形显示在底部color,CV_FILLED,//填充矩形8, 0 );}}/*显示源图像与直方图*/cvNamedWindow( srcname, CV_WINDOW_NORMAL );cvShowImage( srcname, src );cvNamedWindow( histname, CV_WINDOW_AUTOSIZE );cvShowImage( histname, hist_img );return hist;}//**************************************************************************//生成EMD的signature函数:输入图像生成signature并输出EMD距离//hist1,hist2          :指向输入比较图像的指针//h_bins,s_bins        :H(hue色调)、S(saturation饱和度)在直方图里划分的等级//返回值emd             :输入两幅比较图像的EMD距离//**************************************************************************float myEMDsignature( CvHistogram* hist1, CvHistogram* hist2, int h_bins, int s_bins ){/*构建一个(h_bins*s_bins)*3的矩阵头*/CvMat* sig1 = NULL;CvMat* sig2 = NULL;int rows = h_bins*s_bins;int cols = 3;sig1 = cvCreateMat( rows, cols, CV_32FC1 );sig2 = cvCreateMat( rows, cols, CV_32FC1 );/*给二维直方图的矩阵赋值,矩阵每一列第一个变量为bin的值,第二第三为为某点坐标(h,s)*/for (int h=0; h<h_bins; h++){for (int s=0; s<s_bins; s++){float bin_val = cvQueryHistValue_2D( hist1, h, s );cvSet2D( sig1, h*s_bins+s, 0, cvScalar(bin_val));cvSet2D( sig1, h*s_bins+s, 1, cvScalar(h));cvSet2D( sig1, h*s_bins+s, 2, cvScalar(s));bin_val = cvQueryHistValue_2D( hist2, h, s );cvSet2D( sig2, h*s_bins+s, 0, cvScalar(bin_val));cvSet2D( sig2, h*s_bins+s, 1, cvScalar(h));cvSet2D( sig2, h*s_bins+s, 2, cvScalar(s));}}/*计算EMD距离并返回*/float emd = cvCalcEMD2( sig1, sig2, CV_DIST_L2 );return emd;}//*****************************************************//主函数//*****************************************************int main(){/*载入图像并检测*/IplImage* image1 = cvLoadImage( "E:\\...\\hand_1.jpg", CV_LOAD_IMAGE_COLOR );      assert(image1 != NULL);      IplImage* image2 = cvLoadImage( "E:\\...\\hand_2.jpg", CV_LOAD_IMAGE_COLOR );      assert(image2 != NULL);       IplImage* image3 = cvLoadImage( "E:\\...\\hand_3.jpg", CV_LOAD_IMAGE_COLOR );      assert(image3 != NULL);/*显示直方图的变量初始化*/int h_bins = 18;//180平均分成18份int s_bins = 8;//256平均分成8份int scale = 8;//每个矩形宽度为8int width = (h_bins*s_bins)*scale;int height = 300;/*创建直方图,并调用我的直方图画图函数画出直方图*/CvHistogram* hist1;      CvHistogram* hist2;      CvHistogram* hist3;      hist1 = myHSVHistogram( image1, h_bins, s_bins, scale, width, height, "hand_1", "hist_image_1" );    hist2 = myHSVHistogram( image2, h_bins, s_bins, scale, width, height, "hand_2", "hist_image_2" );     hist3 = myHSVHistogram( image3, h_bins, s_bins, scale, width, height, "hand_3", "hist_image_3" );  /*对比第一、第二两个直方图,并打印各个比较值*/printf( "h_bins=%d, s_bins=%d时图像1与图像2直方图的比较:\n", h_bins, s_bins );double cpm1 = cvCompareHist( hist1, hist2, CV_COMP_CORREL );      double cpm2 = cvCompareHist( hist1, hist2, CV_COMP_CHISQR );      double cpm3 = cvCompareHist( hist1, hist2, CV_COMP_INTERSECT );      double cpm4 = cvCompareHist( hist1, hist2, CV_COMP_BHATTACHARYYA );float emd = myEMDsignature( hist1, hist2, h_bins, s_bins );printf( "相关:%f \n卡方:%f \n相交:%f \n距离:%f \nEMD :%f \n\n", cpm1, cpm2, cpm3, cpm4, emd );/*对比第一、第三两个直方图,并打印各个比较值*/printf( "h_bins=%d, s_bins=%d时图像1与图像3直方图的比较:\n", h_bins, s_bins );cpm1 = cvCompareHist( hist1, hist3, CV_COMP_CORREL );      cpm2 = cvCompareHist( hist1, hist3, CV_COMP_CHISQR );      cpm3 = cvCompareHist( hist1, hist3, CV_COMP_INTERSECT );      cpm4 = cvCompareHist( hist1, hist3, CV_COMP_BHATTACHARYYA );  emd = myEMDsignature( hist1, hist3, h_bins, s_bins );printf( "相关:%f \n卡方:%f \n相交:%f \n距离:%f \nEMD :%f \n\n", cpm1, cpm2, cpm3, cpm4, emd );/*对比第二、第三两个直方图,并打印各个比较值*/printf( "h_bins=%d, s_bins=%d时图像2与图像3直方图的比较:\n", h_bins, s_bins );cpm1 = cvCompareHist( hist2, hist3, CV_COMP_CORREL );      cpm2 = cvCompareHist( hist2, hist3, CV_COMP_CHISQR );      cpm3 = cvCompareHist( hist2, hist3, CV_COMP_INTERSECT );      cpm4 = cvCompareHist( hist2, hist3, CV_COMP_BHATTACHARYYA ); emd = myEMDsignature( hist2, hist3, h_bins, s_bins );printf( "相关:%f \n卡方:%f \n相交:%f \n距离:%f \nEMD :%f \n\n", cpm1, cpm2, cpm3, cpm4, emd );/*释放内存,销毁图像*/cvWaitKey(0);cvReleaseImage( &image1 );cvReleaseImage( &image2 );cvReleaseImage( &image3 );cvReleaseHist( &hist1 );cvReleaseHist( &hist2 );cvReleaseHist( &hist3 );cvDestroyAllWindows();return 0;}

0 0
原创粉丝点击