opencv边缘检测的方法

部分边缘检测仅提供主要实现代码工程需要自己补充完整
1、Robert 原理:
任意一对互相垂直方向上的差分可以看成求梯度的近似方法
优缺点:
边缘定位精度较高,对于陡峭边缘且噪声低的图像效果较好,但没有进行平滑处理,没有抑制噪声能力
应用
具有陡峭的低噪声的图像处理效果较好
/*****************************Robert*******************************/
Mat roberts(cv::Mat srcImage)
{
cv::Mat dstImage = srcImage.clone();
int nRows = dstImage.rows;
int nCols = dstImage.cols;
for (int i = 0; i < nRows-1; i++)
{
for (int j = 0; j < nCols-1; j++)
{
int t1 = (srcImage.at(i, j) -
srcImage.at(i+1, j+1)) *
(srcImage.at(i, j) -
srcImage.at(i+1, j+1));
int t2 = (srcImage.at(i+1, j) -
srcImage.at(i, j+1)) *
(srcImage.at(i+1, j) -
srcImage.at(i, j+1));
dstImage.at(i, j) = (uchar)sqrt(t1 + t2);
}
}
return dstImage;
}
2、Sobel和prewwitt 进行了平滑处理,对噪声具有一定的抑制能力,但容易出现多像素宽度。
应用
检测方法对灰度渐变和噪声较多的图像处理效果较好
/*****************************prewwitt*******************************/
Mat prewitt(Mat imageP)
{
cvtColor(imageP,imageP,CV_RGB2GRAY);
float prewittx[9] =
{
-1,0,1,
-1,0,1,
-1,0,1
};
float prewitty[9] =
{
1,1,1,
0,0,0,
-1,-1,-1
};
Mat px=Mat(3,3,CV_32F,prewittx);
Mat py=Mat(3,3,CV_32F,prewitty);
Mat dstx=Mat(imageP.size(),imageP.type(),imageP.channels());
Mat dsty=Mat(imageP.size(),imageP.type(),imageP.channels());
Mat dst=Mat(imageP.size(),imageP.type(),imageP.channels());
filter2D(imageP,dstx,imageP.depth(),px);
filter2D(imageP,dsty,imageP.depth(),py);
float tempx,tempy,temp;
for(int i=0; i {
for(int j=0; j {
tempx=dstx.at(i,j);
tempy=dsty.at(i,j);
temp=sqrt(tempx*tempx+tempy*tempy);
dst.at(i,j)=temp;
}
}
return dst;
}
/*****************************sobel*******************************/
Mat src, src_gray;
Mat grad;
string window_name = "Sobel Demo - Simple Edge Detector";
int scale = 1; //默认值
int delta = 0; //默认值
int ddepth = CV_16S; //防止输出图像深度溢出
int c;
src = https://www.it610.com/article/imread("lena.jpg" );
if( !src.data )
{ return -1; }
//高斯模糊
GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
//变换为灰度图
cvtColor( src, src_gray, CV_RGB2GRAY );
//创建窗口
namedWindow( window_name, CV_WINDOW_AUTOSIZE );
//生成 grad_x and grad_y
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
// Gradient X x方向梯度 1,0:x方向计算微分即导数
Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_x, abs_grad_x );
// Gradient Y y方向梯度 0,1:y方向计算微分即导数
Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_y, abs_grad_y );
//近似总的梯度
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
imshow( window_name, grad );
waitKey(0);
3、Laplacian 对噪声较为敏感,使噪声能力成分得到加强,容易丢失部分边缘方向信息,造成一些不连续的检测边缘,同时抗噪声能力较差。所以很少用该算子检测边缘,而是用来判断边缘像素视为与图像的明区还是暗区。
4、Laplacian(自己加载一张图片就好,img加载图像名,补充完main函数)
/*****************************Laplacian*******************************/
cv::Mat srcImage=cv::imread("lena.jpg", 0);
if (!srcImage.data)
return -1;
// 高斯平滑加上高斯平滑效果边缘检测效果更好
GaussianBlur(srcImage, srcImage, cv::Size(3,3),0, 0, cv::BORDER_DEFAULT);
cv::Mat dstImage;
// 拉普拉斯变换
Laplacian(srcImage, dstImage, CV_16S, 3);
convertScaleAbs( dstImage, dstImage);
cv::imshow("srcImage", srcImage);
cv::imshow("dstImage", dstImage);
cv::waitKey(0);
5、Log 抗噪声能力较强,但会造成一些尖锐的边缘无法检测到。(自己加载一张图片就好,img加载图像名,补充完mainh)
/*****************************Log*******************************/
Mat img_G0,img_G1;
GaussianBlur(img,img_G0,Size(3,3),0);
GaussianBlur(img_G0,img_G1,Size(3,3),0);
Mat img_DoG = img_G0 - img_G1;
normalize(img_DoG,img_DoG,255,0,CV_MINMAX);
imshow("img_DoG",img_DoG);
cv::waitKey(0);
6、Canny 最优化思想的边缘检测算子,同时采用高斯函数对图像进行平滑处理,但会造成将高频边缘平滑掉,造成边缘丢失,采用双阈值算法检测和链接边缘。
/*****************************Canny*******************************/
#include"./opencv2/opencv.hpp"
#include
using namespace cv;
using namespace std;
Mat src, src_gray;
Mat dst, detected_edges;
int edgeThresh = 1;
int lowThreshold;
int const max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
const char* window_name = "Edge Map";
static void CannyThreshold(int, void*)
{
Canny( src_gray, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );
dst = Scalar::all(0);
src.copyTo( dst, detected_edges);
imshow( window_name, dst );
}
int main( int, char** argv )
{
src = https://www.it610.com/article/imread("D:\\lena.jpg",CV_LOAD_IMAGE_COLOR);
if( !src.data )
{ return -1; }
dst.create( src.size(), src.type() );
cvtColor( src, src_gray, CV_BGR2GRAY );
namedWindow( window_name, CV_WINDOW_AUTOSIZE );
createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold );
CannyThreshold(0, 0);
waitKey(0);
return 0;
}
7、形态学边缘检测 利用形态学梯度保留边缘检测morphgrad(src)=dilate(src)?erode(src);
/***********************dilate-erodeEdge detection****************************/
#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp"
using namespace cv;
int main(int argc,char *argv[])
{
Mat image,imageGray,imageDilate,imageErode,imageBorder;
image=imread(argv[1]);
resize(image,image,Size(400,400));
cvtColor(image,imageGray,CV_RGB2GRAY);
//enum { MORPH_RECT=0, MORPH_CROSS=1, MORPH_ELLIPSE=2 };
Mat element=getStructuringElement(1,Size(3,3),Point(-1,-1));
//效果等同与imageDilate-imageErode
//morphologyEx(imageGray,imageGray, MORPH_GRADIENT, element);
dilate(imageGray,imageDilate,element,Point(-1,-1));
erode(imageGray,imageErode,element,Point(-1,-1));
imageBorder=imageDilate-imageErode;
imshow("Source image",image);
imshow("Dilate",imageDilate);
imshow("Erode",imageErode);
imshow("Border",imageBorder);
waitKey(0);
}

【opencv边缘检测的方法】

    推荐阅读