赞
踩
图像卷积的时候边界像素不被卷积操作,原因在于边界像素没有完全跟kernel重叠,只有当3X3的滤波时候有一个像素的边缘没有被处理,5x5滤波的时候有两个像素边缘没有处理。
在卷积开始之前增加边缘像素,填充的像素值为0或者RGB黑色,比如3x3在四周各填充1各像素的边缘,这样就确保图像的边缘被处理,在卷积处理hi后再去掉这些边缘,openCV中默认的处理方式就是:BORDER_DEFAULT,此外还有常用
- copyMakeBorder(
- Mat src,//输入图像
- Mat dst,//添加边缘图像
- int top,//边缘长度,一般上下左右都取相同值
- int bottom,
- int left,
- int right,
- int borderType//边缘类型
- Scalar value
-
- )
- void MyApi::image_edge_processing(Mat& image)
- {
- //每半秒中图像的边缘就会变化一次,我们也可以通过按键选择变化的类型
- Mat dst;
- int top = (int)(0.05 * image.rows);
- int bottom = (int)(0.05 * image.rows);
- int left = (int)(0.05 * image.cols);
- int right = (int)(0.05 * image.cols);
- RNG rng(12345);
- int borderType = BORDER_DEFAULT;
-
- int c = 0;
- while (true)
- {
- c = waitKey(500);
- //ESC
- if ((char)c == 27)
- {
- break;
- }
- if ((char)c == 'r')
- {
- borderType = BORDER_REPLICATE;
- }
- else if ((char)c == 'w')
- {
- borderType == BORDER_WRAP;
- }
- else if ((char)c == 'c')
- {
- borderType == BORDER_CONSTANT;
- }
- Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
- copyMakeBorder(image, dst, top, bottom, left, right, borderType, color);
- imshow("OUTPUT", dst);
- }
-
- }

边缘:
- 边缘是什么:是像素值发生跃迁的地方,是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用。
- 如何捕捉/提取边缘——对图像求他的一阶导数,delta = f(x)-f(x-1).delta越大说明像素在方向变化越大,边缘信号越强
- 我们可以选择利用一些算子如Sobel算子等
水平梯度在水平方向乘以2为了扩大水平方向差异,垂直方向同理。
改进版本的Sobel算子:
相关的API
- cv::Sobel(inputArray src,OutputArray dst,
- int depth,//输出图像深度
- int dx,//x和y方向的几节导数,选择1
- int dy,
- int ksize,//Sobel算子kernel大小,必须是1,3,5,7
- double scale=1
- double delta =0
- int borderType = BORDEDR_DEFAULT
- )
深度一般选择CV_8U中的 CV_16S或者CV_32F
步骤:
- 高斯平滑
- 转灰度
- 求梯度,分别在x和Y方向上的
- 振幅图片(综合X和Y方向上的)
- void MyApi::image_edge_extract(Mat& image)
- {
- Mat gray_image, dst;
- GaussianBlur(image, dst, Size(5, 5), 0, 0);
- cvtColor(dst, gray_image, COLOR_BGR2GRAY);
- Mat xgard, ygrad;
- Sobel(gray_image, xgard, CV_16S, 1, 0, 3);
- Sobel(gray_image, ygrad, CV_16S, 0, 1, 3);
- //convert(ScaleAbs());
- //必须取绝对值不然看不见效果
- convertScaleAbs(xgard, xgard);
- convertScaleAbs(ygrad, ygrad);
- //x方向梯度
- imshow("xgrad", xgard);
- //y方向梯度
- imshow("ygrad", ygrad);
-
- //xy方向梯度
- Mat xygrad;
- addWeighted(xgard, 0.5, ygrad, 0.5,0,xygrad);
- imshow("xygrad", xygrad);
- }

高斯模糊去噪声GaussianBlue()
转换为灰度图像cvtColor()
拉普拉斯二阶导数计算Laplacian()
取绝对值convertScaleAbs()
显示结果
- void MyApi::image_edge_extraxt_Laplance(Mat& image)
- {
- Mat gray_image, edge_image, dst;
- GaussianBlur(image, dst, Size(3, 3), 0, 0);
- cvtColor(dst, gray_image, COLOR_BGR2GRAY);
- Laplacian(gray_image, edge_image, CV_16S, 3);
- convertScaleAbs(edge_image, edge_image);
- imshow("output", edge_image);
- }
为了让效果更佳的明显我们选用了二值化操作:
图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。OpenCV中提供了函数cv::threshold();
加一句:
通过二值化后:
Canny1986年提出的是边缘检测算法,是一个很好的边缘检测器,很常用的图像处理方法
- Canny(
- InputArray src,
- OutputArray edges,
- double threshold1,//低阈值,常取高于之的1/2或者1/3
- double threshold2,//高阈值
- int aptertureSize,//Sobel算子的size,通常3x3取值为3
- bool L2gradient//选择true表示L2来归一化,否则用L1来归一化
- )
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。