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

来源:互联网 发布:简历生活照怎么照之乎 编辑:程序博客网 时间:2024/06/06 02:45
          由于对基本的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个像素点的偏离。后面的代码段对位置有一点小的调整。

0 0
原创粉丝点击