对图像横向和纵向像素均值求一阶导数,进行图像中物体的边缘检测

          由于对基本的Opencv的矩阵的数据类型不太熟悉,以及它们之间的转换,数据的存取都比较陌生,虽然在写这个程序的时候思路很清楚,却总是出错,找到的并不是想要的边缘位置。今天终于搞好啦,关于OpenCV的矩阵类型及操作还要多加熟悉和使用啊!!下面是实现程序及效果图:
#include "stdafx.h"
#include "highgui.h"
#include <opencv2/opencv.hpp> 
  
using namespace std; 
using namespace cv;
void GetLevelGrad();

int main()  
{   
	IplImage* GrayImage;
    const char *pstrImageName = "D:\\picture\\New\\1 (2).bmp";   
    GrayImage = cvLoadImage(pstrImageName, CV_LOAD_IMAGE_GRAYSCALE); 
   
    cvShowImage("灰度图像",GrayImage);       
	Mat SmothImage ; 
	//Mat AverageVal = cvCreateMat(1, GrayImage->width, CV_32FC1);
    Mat Gray_Image(GrayImage);
	GaussianBlur( Gray_Image, SmothImage, Size( 3, 3 ), 0, 0 );
	//imshow("高斯滤波处理",SmothImage);
	
	int iWidth = SmothImage.cols;
	int iHeight = SmothImage.rows;
	int i,j;
	CvMat* averageValue_level = cvCreateMat( 1, iWidth, CV_32FC1 );
	CvMat* averageValue_vertical = cvCreateMat( iHeight,1, CV_32FC1 );
	for (i=0;i<iWidth;i++)
	{
		float value = 0;
		for (j=0;j<iHeight;j++)
		{
			value = value + (float)SmothImage.at<uchar>(j,i);
			
		}
		
		value = value/(float)iHeight;
		CV_MAT_ELEM( *averageValue_level, float,0, i ) = value;
		
		//AverageValue.at<uchar>(0,i) = value;
		//printf("%f\n",CV_MAT_ELEM( *averageValue, float,0, i ) );
	}

	cv::Mat AverageValue_level = cv::Mat(averageValue_level,true);
	//cvShowImage("所有列灰度均值",averageValue);
	
	cv::Mat GradValue_level(1,iWidth, CV_32FC1);
	for (i=0;i<iWidth-1;i++)
	{
		GradValue_level.at<float>(0,i) = (float)CV_MAT_ELEM( *averageValue_level, float,0, i+1 ) -(float)CV_MAT_ELEM( *averageValue_level, float,0, i );
		
		printf("%f\n",GradValue_level.at<float>(0,i));
	}
	///////////////////////////////垂直方向/////////////////////
	for (j=0;j<iHeight;j++)
	{
		float value = 0;
		for (i=0;i<iWidth;i++)
		{
			value = value + (float)SmothImage.at<uchar>(j,i);
			
		}
		
		value = value/(float)iWidth;
		CV_MAT_ELEM( *averageValue_vertical, float,j, 0 ) = value;
		
		//AverageValue.at<uchar>(0,i) = value;
		//printf("%f\n",CV_MAT_ELEM( *averageValue, float,0, i ) );
	}

	cv::Mat AverageValue_vertical = cv::Mat(averageValue_vertical,true);
	//cvShowImage("所有列灰度均值",averageValue_vertical);
	
	cv::Mat GradValue_vertical(iHeight,1, CV_32FC1);
	for (j=0;j<iHeight-1;j++)
	{
		GradValue_vertical.at<float>(j,0) = (float)CV_MAT_ELEM( *averageValue_vertical, float,j+1,0 ) -(float)CV_MAT_ELEM( *averageValue_vertical, float,j,0);
		
		printf("%f\n",GradValue_vertical.at<float>(j,0));
	}

	GradValue_vertical.at<uchar>(iHeight-1,0) =0;
	double minVal, maxVal,minVal_Vertical,maxVal_Vertical;
	Point minLoc_level, maxLoc_level, matchLoc_level,minLoc_vertical,maxLoc_vertical;
    minMaxLoc(GradValue_level, &minVal, &maxVal, &minLoc_level, &maxLoc_level, Mat() );

	//////////////////////////////垂直方向////////////////////////////////////////
	minMaxLoc(GradValue_vertical, &minVal_Vertical, &maxVal_Vertical, &minLoc_vertical, &maxLoc_vertical, Mat() );
	circle( SmothImage, maxLoc_level, 3, Scalar(255,0,255), -1, 8, 0 );
	circle( SmothImage, maxLoc_vertical, 3, Scalar(255,0,255), -1, 8, 0 );
	//circle( SmothImage, minLoc_vertical, 3, Scalar(255,0,255), -1, 8, 0 );
	printf("x坐标:%f",(float)maxLoc_level.x);
	printf("y坐标: %f",(float)maxLoc_vertical.y);
	Point matchPoint;
	matchPoint.x = maxLoc_level.x-1;
	matchPoint.y = maxLoc_vertical.y-1;

	Point center;
	center.x = maxLoc_level.x+(minLoc_level.x-maxLoc_level.x+4)/2;
	center.y = maxLoc_vertical.y+ (minLoc_vertical.y-maxLoc_vertical.y+4)/2;
	rectangle( SmothImage,  Rect(matchPoint, Size(minLoc_level.x-maxLoc_level.x+4, minLoc_vertical.y-maxLoc_vertical.y+4 ) ), Scalar(0), 1, 8, 0 );
	//circle(SmothImage,center,(minLoc_level.x-maxLoc_level.x+4)/2,Scalar(0,0,0),2,8,0);
	imshow("边界点所在位置",SmothImage);
	cvWaitKey();
	
	
}


因为本程序的主要思想是基于一阶导数求梯度的,所以找到的边缘位置会有1~2个像素点的偏离。后面的代码段对位置有一点小的调整。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值