#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);
}