函数:
void cv::copyMakeBorder (InputArray src,
OutputArray dst,
int top,
int bottom,
int left,
int right,
int borderType, //填充类型
const Scalar & value = Scalar() //填充颜色
)
Python:
cv.copyMakeBorder( src, top, bottom, left, right, borderType[, dst[, value]] ) -> dst
填充类型:
使用如下:
RNG rng(12345);
int top, bottom, left, right;
int borderType = BORDER_CONSTANT;
// Initialize arguments for the filter
top = (int) (0.05*src.rows); bottom = top;
left = (int) (0.05*src.cols); right = left;
Scalar value( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) );
copyMakeBorder( src, dst, top, bottom, left, right, borderType, value );
边缘检测原理如下图所示:
数学原理:
函数:
void cv::Sobel (InputArray src,
OutputArray dst,
int ddepth,
int dx, //x方向
int dy, //y方向
int ksize = 3, //核大小
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
)
Python:
cv.Sobel( src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]] ) -> dst
变换函数:
void cv::convertScaleAbs( InputArray src,
OutputArray dst,
double alpha = 1, //对比度
double beta = 0 //亮度
)
Python:
cv.convertScaleAbs( src[, dst[, alpha[, beta]]] ) -> dst
变换原理:
求梯度:
cvtColor(src, src_gray, COLOR_BGR2GRAY);
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
Sobel(src_gray, grad_x, ddepth, 1, 0, ksize, scale, delta, BORDER_DEFAULT);
Sobel(src_gray, grad_y, ddepth, 0, 1, ksize, scale, delta, BORDER_DEFAULT);
// converting back to CV_8U
convertScaleAbs(grad_x, abs_grad_x);
convertScaleAbs(grad_y, abs_grad_y);
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
函数接口:
void cv::Scharr (InputArray src,
OutputArray dst,
int ddepth,
int dx,
int dy,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
)
Python:
cv.Scharr( src, ddepth, dx, dy[, dst[, scale[, delta[, borderType]]]] ) -> dst
当核的大小为3时,上面所示的Sobel核可能产生明显的不准确性(毕竟,Sobel只是导数的近似值)。OpenCV通过使用Scharr()函数解决了大小为3的内核的不准确性问题。这与标准Sobel函数一样快,但更准确。它实现了以下内核:
求梯度时,与Sobel算子实现代码相同,下边给出边缘检测应用:
Mat dx,dy;
Scharr(blurImage,dx,CV_16S,1,0);
Scharr(blurImage,dy,CV_16S,0,1);
Canny( dx,dy, edge2, edgeThreshScharr, edgeThreshScharr*3 );
cedge = Scalar::all(0);
image.copyTo(cedge, edge2);
图形化数学原理:
void cv::Laplacian( InputArray src,
OutputArray dst,
int ddepth,
int ksize = 1,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
)
Python:
cv.Laplacian( src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]] ) -> dst
求梯度实现:
cvtColor( src, src_gray, COLOR_BGR2GRAY ); // Convert the image to grayscale
Mat abs_dst;
Laplacian( src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT );
// converting back to CV_8U
convertScaleAbs( dst, abs_dst );
边缘检测算法步骤:
先经过高斯平滑,目的是去噪声
寻找图像强度梯度
非极大值抑制
上一步算出来的边缘可能比较粗糙,假设边缘是一条很细的线的话,上面处理完的结果你可以理解为得到一条比较粗的线条,所谓非极大值抑制,就是要在局部像素点中找到变换最剧烈的一个点,这样就得到了更细的边缘.
双阈值检测和连接边缘
void Canny(cv::InputArray src,
cv::OutputArray dst,
double threshold1, //梯度小于minVal的像素点弃用,不视为边缘
double threshold2, //梯度大于maxVal的像素点保留,视为边缘
int aperture_size=3
);
详细参考:
https://blog.csdn.net/Vermont_/article/details/108471205
https://blog.csdn.net/xddwz/article/details/111585648
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main() {
Mat srcImage, grayImage;
srcImage = imread("/Users/dwz/Desktop/cpp/1.jpg");
Mat srcImage1 = srcImage.clone();
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
Mat dstImage, edge;
blur(grayImage, grayImage, Size(3,3));
Canny(grayImage, edge, 150, 100, 3);
dstImage.create(srcImage1.size(), srcImage1.type());
dstImage = Scalar::all(0);
srcImage1.copyTo(dstImage, edge);
imwrite("canny.jpg", dstImage);
return 0;
}