opencv两种方法实现sobel边缘检测

#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<iostream>
#include<algorithm>
using namespace std;
using namespace cv;
//sobel非极大值抑制
void sobelVeredge(Mat& src, Mat& result)
{
	CV_Assert(src.channels()==1);
	src.convertTo(src,CV_32FC1);
	//水平方向的sobel算子
	Mat sobelX = (Mat_<float>(3, 3) << -0.125, 0, 0.125, -0.25, 0, 0.25, -0.125, 0, 0.125);
	Mat ConResMat;
	filter2D(src,ConResMat,src.type(),sobelX);
	//计算幅度
	Mat graMagMat;
	multiply(ConResMat,ConResMat,graMagMat);
	//根据梯度幅值及参数设置阈值
	int scaleVal = 4;
	double thresh = scaleVal*mean(graMagMat).val[0];
	cout << mean(graMagMat) << endl;
	cout << thresh << endl;
	Mat resultTemp = Mat::zeros(graMagMat.size(),graMagMat.type());
	float* pDataMag = (float*)graMagMat.data;
	float* pDataRes = (float*)resultTemp.data;
	int nRows = ConResMat.rows;
	int nCols = ConResMat.cols;
	for (int i = 1; i < nRows - 1; i++)
	{
		for (int j = 1; j < nCols - 1; j++)
		{
			//计算该点与水平垂直梯度大小比较
			bool b1 = (pDataMag[i*nCols + j]>pDataMag[(i - 1)*nCols + j]);
			bool b2= (pDataMag[i*nCols + j]>pDataMag[(i + 1)*nCols + j]);
			bool b3= (pDataMag[i*nCols + j]>pDataMag[i*nCols + j-1]);
			bool b4= (pDataMag[i*nCols + j]>pDataMag[i*nCols + j+1]);
			//梯度大于邻域水平和垂直梯度,并根据自适应阈值参数进行二值化
			pDataRes[i*nCols + j] = 255 * ((pDataMag[i*nCols + j] > thresh) && ((b1 && b2) || (b3 && b4)));

		}
	}
	resultTemp.convertTo(resultTemp,CV_8UC1);
	result = resultTemp.clone();
}

//图像卷积实现sobel
void sobelEdge(Mat& src, Mat& result,uchar threshold)
{
	CV_Assert(src.channels()==1);
	src.convertTo(src, CV_32FC1);
	Mat temp= Mat::zeros(src.rows - 2, src.cols - 2, src.type());
	//水平核因子
	Mat sobelX = (Mat_<double>(3, 3) << 1, 0, -1, 2, 0, -2, 1, 0, -1);
	//垂直核因子
	Mat sobelY = (Mat_<double>(3, 3) << 1, 2, 1, 0, 0, 0, -1, -2, -1);
	//result = Mat::zeros(src.rows - 2, src.cols - 2, src.type());
	double edgeX=0;
	double edgeY=0;
	double graMag = 0;
	for (int i = 1; i < src.rows - 1; i++)
	{
		for (int j = 1; j < src.cols - 1; j++)
		{
			edgeX = 0;
			edgeY = 0;
			for (int k = -1; k <= 1; k++)
			{
				for (int n = -1; n <= 1; n++)
				{
					edgeX += src.at<float>(i + k, j + n)*sobelX.at<double>(k+1,n+1);
					edgeY+= src.at<float>(i + k, j + n)*sobelY.at<double>(k + 1, n + 1);
				}
			}
			graMag = sqrt(pow(edgeX,2)+pow(edgeY,2));
			temp.at<float>(i - 1, j - 1) = ((graMag>threshold) ? 255 : 0);
		}
	}
	temp.convertTo(temp,CV_8UC1);
	result = temp.clone();
}
int main()
{
	//imread中0表示灰度返回,1表示原图返回
	Mat src = imread("E:\\研究生\\学习材料\\学习书籍\\OpenCV图像处理编程实例-源码-20160801\\《OpenCV图像处理编程实例-源码-20160801\\images\\building.jpg",0);
	if (!src.data)
		return -1;
	imshow("src", src);
	Mat result;
	Mat result2;
	sobelVeredge(src, result);
	sobelEdge(src, result2, 100);
	imshow("result",result);
	imshow("result2",result2);
	waitKey(0);
	return(0);
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值