自定义线性滤波
l卷积是图像处理中一个操作,是kernel在图像的每个像素上的操作。
lKernel本质上一个固定大小的矩阵数组,其中心点称为锚点(anchor point)
把kernel放到像素数组之上,求锚点周围覆盖的像素乘积之和(包括锚点),用来替换锚点覆盖下像素点值称为卷积处理
Robert算子
#include "cv.hpp"
#include<iostream>
#include<ctime>
#include<random>
using namespace cv;
using namespace std;
int main()
{
Mat src, robertimg;
src = imread("../0.jpg");
imshow("src", src);
//robert x方向
Mat robert_x = (Mat_<int>(2, 2) << 1, 0, 0, -1);
filter2D(src, robertimg, -1, robert_x, Point(-1, -1), 0.0);
imshow("robert_x", robertimg);
//robert y方向
Mat robert_y = (Mat_<int>(2, 2) << 0, 1, -1, 0);
filter2D(src, robertimg, -1, robert_y, Point(-1, -1), 0.0);
imshow("robert_y", robertimg);
waitKey();
}
Sobel算子
#include<random>
using namespace cv;
using namespace std;
int main()
{
Mat src, sobelimg;
src = imread("../0.jpg");
imshow("src", src);
//sobel x方向
Mat sobel_x = (Mat_<int>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
filter2D(src, sobelimg, -1, sobel_x, Point(-1, -1), 0.0);
imshow("sobel_x", sobelimg);
//sobel y方向
Mat sobel_y = (Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
filter2D(src, sobelimg, -1, sobel_y, Point(-1, -1), 0.0);
imshow("sobel_y", sobelimg);
waitKey();
}
拉普拉斯算子
#include "cv.hpp"
#include<iostream>
#include<ctime>
#include<random>
using namespace cv;
using namespace std;
int main()
{
Mat src, laimg;
src = imread("../0.jpg");
imshow("src", src);
Mat kernel = (Mat_<int>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
filter2D(src, laimg, -1, kernel, Point(-1, -1), 0.0);
imshow("拉普拉斯", laimg);
waitKey();
}
自定义卷积模糊
#include "cv.hpp"
#include<iostream>
#include<ctime>
#include<random>
using namespace cv;
using namespace std;
int main()
{
Mat src, img, kernel;
src = imread("../0.jpg");
imshow("src", src);
int c = 0;
int index = 1;
int ksize;
while (true) {
c = waitKey(500);
if ((char)c == 27)
{
break;
}
ksize = 3 + 2 * (index % 9);
kernel = Mat::ones(Size(ksize, ksize), CV_32F)/(float)(ksize*ksize);
filter2D(src, img, -1, kernel, Point(-1, -1), 0);
imshow("自定义卷积模糊", img);
index++;
}
waitKey();
}
卷积边缘问题
图像卷积的时候边界像素,不能被卷积操作,原因在于边界像素没有完全跟kernel重叠,所以当3x3滤波时候有1个像素的边缘没有被处理,5x5滤波的时候有2个像素的边缘没有被处理。
在卷积开始之前增加边缘像素,填充的像素值为0或者RGB黑色,比如3x3在
四周各填充1个像素的边缘,这样就确保图像的边缘被处理,在卷积处理之
后再去掉这些边缘。openCV中默认的处理方法是: BORDER_DEFAULT,此外
常用的还有如下几种:
- BORDER_CONSTANT – 填充边缘用指定像素值
- BORDER_REPLICATE – 填充边缘像素用已知的边缘像素值。
- BORDER_WRAP – 用另外一边的像素来补偿填充
给图像添加边缘API
copyMakeBorder(
- Mat src, // 输入图像
- Mat dst, // 添加边缘图像
- int top, // 边缘长度,一般上下左右都取相同值,
- int bottom,
- int left,
- int right,
- int borderType // 边缘类型
- Scalar value
)