利用OpenCV实现图像边缘直方图输出

这是边缘直方图显示程序,今天整理了以前编写的程序,贴出来给大家分享一下(注意以前,这个编写程序有点乱,请原解(^_^)~.).

参考代码如下所示:

#include "opencv2/opencv.hpp"

#pragma comment(lib, "opencv_core246d.lib")
#pragma comment(lib, "opencv_imgproc246d.lib")
#pragma comment(lib, "opencv_highgui246d.lib")

 int main(int argc, char* argv[]){
	IplImage* src=cvLoadImage("test.jpg", 0); // force to gray image
	if(src==0) return -1;

    cvNamedWindow( "Histogram", 0 );
    CvSize size=cvGetSize(src);

    IplImage* canny=cvCreateImage(cvGetSize(src),8,1);//边缘图像
    IplImage* dx=cvCreateImage(cvGetSize(src),32,1);//x方向上的差分,此处的数据类型为U不怕溢出
    IplImage* dy=cvCreateImage(cvGetSize(src),32,1);
	
	IplImage* gradient_im=cvCreateImage(cvGetSize(src),32,1);//梯度图像
    CvMat* canny_m=cvCreateMat(size.height,size.width,CV_32FC1);//边缘矩阵
    CvMat* dx_m=cvCreateMat(size.height,size.width,CV_32FC1);
    CvMat* dy_m=cvCreateMat(size.height,size.width,CV_32FC1);

    CvMat* gradient=cvCreateMat(size.height,size.width,CV_32FC1);//梯度矩阵
    CvMat* gradient_dir=cvCreateMat(size.height,size.width,CV_32FC1);//梯度方向矩阵
	CvMat* mask=cvCreateMat(size.height,size.width,CV_32FC1);//掩码

    cvCanny(src,canny,60,180,3);//边缘检测
    cvConvert(canny,canny_m);//把图像转换为矩阵

    cvSobel(src,dx,1,0,3);// 一阶X方向的图像差分:dx
    cvSobel(src,dy,0,1,3);// 一阶Y方向的图像差分:dy

    cvConvert(dx,dx_m);
    cvConvert(dy,dy_m);

    cvAdd(dx_m,dy_m,gradient); //梯度不是等于根号下x的导数的平方加上y导数的平方吗?
    cvDiv(dx_m,dy_m,gradient_dir); // direction

	int i,j;
	CvHistogram *hist = 0; // define multi_demention histogram
    float theta;
    int hdims = 8;     // 划分HIST的个数,越高越精确

    float hranges_arr[] = {-PI/2,PI/2}; // 直方图的上界和下界
    float* hranges = hranges_arr;  
    float max_val;
    int bin_w;

	IplImage* histimg = cvCreateImage( cvSize(320,200), 8, 3 ); // 创建一个图像,通道

    for(i=0;i<size.height;i++)
		for(j=0;j<size.width;j++){
			if(cvmGet(canny_m,i,j)!=0 && cvmGet(dx_m,i,j)!=0){//此行是什么意思?只看边缘上的方向?
				theta=cvmGet(gradient_dir,i,j);
				theta=atan(theta);
				cvmSet(gradient_dir,i,j,theta);  
			}
			else{
				cvmSet(gradient_dir,i,j,0); 
			}
		}
		hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 ); 
		//创建一个指定尺寸的直方图,并返回创建的直方图指针
		
		cvZero( histimg ); 
		cvConvert(gradient_dir,gradient_im);//把梯度方向矩阵转化为图像
		cvCalcHist( &gradient_im, hist, 0, canny ); // 计算直方图
		cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );  // 只找最大值
		cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); 
		//缩放bin 到区间[0,255] ,比例系数
		cvZero( histimg );
		bin_w = histimg->width /16;  // hdims: 条的个数,则bin_w 为条的宽度
		// 画直方图
		for( i = 0; i < hdims; i++ ){
			double val = ( cvGetReal1D(hist->bins,i)*histimg->height/255 );
			//返回单通道数组的指定元素, 返回直方图第i条的大小,val为histimg中的i条的高度
			CvScalar color = CV_RGB(255,255,0); //(hsv2rgb(i*180.f/hdims);//直方图颜色
			cvRectangle( histimg, cvPoint(100+i*bin_w,histimg->height),cvPoint(100+(i+1)*bin_w,(int)(histimg->height - val)),
				color, 1, 8, 0 ); // 画直方图——画矩形,左下角,右上角坐标
		}
		
		cvShowImage( "src", src);
		cvShowImage( "Histogram", histimg );
		cvWaitKey(0);
		
		cvDestroyWindow("src");
		cvDestroyWindow("Histogram");
		cvReleaseImage( &src );
		cvReleaseImage( &histimg );
		cvReleaseHist ( &hist );
		return 0;

}

输出结果

 

源始图                        Canny算子边缘检测图

边缘直方图输出


关于Image Engineering & Computer Vision的更多讨论与交流,敬请关注本博客和新浪微博songzi_tea.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值