边缘梯度方向直方图的构建

在手势识别时,可利用模板手势与当前手势的边缘梯度方向直方图进行匹配来识别当前手势, 故而就需要构建图像的边缘梯度方向直方图.

梯度为:dx*dx+dy*dy开方.            

梯度方向则为:dy/dx(注意dx为0的情况处理).

 1 #include "stdafx.h"
 2 #include "cv.h"
 3 #include "highgui.h"
 4 
 5 int main()
 6 {
 7     IplImage* src=cvLoadImage("C:/Users/shark/Desktop/fruits.jpg",0);
 8     CvSize size=cvGetSize(src);
 9     //边缘检测
10     IplImage* canny=cvCreateImage(size,8,1);
11     IplImage* canny32=cvCreateImage(size,IPL_DEPTH_32F,1);
12     cvCanny(src,canny,60,180,3);
13     cvConvert(canny,canny32);
14     //梯度计算
15     IplImage* dx=cvCreateImage(size,IPL_DEPTH_16S,1);
16     IplImage* dy=cvCreateImage(size,IPL_DEPTH_16S,1);
17     cvSobel(src,dx,1,0,3);
18     cvSobel(src,dy,0,1,3);
19     IplImage* dx32=cvCreateImage(size,IPL_DEPTH_32F,1);
20     IplImage* dy32=cvCreateImage(size,IPL_DEPTH_32F,1);
21     cvConvert(dx,dx32);
22     cvConvert(dy,dy32);
23     IplImage* gradient=cvCreateImage(size,IPL_DEPTH_32F,1);       //梯度图像
24     IplImage* gradient_dir=cvCreateImage(size,IPL_DEPTH_32F,1);   //梯度方向图像
25     cvDiv(dx32,dy32,gradient_dir);
26   
27     cvMul(dx32,dx32,dx32,1.0);
28     cvMul(dy32,dy32,dy32,1.0);
29     cvAdd(dx32,dy32,gradient,0);
30     for(int i=0;i<size.height;i++)
31         for(int j=0;j<size.width;j++)
32         {
33             gradient->imageData[i*gradient->widthStep+j]=cvSqrt((float)
34 
35                 gradient->imageData[i*gradient->widthStep+j]);
36         }
37       float theta;
38         for(int i=0;i<size.height;i++)
39             for(int j=0;j<size.width;j++)
40             {
41                 if(cvGetReal2D(canny32,i,j)!=0 && cvGetReal2D(dx32,i,j)!=0)    
42 
43                     //dy/dx中dx!=0
44                 {
45                     theta=cvGetReal2D(gradient_dir,i,j);
46                     theta=atan(theta);
47                     cvSetReal2D(gradient_dir,i,j,theta);
48                 }
49                 else
50                 {
51                     cvSetReal2D(gradient_dir,i,j,0);
52                 }
53             }
54             int bins=20; float max=0;
55             float range[]={-CV_PI/2,CV_PI/2};
56             float* ranges[]={range};
57             CvHistogram* hist=cvCreateHist(1,&bins,CV_HIST_ARRAY,ranges,1);
58             IplImage* hist_img=cvCreateImage(cvSize(320,200),8,3);
59             cvZero(hist_img);
60             cvCalcHist(&gradient_dir,hist,0,canny);                       //只计算边界直方图
61             cvGetMinMaxHistValue(hist,0,&max,0,0);
62             cvConvertScale(hist->bins,hist->bins,max?255./max:0.,0);   //缩放bin到[0,255]
63             double bin_width=(double)hist_img->width/bins*3/4;
64             for(int i=0;i<bins;i++)
65             {
66                 double val=cvGetReal1D(hist->bins,i)*hist_img->height/255;
67                 CvPoint p0=cvPoint(30+i*bin_width,hist_img->height);
68                 CvPoint p1=cvPoint(30+(i+1)*bin_width,hist_img->height-val);
69                 cvRectangle(hist_img,p0,p1,cvScalar(0,255),1,8,0);
70             }
71             cvNamedWindow("hist_img");
72             cvShowImage("hist_img",hist_img);
73             cvWaitKey();
74 
75 
76 }

原图:

梯度方向直方图:

原文地址:https://www.cnblogs.com/luckyboylch/p/4948495.html