【练习7.3】从直方图创建signature、计算两个直方图的EMD距离

提纲
题目要求
程序代码
结果图片
要言妙道

题目要求:

收集三种光照条件下的手的直方图,计算它们之间的EMD距离

程序代码:

  1 // OpenCVExerciseTesting.cpp : 定义控制台应用程序的入口点。
  2 //
  3 //D:\\Work\\Work_Programming\\Source\\Image\\lena.jpg
  4
  5 #include "stdafx.h"
  6 #include <cv.h>
  7 #include <highgui.h>
  8 #include <iostream>
  9
 10 #include <opencv2/legacy/legacy.hpp>
 11 //#pragma comment(lib, "opencv_legacy2411.lib")
 12
 13 using namespace cv;
 14 using namespace std;
 15
 16 //函数声明-->--->-->--->-->--->-->--->//
 17
 18 CvHistogram * Create3DHistogram(const int dims, int bins);
 19 void CreateSingleImage(IplImage * image_Src, IplImage **image_r, IplImage **image_g, IplImage **image_b);
 20 void DrawHistogram(IplImage ** image_hist, const CvHistogram * histogram, int scaleValue);
 21 void CreateSignatureFromHistogram(const CvHistogram * histgogram, CvMat ** signature);
 22
 23 //<--<--<--<--<--<--<--<--<--函数声明//
 24
 25 int _tmain(int argc, _TCHAR* argv[])
 26 {
 27     const char * soutceFile_InDoor = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample3.jpg";
 28     const char * soutceFile_OutDoor = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample2.jpg";
 29     const char * soutceFile_OutDoorSun = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample1.jpg";
 30
 31     IplImage * image_Source_Indoor = cvLoadImage(soutceFile_InDoor, CV_LOAD_IMAGE_UNCHANGED);
 32     assert(image_Source_Indoor);
 33     IplImage * image_Source_Outdoor = cvLoadImage(soutceFile_OutDoor, CV_LOAD_IMAGE_UNCHANGED);
 34     assert(image_Source_Outdoor);
 35     IplImage * image_Source_OutdoorSun = cvLoadImage(soutceFile_OutDoorSun, CV_LOAD_IMAGE_UNCHANGED);
 36     assert(image_Source_OutdoorSun);
 37
 38     IplImage * image_r;
 39     IplImage * image_g;
 40     IplImage * image_b;
 41
 42     CvHistogram * histgram_3D_InDoor;
 43     CvHistogram * histgram_3D_OutDoor;
 44     CvHistogram * histgram_3D_OutDoorSun;
 45     CvMat * sig_Indoor, *sig_Outdoor, *sig_OutdoorSun;
 46
 47     double emd_result;
 48
 49     const int dims = 3;
 50     int bin_N[] = { 8 }; //本题只计算bin值为8的情况
 51     size_t length_bin_N = sizeof(bin_N) / sizeof(bin_N[0]);
 52
 53     for (size_t i = 0; i < length_bin_N; ++i)
 54     {
 55         //室内直方图
 56         CreateSingleImage(image_Source_Indoor, &image_r, &image_g, &image_b);
 57         cvCvtPixToPlane(image_Source_Indoor, image_r, image_g, image_b, NULL);
 58         IplImage *allImagePlane[3] = { image_r, image_g, image_b };
 59
 60         histgram_3D_InDoor = Create3DHistogram(dims, bin_N[i]);
 61         cvCalcHist(allImagePlane, histgram_3D_InDoor);
 62         //cvNormalizeHist(histgram_3D_InDoor, 1.0);
 63         CreateSignatureFromHistogram(histgram_3D_InDoor, &sig_Indoor);
 64
 65         cvReleaseImage(&image_r);
 66         cvReleaseImage(&image_g);
 67         cvReleaseImage(&image_b);
 68
 69         //室外直方图
 70         CreateSingleImage(image_Source_Outdoor, &image_r, &image_g, &image_b);
 71         cvCvtPixToPlane(image_Source_Outdoor, image_r, image_g, image_b, NULL);
 72         allImagePlane[0] = image_r;
 73         allImagePlane[1] = image_g;
 74         allImagePlane[2] = image_b;
 75
 76         histgram_3D_OutDoor = Create3DHistogram(dims, bin_N[i]);
 77         cvCalcHist(allImagePlane, histgram_3D_OutDoor);
 78         //cvNormalizeHist(histgram_3D_OutDoor, 1.0);
 79         CreateSignatureFromHistogram(histgram_3D_OutDoor, &sig_Outdoor);
 80
 81         cvReleaseImage(&image_r);
 82         cvReleaseImage(&image_g);
 83         cvReleaseImage(&image_b);
 84
 85         //室外阳光直方图
 86         CreateSingleImage(image_Source_OutdoorSun, &image_r, &image_g, &image_b);
 87         cvCvtPixToPlane(image_Source_OutdoorSun, image_r, image_g, image_b, NULL);
 88         allImagePlane[0] = image_r;
 89         allImagePlane[1] = image_g;
 90         allImagePlane[2] = image_b;
 91
 92         histgram_3D_OutDoorSun = Create3DHistogram(dims, bin_N[i]);
 93         cvCalcHist(allImagePlane, histgram_3D_OutDoorSun);
 94         //cvNormalizeHist(histgram_3D_OutDoorSun, 1.0);
 95         CreateSignatureFromHistogram(histgram_3D_OutDoorSun, &sig_OutdoorSun);
 96
 97         cvReleaseImage(&image_r);
 98         cvReleaseImage(&image_g);
 99         cvReleaseImage(&image_b);
100
101         cout << "=============直方图EMD距离:0表示最精确的匹配=============" << endl << endl;
102         cout << "-------------Indoor和Outdoor直方图EMD距离-------------" << endl;
103         emd_result = cvCalcEMD2(sig_Indoor, sig_Outdoor, CV_DIST_L2);
104         cout << emd_result << endl;
105
106         cout << "-------------Indoor和OutdoorSun直方图EMD距离-------------" << endl;
107         emd_result = cvCalcEMD2(sig_Indoor, sig_OutdoorSun, CV_DIST_L2);
108         cout << emd_result << endl;
109
110         cout << "-------------Outdoor和OutdoorSun直方图EMD距离-------------" << endl;
111         emd_result = cvCalcEMD2(sig_OutdoorSun, sig_Outdoor, CV_DIST_L2);
112         cout << emd_result << endl;
113         emd_result = cvCalcEMD2(sig_Outdoor, sig_OutdoorSun, CV_DIST_L2);
114         cout << emd_result<<"  可见cvCalcEMD2参数signature顺序无关,不影响结果" << endl;
115
116         cvReleaseMat(&sig_Indoor);
117         cvReleaseMat(&sig_Outdoor);
118         cvReleaseMat(&sig_OutdoorSun);
119
120         cvReleaseHist(&histgram_3D_InDoor);
121         cvReleaseHist(&histgram_3D_OutDoor);
122         cvReleaseHist(&histgram_3D_OutDoorSun);
123     }
124
125     system("pause");
126
127     cvWaitKey();
128     cvReleaseImage(&image_Source_Indoor);
129     cvReleaseImage(&image_Source_Outdoor);
130     cvReleaseImage(&image_Source_OutdoorSun);
131
132     cvDestroyAllWindows();
133
134     return 0;
135 }
136
137 CvHistogram * Create3DHistogram(const int dims, int bins)
138 {
139     int hist_sizes[] = { bins, bins, bins };
140     int hist_type = CV_HIST_ARRAY;
141     float r_range[] = { 0, 255 };
142     float g_range[] = { 0, 255 };
143     float b_range[] = { 0, 255 };
144     float *hist_ranges[] = { r_range, g_range, b_range };
145
146     return cvCreateHist(dims, hist_sizes, hist_type, hist_ranges, 1);
147 }
148
149 void CreateSingleImage(IplImage * image_Src, IplImage **image_r, IplImage **image_g, IplImage **image_b)
150 {
151     IplImage * image_temp = cvCreateImage(cvGetSize(image_Src), IPL_DEPTH_8U, 1);
152     //image_r = &image_temp;
153     //如果用上面这行这种方式,编译通过,但运行崩溃,本函数结束后image_r便被释放,
154     //因为image_temp只是一个指针变量,占用四个字节的局部变量,对它取地址即&image_temp只是这个局部指针变量的地址,函数结束后自然释放掉
155     //但是,将使用下面这行:将image_temp指针变量所保存的地址赋值给“*image_r”,这个地址是从cvCreateImagere中turn出来的,自然不会随函数结束而释放
156     *image_r = image_temp;
157
158     *image_g = cvCloneImage(image_temp);
159     *image_b = cvCloneImage(image_temp);
160     cvZero(*image_r);
161     cvZero(*image_g);
162     cvZero(*image_b);
163 }
164
165 //目前只实现绘制三维直方图
166 void DrawHistogram(IplImage ** image_hist, const CvHistogram * histogram,int scaleValue)
167 {
168     //直方图:横坐标表示各个bin,纵坐标表示各个bin归一化后的值
169     int hist_dims = histogram->mat.dims;
170
171     int bin_size1, bin_size2, bin_size3;
172
173     if (hist_dims == 3)
174     {
175         bin_size1 = histogram->mat.dim[0].size;
176         bin_size2 = histogram->mat.dim[1].size;
177         bin_size3 = histogram->mat.dim[2].size;
178     }
179     else
180     {
181         return;
182     }
183
184     int bin_count = bin_size1*bin_size2*bin_size3;
185     float max_temp;
186     cvGetMinMaxHistValue(histogram, NULL, &max_temp);
187     int max_value = (int)(max_temp*scaleValue) + 1;
188     CvSize hist_imageSize = cvSize(bin_count, max_value);
189     *image_hist = cvCreateImage(hist_imageSize, IPL_DEPTH_8U, 1);
190     (*image_hist)->origin = 1;
191     cvZero(*image_hist);
192
193     int x;
194     int value;
195
196     for (int r = 0; r < bin_size1; ++r)
197     {
198         for (int g = 0; g < bin_size2; ++g)
199         {
200             for (int b = 0; b < bin_size3; ++b)
201             {
202                 x = r*(bin_size1*bin_size2) + g*bin_size2 + b;
203                 value = (int)(cvQueryHistValue_3D(histogram, r, g, b)*scaleValue);
204         /*        if (value == 0)
205                 {
206                     value = 10;
207                 }*/
208                 cvRectangle(*image_hist, cvPoint(x, 0), cvPoint(x, value), cvScalar(255));
209             }
210         }
211     }
212 }
213
214 void CreateSignatureFromHistogram(const CvHistogram * histgogram,CvMat ** signature)
215 {
216     int hist_dims = histgogram->mat.dims;
217
218     int bin_size1, bin_size2, bin_size3;
219
220     //只实现从三维直方图的创建
221     if (hist_dims == 3)
222     {
223         bin_size1 = histgogram->mat.dim[0].size;
224         bin_size2 = histgogram->mat.dim[1].size;
225         bin_size3 = histgogram->mat.dim[2].size;
226     }
227     else
228     {
229         return;
230     }
231
232     int numrows = bin_size1*bin_size2*bin_size3;
233     *signature = cvCreateMat(numrows, 4, CV_32FC1);
234
235     float bin_value;
236     int idx;
237     for (int r = 0; r < bin_size1; ++r)
238     {
239         for (int g = 0; g < bin_size2; ++g)
240         {
241             for (int b = 0; b < bin_size3; ++b)
242             {
243                 idx = r*(bin_size1*bin_size2) + g*bin_size2 + b;
244                 bin_value = cvQueryHistValue_3D(histgogram, r, g, b);
245                 cvSet2D(*signature, idx, 0, cvScalar(bin_value));
246                 cvSet2D(*signature, idx, 1, cvScalar(r));
247                 cvSet2D(*signature, idx, 2, cvScalar(g));
248                 cvSet2D(*signature, idx, 3, cvScalar(b));
249             }
250         }
251     }
252 }

结果图片:

要言妙道:

①EMD用来度量两个分布之间的相似性

时间: 2024-11-01 16:14:00

【练习7.3】从直方图创建signature、计算两个直方图的EMD距离的相关文章

PHP MYSQL 搜索周边坐标,并计算两个点之间的距离

搜索附近地点,例如,坐标(39.91, 116.37)附近500米内的人,首先算出“给定坐标附近500米”这个范围的坐标范围. 虽然它是个圆,但我们可以先求出该圆的外接正方形,然后拿正方形的经纬度范围去搜索数据库.红色部分为要求的搜索范围,绿色部分为实际搜索范围. /** * 获取周围坐标 * Enter description here ... * @param unknown_type $lng 固定坐标经度 * @param unknown_type $lat 固定坐标纬度 * @para

计算两个经纬度之间的距离

//计算两个经纬度之间的距离 /** * 计算两点地理坐标之间的距离 * @param Decimal $longitude1 起点经度 * @param Decimal $latitude1 起点纬度 * @param Decimal $longitude2 终点经度 * @param Decimal $latitude2 终点纬度 * @param Int $unit 单位 1:米 2:公里 * @param Int $decimal 精度 保留小数位数 * @return Decimal

IOS 计算两个经纬度之间的距离

一 丶 -(double)distanceBetweenOrderBy:(double) lat1 :(double) lat2 :(double) lng1 :(double) lng2{ CLLocation *curLocation = [[CLLocation alloc] initWithLatitude:lat1 longitude:lng1]; CLLocation *otherLocation = [[CLLocation alloc] initWithLatitude:lat2

计算两个经纬度之间的距离(python算法)

EARTH_REDIUS = 6378.137 def rad(d): return d * pi / 180.0 def getDistance(lat1, lng1, lat2, lng2): radLat1 = rad(lat1) radLat2 = rad(lat2) a = radLat1 - radLat2 b = rad(lng1) - rad(lng2) s = 2 * math.asin(math.sqrt(math.pow(sin(a/2), 2) + cos(radLat1

PHP计算两个坐标之间的距离

<?php /** * 计算两点之间的距离 * @param $lng1 经度1 * @param $lat1 纬度1 * @param $lng2 经度2 * @param $lat2 纬度2 * @param int $unit m,km * @param int $decimal 位数 * @return float */ function getDistance($lng1, $lat1, $lng2, $lat2, $unit = 2, $decimal = 2) { $EARTH_R

计算两个GPS坐标的距离

场景:已知两个GPS点的经纬度坐标信息.计算两点的距离. 1. 距离/纬度关系 GPS: 22.514519,113.380301 GPS: 22.511962,113.380301 距离: 284.6439379583341   jl_wd=284.6439379583341/(22.51451-22.511962) = 111712.69150641055729984301412873 (米/度) 2. 距离/经度关系 GPS: 22.514866, 113.388444 GPS: 22.5

爬虫计算两张验证图片的距离(情况一)

一.图 这两张图片的计算距离 二.计算代码 import cv2 import numpy as np def get_image_deviation(): ''' 计算slideImg.png 与 slideImg.png 位移的距离 ''' print(sys.path) slideImg = cv2.imread('图片路径1') bgImg = cv2.imread(f'图片路径2') result = cv2.matchTemplate(slideImg, bgImg, cv2.TM_

Matlab计算两集合间的海明距离

一.问题描述 B1[1 2 3 4 5 6 7 8 9] B2[12 13 14 21 31 41 51  1 1 81 1 1] 两个十进制矩阵,行数不一样,分别是n1和n2,列数必须一致,为nwords,输出的矩阵Dh是[n1,n2],这和求两句真的欧氏距离一样的. 输出[1 1] = 1和12海明+2和13海明 + 3和14海明,[1 2] = 1和21 + 2和31 + 3和41,也就是说[i j]是B1第i行和B2第j行的海明距离. 二.问题分析 1和12 21 51 81分别求海明距

百度地图计算两个点之间的距离

BMKMapPoint point1 = BMKMapPointForCoordinate(CLLocationCoordinate2DMake(38.085178, 114.502358)); BMKMapPoint point2 = BMKMapPointForCoordinate(CLLocationCoordinate2DMake(38.085171, 114.502312)); CLLocationDistance distance = BMKMetersBetweenMapPoint