16识别手势(EMD)
尝试识别手势。实现例15功能,但是利用EMD匹配策略,本例仅对Compare_Gesture_Hist()函数做了适当修改,具体代码如下:
void Compare_Gesture_Hist(IplImage *sobel1, IplImage *sobel2, IplImage *test, IplImage** canny, IplImage* hist_img)
{
//建立直方图
CvHistogram *hist_model1, *hist_model2, *hist_test;
int bins = 20;
int hist_size[] = { bins }; //对应维数包含bins个数的数组
float range[] = { -CV_PI / 2, CV_PI / 2 };
float* ranges[] = { range }; //划分范围数对, ****均匀bin,range只要最大最小边界
//创建直方图 (维数,对应维数bins个数,密集矩阵方式存储,划分范围数对,均匀直方图)
hist_model1 = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1);
hist_model2 = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1);
hist_test = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1);
IplImage *planes1[] = { sobel1 };
IplImage *planes2[] = { sobel2 };
IplImage *planes3[] = { test };
cvCalcHist(planes1, hist_model1, 0, canny[0]); //计算直方图(图像,直方图结构,不累加,掩码)
cvCalcHist(planes2, hist_model2, 0, canny[1]); //计算直方图(图像,直方图结构,不累加,掩码)
cvCalcHist(planes3, hist_test, 0, canny[2]); //计算直方图(图像,直方图结构,不累加,掩码)
cvNormalizeHist(hist_model1, 1.0); //直方图归一化
cvNormalizeHist(hist_model2, 1.0); //直方图归一化
cvNormalizeHist(hist_test, 1.0); //直方图归一化
//EMD
CvMat *sig1, *sig2, *sig_test;
int numrows = bins;
sig1 = cvCreateMat(numrows, 2, CV_32FC1); //numrows行 2列 矩阵
sig2 = cvCreateMat(numrows, 2, CV_32FC1);
sig_test = cvCreateMat(numrows, 2, CV_32FC1);
for (int h = 0; h < bins; h++)
{
float bin_val = 0.0;
bin_val = cvQueryHistValue_1D(hist_model1, h);
//h:行数 s_bins:总列数(行长度)s:列数 h*s_bins+s 当前bin对应的sig行数
cvSet2D(sig1, h, 0, cvScalar(bin_val));
cvSet2D(sig1, h, 1, cvScalar(h));
bin_val = cvQueryHistValue_1D(hist_model2, h);
//h:行数 s_bins:总列数(行长度)s:列数 h*s_bins+s 当前bin对应的sig行数
cvSet2D(sig2, h, 0, cvScalar(bin_val));
cvSet2D(sig2, h, 1, cvScalar(h));
bin_val = cvQueryHistValue_1D(hist_test, h);
//h:行数 s_bins:总列数(行长度)s:列数 h*s_bins+s 当前bin对应的sig行数
cvSet2D(sig_test, h, 0, cvScalar(bin_val));
cvSet2D(sig_test, h, 1, cvScalar(h));
}
float emd1 = cvCalcEMD2(sig1, sig_test, CV_DIST_L2);
float emd2 = cvCalcEMD2(sig2, sig_test, CV_DIST_L2);
printf("EMD距离1:%f; \n", emd1);
printf("EMD距离2:%f; \n", emd2);
if ((emd1 <= 1) && (emd2 >= 4))
{
cvDrawRect(hist_img, cvPoint(100, 100), cvPoint(200, 200), cvScalar(255, 0, 0), CV_FILLED, 8);
}
if ((emd1 >= 1.7) && (emd2 <= 3.4))
{
cvDrawRect(hist_img, cvPoint(100, 100), cvPoint(200, 200), cvScalar(0, 0, 255), CV_FILLED, 8);
}
printf("\n");
cout << endl;
比较直方图
//for (int j = 0; j < 4; j++)
//{
// double value1 = cvCompareHist(hist_test, hist_model1, j); //相关方式比较
// double value2 = cvCompareHist(hist_test, hist_model2, j); //相关方式比较
// //if (j == 0)
// //{
// // std::printf(" Hist_test & Hist_model1 ,CV_COMP_CORREL: %lf;\n", value1);
// // std::printf(" Hist_test & Hist_model2 ,CV_COMP_CORREL: %lf;\n", value2);
// //}
// if (j == 1)
// {
// std::printf(" Hist_test & Hist_model1 ,CV_COMP_CHISQR: %lf;\n", value1);
// std::printf(" Hist_test & Hist_model2 ,CV_COMP_CHISQR: %lf;\n", value2);
// if ((value1 <= 0.25) && (value2 >= 0.55))
// {
// cvDrawRect(hist_img, cvPoint(100, 100), cvPoint(200, 200), cvScalar(255, 0, 0), CV_FILLED, 8);
// }
// if ((value1 >= 0.45) && (value2 <= 0.4))
// {
// cvDrawRect(hist_img, cvPoint(100, 100), cvPoint(200, 200), cvScalar(0, 0, 255), CV_FILLED, 8);
// }
// }
// //if (j == 2)
// //{
// // std::printf(" Hist_test & Hist_model1 ,CV_COMP_INTERSECT: %lf;\n", value1);
// // std::printf(" Hist_test & Hist_model2 ,CV_COMP_INTERSECT: %lf;\n", value2);
// //}
// //if (j == 3)
// //{
// // std::printf(" Hist_test & Hist_model1 ,CV_CCOMP_BHATTACHARYYA: %lf;\n", value1);
// // std::printf(" Hist_test & Hist_model2 ,CV_CCOMP_BHATTACHARYYA: %lf;\n", value2);
// //}
// std::printf("\n");
//}
结果如下: