第七章 学习OpenCV(9)
运行结果如下图:
根据输入的手势图像,在每一个区域求取其梯度方向,计算出梯度方向直方图,并可视化。具体代码如下:
#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
using namespace std;
void Create_Hist_1D(IplImage* src, IplImage* canny, IplImage* sobel, IplImage* hist_img);
void Compare_Gesture_Hist(IplImage *sobel1, IplImage *sobel2, IplImage *test, IplImage** canny);
int main(int argc, char* argv[])
{
IplImage *src1, *Isobel1, *Ihist1; //图像
IplImage *src2, *Isobel2, *Ihist2; //图像
IplImage *src3, *Isobel3, *Ihist3; //图像
IplImage *Icanny[3];
if (!(src1 = cvLoadImage("D:\\Template\\OpenCV\\Template57_HOG_Compare\\Debug\\Imask_1.jpg", 0)))
return -1;
if (!(src2 = cvLoadImage("D:\\Template\\OpenCV\\Template57_HOG_Compare\\Debug\\Imask_2.jpg", 0)))
return -2;
if (!(src3 = cvLoadImage("D:\\Template\\OpenCV\\Template57_HOG_Compare\\Debug\\DST.jpg", 0)))
return -3;
Icanny[0] = cvCreateImage(cvSize(src1->width, src1->height), 8, 1); //canny图像 深度8
Icanny[1] = cvCreateImage(cvSize(src2->width, src2->height), 8, 1);
Icanny[2] = cvCreateImage(cvSize(src3->width, src3->height), 8, 1);
Isobel1 = cvCreateImage(cvSize(src1->width, src1->height), 32, 1);
Isobel2 = cvCreateImage(cvSize(src2->width, src2->height), 32, 1);
Isobel3 = cvCreateImage(cvSize(src3->width, src3->height), 32, 1);
Ihist1 = cvCreateImage(cvSize(320, 300), 8, 3); //320*320
Ihist2 = cvCreateImage(cvSize(320, 300), 8, 3); //320*320
Ihist3 = cvCreateImage(cvSize(320, 300), 8, 3); //320*320
Create_Hist_1D(src1, Icanny[0], Isobel1, Ihist1);
Create_Hist_1D(src2, Icanny[1], Isobel2, Ihist2);
Create_Hist_1D(src3, Icanny[2], Isobel3, Ihist3);
Compare_Gesture_Hist(Isobel1, Isobel2, Isobel3, Icanny);
cvNamedWindow("SRC1", 1);
cvNamedWindow("SRC2", 2);
cvNamedWindow("SRC3", 3);
//cvNamedWindow("Canny_1", 1);
//cvNamedWindow("Canny_2", 1);
//cvNamedWindow("Canny_3", 1);
cvNamedWindow("SOBEL_1", 1);
cvNamedWindow("SOBEL_2", 1);
cvNamedWindow("SOBEL_3", 1);
cvNamedWindow("Hist_1", 1);
cvNamedWindow("Hist_2", 1);
cvNamedWindow("Hist_3", 1);
cvShowImage("SRC1", src1);
cvShowImage("SRC2", src2);
cvShowImage("SRC3", src3);
//cvShowImage("Canny_1", Icanny[0]);
//cvShowImage("Canny_2", Icanny[1]);
//cvShowImage("Canny_3", Icanny[2]);
cvShowImage("SOBEL_1", Isobel1);
cvShowImage("SOBEL_2", Isobel2);
cvShowImage("SOBEL_3", Isobel3);
cvShowImage("Hist_1", Ihist1);
cvShowImage("Hist_2", Ihist2);
cvShowImage("Hist_3", Ihist3);
cvWaitKey();
cvReleaseImage(&src1);
cvReleaseImage(&src2);
cvReleaseImage(&src3);
cvReleaseImage(&Icanny[0]);
cvReleaseImage(&Icanny[1]);
cvReleaseImage(&Icanny[2]);
cvReleaseImage(&Isobel1);
cvReleaseImage(&Isobel2);
cvReleaseImage(&Isobel3);
cvReleaseImage(&Ihist1);
cvReleaseImage(&Ihist2);
cvReleaseImage(&Ihist3);
cvDestroyAllWindows();
}
void Create_Hist_1D(IplImage* src, IplImage* canny, IplImage* gradient_dir, IplImage* hist_img)
{
IplImage *sobel_x, *sobel_y;
sobel_x = cvCreateImage(cvSize(src->width, src->height), 32, 1);
sobel_y = cvCreateImage(cvSize(src->width, src->height), 32, 1);
//边缘检测 src dst 边缘连接 边缘初始分割 核
cvCanny(src, canny, 60, 180, 3);
//方向导数
cvSobel(src, sobel_x, 1, 0, 3); //横向梯度dx
cvSobel(src, sobel_y, 0, 1, 3); //纵向梯度dy
//梯度方向 dy/dx
cvDiv(sobel_y, sobel_x, gradient_dir);
//梯度方向
char* ptr = NULL;
float theta=0.0; //梯度方向角
ptr = gradient_dir->imageData;
if (ptr != NULL)
{
for (int i = 0; i < gradient_dir->height; i++) //矩阵指针行寻址
{
ptr = (gradient_dir->imageData + i*(gradient_dir->widthStep)); //i 行 j 列
for (int j = 0; j < gradient_dir->width; j++) //矩阵指针列寻址
{
if (cvGetReal2D(canny, i, j) && cvGetReal2D(sobel_x, i, j)) //dx!=0
{
theta = cvGetReal2D(gradient_dir, i, j);
theta = atan(theta);
cvSetReal2D(gradient_dir, i, j, theta);
}
else //dx=0
{
cvSetReal2D(gradient_dir, i, j, 0);
}
}
}
}
float max = 0.0;
int bins = 20;
int hist_size[] = { bins }; //对应维数包含bins个数的数组
float range[] = { -CV_PI / 2, CV_PI / 2 };
float* ranges[] = { range };
CvHistogram* hist = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1);
cvZero(hist_img);
IplImage *planes[] = { gradient_dir }; //梯度图像数组
cvCalcHist(planes, hist, 0, canny); //只计算边界直方图
cvGetMinMaxHistValue(hist, 0, &max, 0, 0);
cvConvertScale(hist->bins, hist->bins, max ? 255. / max : 0., 0); //缩放bin到[0,255]
double bin_width = (double)hist_img->width / bins * 3 / 4;
for (int i = 0; i<bins; i++)
{
double val = cvGetReal1D(hist->bins, i)*hist_img->height / 255;
CvPoint p0 = cvPoint(30 + i*bin_width, hist_img->height);
CvPoint p1 = cvPoint(30 + (i + 1)*bin_width, hist_img->height - val);
cvRectangle(hist_img, p0, p1, cvScalar(0, 255), 1, 8, 0);
}
cvReleaseHist(&hist); //释放直方图
cvReleaseImage(&sobel_x);
cvReleaseImage(&sobel_y);
}
void Compare_Gesture_Hist(IplImage *sobel1, IplImage *sobel2, IplImage *test, IplImage** canny)
{
//建立直方图
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); //直方图归一化
//比较直方图
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 (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");
}
cvReleaseHist(&hist_model1);
cvReleaseHist(&hist_model2);
cvReleaseHist(&hist_test);
}
http://www.jiaoanw.com/%E6%95%99%E6%A1%88%E6%A0%BC%E5%BC%8F/article-43870-9.html
http://www.jiaoanw.com/
true
教案网
http://www.jiaoanw.com/%E6%95%99%E6%A1%88%E6%A0%BC%E5%BC%8F/article-43870-9.html
report
16997
运行结果如下图: 根据输入的手势图像,在每一个区域求取其梯度方向,计算出梯度方向直方图,并可视化。具体代码如下: #include cv.h #include highgui.h
省下的钱足够养得起军队了