【15】opencv卷积运算
参考:
https://blog.csdn.net/zhu_hongji/article/details/81562746(关于卷积运算)
https://www.cnblogs.com/MrMKG/p/16062746.html(对于RNG函数的解答)
(一)首先是对于边缘的填充(避免有些像素卷积不了)
C++ void copyMakeBorder( Mat src, // 输入图像 Mat dst, // 添加边缘图像 int top, // 边缘长度,一般上下左右都取相同值, int bottom, int left, int right, int borderType // 边缘类型 Scalar value )
关于borderType的值:
- BORDER_CONSTANT – 填充边缘用指定像素值 - BORDER_REPLICATE – 填充边缘像素用已知的边缘像素值。 - BORDER_WRAP – 用另外一边的像素来补偿填充
下面实现对于图片边缘地区进行填补像素:
#include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { Mat Origin = imread("0003.jpg"); if (!Origin.data) { cout << "ERROR" << endl; return -1; } Mat OutPut1 = Mat(Origin.size(), Origin.type()); Mat OutPut2 = Mat(Origin.size(), Origin.type()); Mat OutPut3 = Mat(Origin.size(), Origin.type()); int added_cols = Origin.cols * 0.06; int added_rows = Origin.rows * 0.06; RNG rng(14); Scalar color = (rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); copyMakeBorder(Origin, OutPut1, added_cols, added_cols, added_rows, added_rows,BORDER_ISOLATED, color); copyMakeBorder(Origin, OutPut2, added_cols, added_cols, added_rows, added_rows,BORDER_DEFAULT, color); copyMakeBorder(Origin, OutPut3, added_cols, added_cols, added_rows, added_rows, BORDER_CONSTANT, color); imshow("OUTPUT BORDER_ISOLATED", OutPut1); imshow("OUTPUT BORDER_DEFAULT", OutPut2); imshow("OUTPUT BORDER_CONSTANT", OutPut3); waitKey(0); }
(二)卷积运算代码基础
<1>自定义卷积模糊:
Mat Model = (Mat_<char>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
C++ void filter2D( Mat src, //输入图像 Mat dst, // 模糊图像 int depth, // 图像深度32/8 Mat kernel, // 卷积核/模板 Point anchor, // 锚点位置 double delta // 计算出来的像素+delta)其中 kernel是可以自定义的卷积核
#include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { Mat Input = imread("0004.jpg"); Mat Output_1 = Mat(Input.size(), Input.type()); Mat Output_2 = Mat(Input.size(), Input.type()); Mat Output_3 = Mat(Input.size(), Input.type()); if (!Input.data) { cout << "ERROR" << endl; return -1; } Mat Model_1 = (Mat_<char>(3,3) << 0, 1 , 0, 0, 1, 0, 0, 1, 0); Mat Model_2 = (Mat_<char>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1); Mat Model_3 = (Mat_<char>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0); Point ANCHOR = Point(-1, -1); filter2D(Input, Output_1,-1, Model_1,ANCHOR,BORDER_DEFAULT); filter2D(Input, Output_2, -1, Model_2, ANCHOR,100, BORDER_DEFAULT); filter2D(Input, Output_3, -1, Model_3, ANCHOR,100 ,BORDER_DEFAULT); imshow("input", Input); imshow("output1", Output_1); imshow("output2", Output_2); imshow("output3", Output_3); waitKey(0); }
<2>Sobel算子:
关于sobel算子具体内容,移步:
https://blog.sciencenet.cn/blog-425437-1139187.html
https://www.daimadog.com/2335.html
C++ void Sobel ( InputArray Src // 输入图像 OutputArray dst// 输出图像,大小与输入图像一致 int depth // 输出图像深度. Int dx // X方向,几阶导数 int dy // Y方向,几阶导数 int ksize, SOBEL算子kernel大小,必须是1、3、5、7、 double scale = 1 double delta = 0 int borderType = BORDER_DEFAULT)
参数解释:
src:原图
ddepth:处理结果图像深度,一般我们都填-1,即与原图深度相同。但在这里我们需要填写cv2.CV_64F。简单来说就是如果填写-1,我们在计算梯度时产生的负数就会被程序默认为0,导致有一边的边缘出不来。而cv2.CV_64F范围更大,可以保留负数。
dx:计算x方向的梯度
dy:计算y方向的梯度
ksize:卷积核的尺寸。默认为3,即3*3的矩阵。
原文链接:https://blog.csdn.net/weixin_45939019/article/details/104410567
//改进版本的sobel算子:
C++ void Scharr (
InputArray Src // 输入图像
OutputArray dst// 输出图像,大小与输入图像一致
int depth // 输出图像深度.
Int dx. // X方向,几阶导数
int dy // Y方向,几阶导数.
double scale = 1
double delta = 0
int borderType = BORDER_DEFAULT)
(to be continued)
(三)常用卷积核
以下为原图片:
<1>什么都不处理(3*3)
很容易理解,就是0*8+中间原像素值
<2>图像锐化滤波器Sharpness Filter(3*3)(梯度锐化和拉普拉斯锐化)
注意一下,中间值为8就是边缘检测,为9就是原图的图像锐化
另外,如果卷积核更大,则锐化的程度也会更细致。
我的分析(暂无,等待学习数字图像处理再来推导)
>>关于梯度锐化:
>>关于拉普拉斯锐化:
具体分析见:
https://blog.csdn.net/weixin_42183170/article/details/88751409
<3>边缘检测Edge Detection
相当于求导的离散版本:你将当前的像素值减去前一个像素值,这样你就可以得到这个函数在这两个位置的差别或者斜率。
上面的是垂直边缘检测,以此类推,可以实现水平和斜向45度的边缘检测。
<4>Canny边缘检测Edge Detection
<5>浮雕Embossing Filter
浮雕滤波器可以给图像一种3D阴影的效果。只要将中心一边的像素减去另一边的像素就可以了。这时候,像素值有可能是负数,我们将负数当成阴影,将正数当成光,然后我们对结果图像加上128的偏移。这时候,图像大部分就变成灰色了。(转载)
这里我将灰度值调高了100
<6>均值模糊Box Filter (Averaging)
注意这里的1应该是十三分之一,这里没有处理,只是将最后输出的图片的灰度值更改了。
均值就得求平均。
你想要更模糊的效果,加大滤波器的大小即可。或者对图像应用多次模糊也可以。
<7>高斯模糊
均值模糊很简单,但不是很平滑。高斯模糊就有这个优点,所以被广泛用在图像降噪上。特别是在边缘检测之前,都会用来移除细节。高斯滤波器是一个低通滤波器。(转载)
//_src _IN_ 输入的源影像 //_dst _OUT_ 输出的目标影像 //kSize 核大小 如果大小为负数的话,那么根据输入的sigma进行计算 //ksize 大小可以为1,3,5,7,最大值为7 //计算的公式为 sigma = 0.3\*((ksize - 1)\*0.5 - 1) + 0.8 //sigmal1 X方向上的sigma值 //sigmal2 Y方向上的sigma值 //如果sigmal值为负数的话,那么使用默认的滤波过滤器 void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType )
<8>运动模糊Motion Blur
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!