若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/104458554
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)
上一篇:《OpenCV开发笔记(十三):OpenCV图像对比度、亮度的调整》
下一篇:《OpenCV开发笔记(十五):算法基础之线性滤波-均值滤波》
本篇开始正式进入算法学习,学习的算法都是OpenCV提供的基础算法,实际应用中的一些图片处理算法是需要各种基础算法再加上开发者其他的逻辑数据处理多环节综合处理后得到的最终效果的整个过程。
即将接触到的基础卷积操作。
图像平滑是指用于突出图像的宽大区域、低频成分、主干部分或抑制图像噪声和干扰高频成分的图像处理方法,目的是使图像亮度平缓渐变,减小突变梯度,改善图像质量。
图像平滑的方法包括:插值方法,线性平滑方法,卷积法等等。这样的处理方法根据图像噪声的不同进行平滑,比如椒盐噪声,就采用线性平滑方法。
图像滤波,指再尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,起处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。
图像滤波的目的有两个:一个是抽出对象的特征作为图像识别的特征模式;另一个是为适应图像处理的要求,消除图像数字化时所混入的噪声。
滤波器类似于一个加权系数的窗口,当使用这个滤波器平滑处理图像时,就把这个窗口放到图像之上,透过这个窗口来看图像。
滤波器有很多种类,OpenCV也提供了多种滤波器,常用的线性滤波器五中:
线性滤波器:线性滤波器经常用于消除输入信号中不想要的频率或者从许多频率中选择一个想要的频率。
几种常见的线性滤波器如下:
滤波是信号中特定波段频率滤除的操作,是抑制和防止干扰的一项重要措施。滤波可分为低通滤波和高通滤波,高斯滤波是指用高斯函数作为滤波函数的滤波操作,高斯低通是模糊操作,高斯高通是瑞锐化。
领域算子(局部算子)是利用给定像素周围的像素值决定次像素的最终输出的一种算子。而线性领域滤波就是一种常用的领域算子,像素的输出值取决于输入像素的加权和。
归一化normalize,就是把要处理的量都缩放到一个范围内,比如(0,1),以便统一处理和直观量化。
方框滤波是使用方框滤波器来模糊一张图片。
方框滤波的函数原型如下:
void boxFilter(InputArray src,
OutputArray dst,
int ddepth,
Size ksize,
Point anchor=Point(-1, -1),
bool normalize = true,
int borderType = BORDER_DEFALT)
其中:
void OpenCVManager::testBoxFilter()
{
QString fileName1 = "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/1.jpg";
cv::Mat matSrc = cv::imread(fileName1.toStdString());
cv::String windowName = _windowTitle.toStdString();
cvui::init(windowName);
if(!matSrc.data)
{
qDebug() << __FILE__ << __LINE__
<< "Failed to load image:" << fileName1;
return;
}
cv::Mat dstMat;
dstMat = cv::Mat::zeros(matSrc.size(), matSrc.type());
cv::Mat windowMat = cv::Mat(cv::Size(dstMat.cols * 3, dstMat.rows),
matSrc.type());
bool isBoxFilter = true;
int ksize = 3; // 核心大小
int anchor = -1; // 锚点, 正数的时候必须小于核心大小,即:-1 <= anchor < ksize
cvui::window(windowMat, dstMat.cols, 0, dstMat.cols, dstMat.rows, "settings");
while(true)
{
windowMat = cv::Scalar(0, 0, 0);
// 原图先copy到左边
cv::Mat leftMat = windowMat(cv::Range(0, matSrc.rows),
cv::Range(0, matSrc.cols));
cv::addWeighted(leftMat, 1.0f, matSrc, 1.0f, 0.0f, leftMat);
// 中间为调整方框滤波参数的相关设置
// 是否方框滤波
cvui::checkbox(windowMat, 375, 10, "boxFilter", &isBoxFilter);
cvui::printf(windowMat, 375, 40, "ksize");
cvui::trackbar(windowMat, 375, 50, 165, &ksize, 1, 10);
if(anchor >= ksize)
{
anchor = ksize - 1;
}
cvui::printf(windowMat, 375, 100, "anchor");
cvui::trackbar(windowMat, 375, 110, 165, &anchor, -1, ksize-1);
cv::boxFilter(matSrc,
dstMat,
-1,
cv::Size(ksize, ksize),
cv::Point(anchor, anchor),
isBoxFilter);
// 效果图copy到右边
// 注意:rang从位置1到位置2,不是位置1+宽度
cv::Mat rightMat = windowMat(cv::Range(0, matSrc.rows),
cv::Range(matSrc.cols * 2, matSrc.cols * 3));
cv::addWeighted(rightMat, 0.0f, dstMat, 1.0f, 0.0f, rightMat);
// 更新
cvui::update();
// 显示
cv::imshow(windowName, windowMat);
// esc键退出
if(cv::waitKey(25) == 27)
{
break;
}
}
}
对应版本号v1.9.0
原因:
锚点的位置(x和y)不能超过或者等于内核的大小,opencv会错误宕机(可以通俗理解为:数组越界宕机)
解决方法:
锚点可以无限小,但是到-1再往下下已无意义,当时-1是,就代表中心,如x为-1代表x为内核中心,对应y也是,一般默认是cv::Point(-1,-1)就代表内核的中心。
但是有效果的范围大小应该小于ksize的大小。
-1 <= 锚点x < 内核ksize的x
-1 <= 锚点y < 内核ksize的y。
上一篇:《OpenCV开发笔记(十三):OpenCV图像对比度、亮度的调整》
下一篇:《OpenCV开发笔记(十五):算法基础之线性滤波-均值滤波》
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/104458554