OpenCV(4)-图像掩码操作(卷积)--平滑处理

时间:2022-12-24 16:18:57

卷积定义

矩阵的掩码操作即对图像进行卷积。对图像卷积操作的意义为:邻近像素对(包括该像素自身)对新像素的影响;影响大小取决于卷积核对应位置值得大小。

例如:图像增强可以使用

\[I(i,j)=5*I(i,j)-[I(i-1,j) + I(i+1,j) + I(i, j-1) + I(i, j+1)]
\]

用代码实现

 void Sharpen(const Mat& myImage, Mat& Result)
{
CV_Assert(myImage.depth() == CV_8U); // 仅接受uchar图像
Result.create(myImage.size(), myImage.type());
const int nChannels = myImage.channels(); for (int j = 1; j < myImage.rows - 1; ++j)//从第一行开始,而不是0;到rows-2行结束
{
const uchar* previous = myImage.ptr<uchar>(j - 1);//上一行
const uchar* current = myImage.ptr<uchar>(j);
const uchar* next = myImage.ptr<uchar>(j + 1);//下一行 uchar* output = Result.ptr<uchar>(j); for (int i = nChannels; i < nChannels*(myImage.cols - 1); ++i)
{
*output++ = saturate_cast<uchar>(5 * current[i]
- current[i - nChannels] - current[i + nChannels] - previous[i] - next[i]);
}
} //边缘处理。边缘没有卷积,所以边缘赋值为原图像对应像素的值。 //先处理上和下
uchar* output_top = Result.ptr<uchar>(0);
const uchar* origin_top = myImage.ptr<uchar>(0);
uchar* output_bottom = Result.ptr<uchar>(myImage.rows - 1);
const uchar* origin_bottom = Result.ptr<uchar>(myImage.rows - 1);
for (int i = 0; i < nChannels * myImage.cols - 1; ++i){
*output_top++ = *origin_top++;
*output_bottom++ = *origin_bottom++;
} //左和右 分别有nChannel
for (int i = 0; i < myImage.rows; ++i){
const uchar* origin_left = myImage.ptr<uchar>(i);
uchar* output_left = Result.ptr<uchar>(i);
const uchar* origin_right = origin_left + nChannels*(myImage.cols - 1);
uchar* output_right = output_left + nChannels*(myImage.cols - 1);
for (int j = 0; j < nChannels; ++j){
*output_left++ = *origin_left++;
*output_right++ = *origin_right++;
}
}
}

卷积在图像处理中应用很广泛,可以使用OpenCV自带函数

void filter2D(InputArray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor=Point(-1,-1), double delta=0, int borderType=BORDER_DEFAULT )

OpenCV(4)-图像掩码操作(卷积)--平滑处理

滤波器

滤波器中,所有元素和相加后应该等于1。如果大于1,则图像会变亮,如果小于1,图像变暗。

平滑滤波器

平滑滤波器的作用是去除图像中一些不重要的细节,减小噪声。可以分为线性和非线性2大类:

1、线性平滑滤波器:均值波滤器

2、非线性平滑滤波器:最大值滤波、中值滤波、最小值滤波。

线性平滑滤波

线性平滑滤波可以减小“尖锐”,减小噪声;因为图像边缘是有“尖锐”变换引起的,所以也就模糊了边缘。

\[ \frac{1}{9}\left[
\begin{matrix}
1 & 1 & 1 \\
1 & 1 & 1 \\
1 & 1 & 1
\end{matrix}
\right] \tag{3}
\]

上面这个滤波器,各个像素的值贡献相同,是均值滤波,在OpenCV有对应函数。

void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )

有时各个像素的重要性不同,可以使用:

\[ \frac{1}{16}\left[
\begin{matrix}
1 & 2 & 1 \\
2 & 4 & 2 \\
1 & 2 & 1
\end{matrix}
\right] \tag{3}
\]

上面的滤波器表面中间和其挨着的像素贡献大一些。

非线性滤波

线性滤波是对滤波器区域内各个像素点加权求和,结果和原图像滤波区域有一个线性关系。非线性滤波则不然;基于统计排序的非线性滤波分为:最大值滤波、中值滤波、最小值滤波。顾名思义,上述三种滤波器是分别取卷积核区域内最大像素点值、中值像素点值、最小像素点值。

中值滤波:

中值滤波是对卷积核区域内像素排序,取中位数,只有奇数才有中位数,所有卷积核只能为3、5、7……这样的奇数。中值滤波在去除噪声的同时,可以比较好的保留图像细节(尖锐等),能够有效去除脉冲噪声(椒盐噪声)。

void medianBlur(InputArray src, OutputArray dst, int ksize)

高斯滤波:卷积核是按照高斯分布的

\[G(x,y)=Ae^{\frac{-(x-\mu_x)^2}{2\sigma_x^2}+\frac{-(x-\mu_y)^2}{2\sigma_y^2}}
\]

和均值像素差值大的像素,对结果贡献较小;离均值“近”的像素,对结果贡献较大。

函数为:

void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )

双边滤波:

前面提高的滤波都是知识考虑了图像的空间关系,即卷积核区域内的空域关系,没有考虑像素间的关系。因此在平滑时,会模糊整幅图像;双边滤波不仅考虑了图像的空域关系,还考虑了图像间像素值的差异关系。可以参考这里

OpenCV对应函数

void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT )

实验代码

#include <iostream>
#include <opencv2/opencv.hpp> using namespace std;
using namespace cv; void Sharpen(const Mat& myImage, Mat& Result)
{
CV_Assert(myImage.depth() == CV_8U); // 仅接受uchar图像 Result.create(myImage.size(), myImage.type());
const int nChannels = myImage.channels(); for (int j = 1; j < myImage.rows - 1; ++j)//从第一行开始,而不是0;到rows-2行结束
{
const uchar* previous = myImage.ptr<uchar>(j - 1);//上一行
const uchar* current = myImage.ptr<uchar>(j);
const uchar* next = myImage.ptr<uchar>(j + 1);//下一行 uchar* output = Result.ptr<uchar>(j); for (int i = nChannels; i < nChannels*(myImage.cols - 1); ++i)
{
*output++ = saturate_cast<uchar>(5 * current[i]
- current[i - nChannels] - current[i + nChannels] - previous[i] - next[i]);
}
} //边缘处理。边缘没有卷积,所以边缘赋值为原图像对应像素的值。 //先处理上和下
uchar* output_top = Result.ptr<uchar>(0);
const uchar* origin_top = myImage.ptr<uchar>(0);
uchar* output_bottom = Result.ptr<uchar>(myImage.rows - 1);
const uchar* origin_bottom = Result.ptr<uchar>(myImage.rows - 1);
for (int i = 0; i < nChannels * myImage.cols - 1; ++i){
*output_top++ = *origin_top++;
*output_bottom++ = *origin_bottom++;
} //左和右 分别有nChannel
for (int i = 0; i < myImage.rows; ++i){
const uchar* origin_left = myImage.ptr<uchar>(i);
uchar* output_left = Result.ptr<uchar>(i);
const uchar* origin_right = origin_left + nChannels*(myImage.cols - 1);
uchar* output_right = output_left + nChannels*(myImage.cols - 1);
for (int j = 0; j < nChannels; ++j){
*output_left++ = *origin_left++;
*output_right++ = *origin_right++;
}
}
} int main(int argc, char* argv[]){
const char* path = "";
Mat img = imread(path);
if (img.empty())
{
cout << "error";
return -1;
}
imshow("原图像", img); //均值滤波
Mat blur_mat;
blur(img, blur_mat, Size(3, 3));
imshow("均值滤波", blur_mat); //线性非均值滤波
Mat kern = (Mat_<float>(3, 3) << 1, 2, 1,
2, 4, 2,
1, 2, 1) / 16;
Mat blur2_mat;
filter2D(img, blur2_mat, img.depth(), kern);
imshow("线性非均值滤波", blur2_mat); //中值滤波
Mat memedian_mat;
medianBlur(img, memedian_mat, 3);
imshow("中值滤波", memedian_mat); //高斯滤波
Mat Gaussian_mat;
GaussianBlur(img, Gaussian_mat, Size(3, 3), 0, 0);
imshow("高斯滤波", Gaussian_mat); //双边滤波 Mat bilateral_mat;
bilateralFilter(img, bilateral_mat, 25, 25 * 2, 25 / 2);
imshow("双边滤波", bilateral_mat);
waitKey();
return 0; }

OpenCV(4)-图像掩码操作(卷积)--平滑处理的更多相关文章

  1. OpenCV&lpar;5&rpar;-图像掩码操作(卷积)-锐化

    锐化概念 图像平滑过程是去除噪声的过程.图像的主要能量在低频部分,而噪声主要集中在高频部分.图像的边缘信息主要也在高频部分,在平滑处理后,将会丢不部分边缘信息.因此需要使用锐化技术来增强边缘. 平滑处 ...

  2. opencv——图像掩码操作

    使用opencv通过掩码去扣取图像中感兴趣的区域 步骤: 1.读取一张图片 2.转换颜色格式为hsv 3.设置要扣取区域颜色的上下门限 4.从原始图像中获取感兴趣区域的掩码 5.使用掩码和原始图像做云 ...

  3. OpenCV中图像算术操作与逻辑操作

    OpenCV中图像算术操作与逻辑操作 在图像处理中有两类最重要的基础操作各自是图像点操作与块操作.简单点说图像点操作就是图像每一个像素点的相关逻辑与几何运算.块操作最常见就是基于卷积算子的各种操作.实 ...

  4. OpenCV学习笔记:矩阵的掩码操作

    矩阵的掩码操作很简单.其思想是:根据掩码矩阵(也称作核)重新计算图像中每个像素的值.掩码矩阵中的值表示近邻像素值(包括该像素自身的值)对新像素值有多大影响.从数学观点看,我们用自己设置的权值,对像素邻 ...

  5. Opencv中图像的遍历与像素操作

    Opencv中图像的遍历与像素操作 OpenCV中表示图像的数据结构是cv::Mat,Mat对象本质上是一个由数值组成的矩阵.矩阵的每一个元素代表一个像素,对于灰度图像,像素是由8位无符号数来表示(0 ...

  6. opencv图像阈值操作

    使用threshold方法和adaptivethreshold方法对图像进行阈值分割操作. 1.使用threshold方法,设置一个阈值,将大于阈值的值变换为最大值,小于阈值的值变换为0. #-*- ...

  7. 【图像处理】OpenCV&plus;Python图像处理入门教程(七)图像形态学操作

    图像形态学主要从图像内提取分量信息,该分量信息通常对表达图像的特征具有重要意义.例如,在车牌号码识别中,能够使用形态学计算其重要特征信息,在进行识别时,只需对这些特征信息运算即可.图像形态学在目标视觉 ...

  8. OpenCV在矩阵上的卷积

    转载请注明出处!!!http://blog.csdn.net/zhonghuan1992 OpenCV在矩阵上的卷积 在openCV官网上说是戴面具,事实上就是又一次计算一下矩阵中的每个value,那 ...

  9. opencv 6 图像轮廓与图像分割修复 3 图像的矩,分水岭,图像修补

    图像的矩 矩的计算:moments()函数 计算轮廓面积:contourArea()函数 #include "opencv2/highgui/highgui.hpp" #inclu ...

随机推荐

  1. Hawk 6&period; 编译和扩展开发

    Hawk是开源项目,因此任何人都可以为其贡献代码.作者也非常欢迎使用者能够扩展出更有用的插件. 编译 编译需要Visual Stuido,版本建议使用2015, 2010及以上没有经过测试,但应该可以 ...

  2. JAVA输入一个整数,求出其所有质因数

    首先得求出能整除A的数,再判断I是否是质数!!! import java.util.*; public class aa { public static void main(String[] args ...

  3. SVN安装与配置 SVN整合MyEclipse

    SVN安装: 1.安装服务器 ######### 安装文件:SVN服务器############### # http://www.collab.net/downloads/subversion # C ...

  4. Vijos P1063 迎春舞会之交谊舞 DP

    题目链接:https://vijos.org/p/1063 题意:有n(n <= 100)行,每行有2*i-1个可显字符'#'与'-',组成一个倒三角形,问由'-'组成的最大三角形的'-'的个数 ...

  5. sql 2000 &quot&semi;无法执行查询&comma;因为一些文件缺少或未注册&quot&semi;的

    sql 2000 "无法执行查询,因为一些文件缺少或未注册"的解决办法 在SQL server 2000中打开表查看数据的时候,提示说“无法执行查询,因为一些文件缺少或未注册” 用 ...

  6. Another attempt about LSI

    Last week I was here Natural Language Processing in NZ. Someone asked a question, is there any exist ...

  7. 怎样成为一个游戏制作人——第五章&colon;使用GGE图形库来写游戏

    怎样成为一个游戏制作人--第五章:使用GGE图形库来写游戏 前言: 细致想了一下,来看博客的一般都是有自学能力的了.C++基础多少也会有一些了. 于是决定以下的章节.会教大家做一些小游戏. 来巩固自己 ...

  8. Delphi 的绘图功能&lbrack;10&rsqb; - TFONT 类

    Delphi 的绘图功能[10] - TFONT 类 ;DEFAULT_CHARSET     = ;SYMBOL_CHARSET      = ;SHIFTJIS_CHARSET    = ;HAN ...

  9. base 镜像 - 每天5分钟玩转容器技术(10)

    上一节我们介绍了最小的 Docker 镜像,本节讨论 base 镜像. base 镜像有两层含义: 不依赖其他镜像,从 scratch 构建. 其他镜像可以之为基础进行扩展. 所以,能称作 base ...

  10. ASP&period;NET Core 使用 URL Rewrite 中间件实现 HTTP 重定向到 HTTPS

    在传统 ASP.NET 程序中,我们可以通过配置 IIS 的“URL 重写”功能实现将 HTTP 请求重定向为 HTTPS .但是该方法在 ASP.NET Core 应用中不再工作.在 ASP.NET ...