【练习7.2】直方图归一化cvNormalizeHist、匹配cvCompareHist及各种匹配方法
2015-05-07 12:36
447 查看
题目要求 |
程序代码 |
结果图片 |
要言妙道 |
使用三种光照条件下的手的图像,利用cvCalcHist来获得直方图
a、获得图像HSV三维直方图
b、匹配三种光照条件下的直方图,使用所有的匹配方法,测试bin的值为2, 8, 16, 32, 256的情况
程序代码:
// OpenCVExerciseTesting.cpp : 定义控制台应用程序的入口点。 // //D:\\Work\\Work_Programming\\Source\\Image\\lena.jpg #include "stdafx.h" #include <cv.h> #include <highgui.h> #include <iostream> #include <opencv2/legacy/legacy.hpp> //#pragma comment(lib, "opencv_legacy2411.lib") using namespace cv; using namespace std; //函数声明-->--->-->--->-->--->-->--->// //<--<--<--<--<--<--<--<--<--函数声明// int _tmain(int argc, _TCHAR* argv[]) { char * soutceFile = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample3.jpg"; IplImage * image_Source = cvLoadImage(soutceFile, CV_LOAD_IMAGE_UNCHANGED); assert(image_Source); IplImage *image_HSV = cvCreateImage(cvGetSize(image_Source), IPL_DEPTH_8U, 3); cvCvtColor(image_Source, image_HSV, CV_BGR2HSV); IplImage * image_h = cvCreateImage(cvGetSize(image_HSV), IPL_DEPTH_8U, 1); IplImage * image_s = cvCreateImage(cvGetSize(image_HSV), IPL_DEPTH_8U, 1); IplImage * image_v = cvCreateImage(cvGetSize(image_HSV), IPL_DEPTH_8U, 1); cvCvtPixToPlane(image_HSV, image_h, image_s, image_v, NULL); CvHistogram * histgram_3D; const int dims = 3; int bin_2 = 2; int bin_16 = 16; int bin_256 = 256; int hist_sizes[dims] = { bin_2, bin_2, bin_2 }; int hist_type = CV_HIST_ARRAY; float h_range[] = { 0, 180 }; float s_range[] = { 0, 255 }; float v_range[] = { 0, 255 }; float *hist_ranges[dims] = { h_range, s_range, v_range }; histgram_3D = cvCreateHist(dims, hist_sizes, hist_type, hist_ranges, 1); IplImage *allImagePlane[dims] = { image_h, image_s, image_v }; cvCalcHist(allImagePlane, histgram_3D); system("pause"); cvWaitKey(); cvReleaseImage(&image_Source); cvDestroyAllWindows(); return 0; } void DrawHistogram(IplImage * image_hist, const CvHistogram * histogram) { }
题目a代码
// OpenCVExerciseTesting.cpp : 定义控制台应用程序的入口点。 // //D:\\Work\\Work_Programming\\Source\\Image\\lena.jpg #include "stdafx.h" #include <cv.h> #include <highgui.h> #include <iostream> #include <opencv2/legacy/legacy.hpp> //#pragma comment(lib, "opencv_legacy2411.lib") using namespace cv; using namespace std; //函数声明-->--->-->--->-->--->-->--->// CvHistogram * Create3DHistogram(const int dims, int bins); void CreateSingleImage(IplImage * image_Src, IplImage **image_r, IplImage **image_g, IplImage **image_b); void DrawHistogram(IplImage ** image_hist, const CvHistogram * histogram, int scaleValue); //<--<--<--<--<--<--<--<--<--函数声明// int _tmain(int argc, _TCHAR* argv[]) { const char * soutceFile_InDoor = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample3.jpg"; const char * soutceFile_OutDoor = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample2.jpg"; const char * soutceFile_OutDoorSun = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample1.jpg"; IplImage * image_Source_Indoor = cvLoadImage(soutceFile_InDoor, CV_LOAD_IMAGE_UNCHANGED); assert(image_Source_Indoor); IplImage * image_Source_Outdoor = cvLoadImage(soutceFile_OutDoor, CV_LOAD_IMAGE_UNCHANGED); assert(image_Source_Outdoor); IplImage * image_Source_OutdoorSun = cvLoadImage(soutceFile_OutDoorSun, CV_LOAD_IMAGE_UNCHANGED); assert(image_Source_OutdoorSun); IplImage * image_r; IplImage * image_g; IplImage * image_b; CvHistogram * histgram_3D_InDoor; CvHistogram * histgram_3D_OutDoor; CvHistogram * histgram_3D_OutDoorSun; double histCompare; const int dims = 3; int bin_N[] = { 2, 8, 16, 32, 256 }; size_t length_bin_N = sizeof(bin_N) / sizeof(bin_N[0]); for (size_t i = 0; i < length_bin_N; ++i) { //室内直方图 CreateSingleImage(image_Source_Indoor, &image_r, &image_g, &image_b); cvCvtPixToPlane(image_Source_Indoor, image_r, image_g, image_b, NULL); IplImage *allImagePlane[3] = { image_r, image_g, image_b }; histgram_3D_InDoor = Create3DHistogram(dims, bin_N[i]); cvCalcHist(allImagePlane, histgram_3D_InDoor); cvNormalizeHist(histgram_3D_InDoor, 1.0); cvReleaseImage(&image_r); cvReleaseImage(&image_g); cvReleaseImage(&image_b); //室外直方图 CreateSingleImage(image_Source_Outdoor, &image_r, &image_g, &image_b); cvCvtPixToPlane(image_Source_Outdoor, image_r, image_g, image_b, NULL); allImagePlane[0] = image_r; allImagePlane[1] = image_g; allImagePlane[2] = image_b; histgram_3D_OutDoor = Create3DHistogram(dims, bin_N[i]); cvCalcHist(allImagePlane, histgram_3D_OutDoor); cvNormalizeHist(histgram_3D_OutDoor, 1.0); cvReleaseImage(&image_r); cvReleaseImage(&image_g); cvReleaseImage(&image_b); //室外阳光直方图 CreateSingleImage(image_Source_OutdoorSun, &image_r, &image_g, &image_b); cvCvtPixToPlane(image_Source_OutdoorSun, image_r, image_g, image_b, NULL); allImagePlane[0] = image_r; allImagePlane[1] = image_g; allImagePlane[2] = image_b; histgram_3D_OutDoorSun = Create3DHistogram(dims, bin_N[i]); cvCalcHist(allImagePlane, histgram_3D_OutDoorSun); cvNormalizeHist(histgram_3D_OutDoorSun, 1.0); cvReleaseImage(&image_r); cvReleaseImage(&image_g); cvReleaseImage(&image_b); if (bin_N[i] == 8) { cvNamedWindow("bin等于8时的室内直方图", CV_WINDOW_AUTOSIZE); cvNamedWindow("bin等于8时的室外直方图", CV_WINDOW_AUTOSIZE); cvNamedWindow("bin等于8时的室外阳光直方图", CV_WINDOW_AUTOSIZE); IplImage *histImage_Indoor; IplImage *histImage_Outdoor; IplImage *histImage_OutdoorSun; DrawHistogram(&histImage_Indoor, histgram_3D_InDoor, 1000); cvShowImage("bin等于8时的室内直方图", histImage_Indoor); cvReleaseImage(&histImage_Indoor); DrawHistogram(&histImage_Outdoor, histgram_3D_OutDoor, 1000); cvShowImage("bin等于8时的室外直方图", histImage_Outdoor); cvReleaseImage(&histImage_Outdoor); DrawHistogram(&histImage_OutdoorSun, histgram_3D_OutDoorSun, 1000); cvShowImage("bin等于8时的室外阳光直方图", histImage_OutdoorSun); cvReleaseImage(&histImage_OutdoorSun); } //输出匹配结果 cout << "-- bin为"<<bin_N[i]<<" -- " << endl; cout << "===============================================================================" << endl; cout << "CV_COMP_CORREL方法:数值越大越匹配,范围:完全匹配:1,完全不匹配:-1,无关联:0" << endl; cout << "-------------------------------------------------------------------------------" << endl; histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoor, CV_COMP_CORREL); cout << "InDoor与OutDoor :" << histCompare << endl; histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoorSun, CV_COMP_CORREL); cout << "InDoor与OutDoorSun :" << histCompare << endl; histCompare = cvCompareHist(histgram_3D_OutDoor, histgram_3D_OutDoorSun, CV_COMP_CORREL); cout << "OutDoor与OutDoorSun:" << histCompare << endl; cout << endl; cout << "CV_COMP_CHISQR方法:数值越小越匹配,范围:0到无穷大" << endl; cout << "-------------------------------------------------------------------------------" << endl; histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoor, CV_COMP_CHISQR); cout << "InDoor与OutDoor :" << histCompare << endl; histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoorSun, CV_COMP_CHISQR); cout << "InDoor与OutDoorSun :" << histCompare << endl; histCompare = cvCompareHist(histgram_3D_OutDoor, histgram_3D_OutDoorSun, CV_COMP_CHISQR); cout << "OutDoor与OutDoorSun:" << histCompare << endl; cout << endl; cout << "CV_COMP_INTERSECT方法:低分代表坏的匹配,范围:如果两个直方图都被归一化到1,则0~1" << endl; cout << "-------------------------------------------------------------------------------" << endl; histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoor, CV_COMP_INTERSECT); cout << "InDoor与OutDoor :" << histCompare << endl; histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoorSun, CV_COMP_INTERSECT); cout << "InDoor与OutDoorSun :" << histCompare << endl; histCompare = cvCompareHist(histgram_3D_OutDoor, histgram_3D_OutDoorSun, CV_COMP_INTERSECT); cout << "OutDoor与OutDoorSun:" << histCompare << endl; cout << endl; cout << "CV_COMP_BHATTACHARYYA方法:低分代表好的匹配,范围:0~1" << endl; cout << "-------------------------------------------------------------------------------" << endl; histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoor, CV_COMP_BHATTACHARYYA); cout << "InDoor与OutDoor :" << histCompare << endl; histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoorSun, CV_COMP_BHATTACHARYYA); cout << "InDoor与OutDoorSun :" << histCompare << endl; histCompare = cvCompareHist(histgram_3D_OutDoor, histgram_3D_OutDoorSun, CV_COMP_BHATTACHARYYA); cout << "OutDoor与OutDoorSun:" << histCompare << endl; cout << endl; cout << endl; cout << endl; cvReleaseHist(&histgram_3D_InDoor); cvReleaseHist(&histgram_3D_OutDoor); cvReleaseHist(&histgram_3D_OutDoorSun); } //system("pause"); cvWaitKey(); cvReleaseImage(&image_Source_Indoor); cvReleaseImage(&image_Source_Outdoor); cvReleaseImage(&image_Source_OutdoorSun); cvDestroyAllWindows(); return 0; } CvHistogram * Create3DHistogram(const int dims, int bins) { int hist_sizes[] = { bins, bins, bins }; int hist_type = CV_HIST_ARRAY; float r_range[] = { 0, 255 }; float g_range[] = { 0, 255 }; float b_range[] = { 0, 255 }; float *hist_ranges[] = { r_range, g_range, b_range }; return cvCreateHist(dims, hist_sizes, hist_type, hist_ranges, 1); } void CreateSingleImage(IplImage * image_Src, IplImage **image_r, IplImage **image_g, IplImage **image_b) { IplImage * image_temp = cvCreateImage(cvGetSize(image_Src), IPL_DEPTH_8U, 1); //image_r = &image_temp; //如果用上面这行这种方式,编译通过,但运行崩溃,本函数结束后image_r便被释放, //因为image_temp只是一个指针变量,占用四个字节的局部变量,对它取地址即&image_temp只是这个局部指针变量的地址,函数结束后自然释放掉 //但是,将使用下面这行:将image_temp指针变量所保存的地址赋值给“*image_r”,这个地址是从cvCreateImagere中turn出来的,自然不会随函数结束而释放 *image_r = image_temp; *image_g = cvCloneImage(image_temp); *image_b = cvCloneImage(image_temp); cvZero(*image_r); cvZero(*image_g); cvZero(*image_b); } //目前只实现绘制三维直方图 void DrawHistogram(IplImage ** image_hist, const CvHistogram * histogram,int scaleValue) { //直方图:横坐标表示各个bin,纵坐标表示各个bin归一化后的值 int hist_dims = histogram->mat.dims; int bin_size1, bin_size2, bin_size3; if (hist_dims == 3) { bin_size1 = histogram->mat.dim[0].size; bin_size2 = histogram->mat.dim[1].size; bin_size3 = histogram->mat.dim[2].size; } else { return; } int bin_count = bin_size1*bin_size2*bin_size3; float max_temp; cvGetMinMaxHistValue(histogram, NULL, &max_temp); int max_value = (int)(max_temp*scaleValue) + 1; CvSize hist_imageSize = cvSize(bin_count, max_value); *image_hist = cvCreateImage(hist_imageSize, IPL_DEPTH_8U, 1); (*image_hist)->origin = 1; cvZero(*image_hist); int x; int value; for (int r = 0; r < bin_size1; ++r) { for (int g = 0; g < bin_size2; ++g) { for (int b = 0; b < bin_size3; ++b) { x = r*(bin_size1*bin_size2) + g*bin_size2 + b; value = (int)(cvQueryHistValue_3D(histogram, r, g, b)*scaleValue); /* if (value == 0) { value = 10; }*/ cvRectangle(*image_hist, cvPoint(x, 0), cvPoint(x, value), cvScalar(255)); } } } }
结果图片:
①二维直方图bin的多少是各维度bin的乘积,以h和s二维直方图来说,如果h的bin的个数为30,s的bin的个数为32,则,二维直方图的bin的个数为30×32,访问的时候要使用cvQueryHistValue_2D
②由于需要匹配“各种光线”下的直方图,所以,代码中将BGR图像转成了HSV图像 cvCvtColor(image_Source, image_HSV, CV_BGR2HSV);
③书中Example 7-1统计的是HS直方图,即色调和饱和度,没有统计亮度,针对三种光线下的手的图像,如果统计亮度即V的直方图,三种环境下的匹配结果值肯定不匹配度很高。这点在230页有专门的讲解,为什么只选取HS两维而避开V维,是这个道理。
④为什么说是手的肤色直方图,从图7-6的表述来看,所谓肤色直方图即肤色所在图片的直方图,在英文版更看得出这个意思。
⑤一般情况下在对比直方图之前,都应该自行进行归一化操作,因为如果不归一化,像直方图相交等概念就没有任何意义(即使运行)
相关文章推荐
- 直方图匹配方法
- 直方图匹配方法
- 【练习7.1】cvCreateHist创建直方图、cvCalcHist计算直方图、cvQueryHistValue_1D访问直方图及右左法则
- 直方图匹配方法
- 练习:利用颜色直方图匹配算法实现图像中目标的识别
- 【Python OpenCV】图像直方图 calcHist方法 equalizeHist方法
- 直方图匹配方法
- 练习:利用颜色直方图匹配算法实现图像中目标的识别
- 练习1-13 编写一个程序,打印输入中单词长度的直方图(水平)(方法2)
- 数组练习:各种数组方法的使用&&事件练习:封装兼容性添加、删除事件的函数&&星级评分系统
- 常用直方图匹配方法
- 《学习OpenCV》第七章直方图(练习7.2)
- 直方图对比,各种方法的范围
- 数组练习:各种数组方法的使用
- OpenCV直方图计算匹配方法详解calcHist
- 【java】:java中关于String,各种集合的方法的练习笔记
- python字典的各种创建方法
- 方法练习
- 概述各种上传漏洞的利用方法
- 各种数据库查询前几条数据的方法