OpenCV中滤波器的操作

该博客聚焦于OpenCV的图像空域滤波。介绍了图像锐化操作,通过拉普拉斯算子实现边缘锐化;还提及使用自带函数cv::filter2D进行2D滤波器运算,提高效率。此外,讲解了OpenCV自带的均值、高斯加权均值和中值滤波器的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.图像锐化操作(纯手动挡)

图像滤波分为空域滤波和频域滤波两个,这篇随笔主要针对空域滤波。

当然空域与频域之间是有一定关系的,比如均值滤波器,就是一种低通滤波,而像边缘检测,空域中一般使用的是拉普拉斯算子,其也是一种高通滤波。

大家都知道空域中的拉普拉斯算子是这样子的:

0-10
-14-1
0-10

这个表示的是纵横两个方向的二阶导,将这个算子应在图像上可以得到图像的边缘痕迹,如果把边缘再叠加到图像上,则可以是边缘更加明显,这个操作叫做锐化处理,锐化处理的算子可以表示为:

0-10
-15-1
0-10

之前我们知道使用指针来操作像素,格式为:

数据类型* 指针名称 = 矩阵名称.ptr<数据类型>(行数);

使用算子时一般我们要同时处理3行以上,我们只需要同时建立这些指针即可。

在这个操作中,我们保存原来的图像,因此我们建立的指针类型为const,同时我们新加载一幅图像,建立普通指针来操作:

复制代码
void sharpen(cv::Mat image,cv::Mat sharpen_image)
{
    int num_channels = image.channels();
</span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> r = <span style="color: #800080;">1</span>; r &lt; image.rows - <span style="color: #800080;">1</span>; r++<span style="color: #000000;">)
{
    </span><span style="color: #0000ff;">const</span> uchar* last_r = image.ptr&lt;<span style="color: #0000ff;">const</span> uchar&gt;(r - <span style="color: #800080;">1</span><span style="color: #000000;">);
    </span><span style="color: #0000ff;">const</span> uchar* curr_r = image.ptr&lt;<span style="color: #0000ff;">const</span> uchar&gt;<span style="color: #000000;">(r);
    </span><span style="color: #0000ff;">const</span> uchar* next_r = image.ptr&lt;<span style="color: #0000ff;">const</span> uchar&gt;(r + <span style="color: #800080;">1</span><span style="color: #000000;">);
    uchar</span>* output = sharpen_image.ptr&lt;uchar&gt;<span style="color: #000000;">(r);
    </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> c = num_channels; c &lt; (image.cols - <span style="color: #800080;">1</span>)*num_channels; c++<span style="color: #000000;">)
    {
        output[c] </span>=cv::saturate_cast&lt;uchar&gt; (<span style="color: #800080;">5</span> * curr_r[c]-last_r[c] - curr_r[c - <span style="color: #800080;">1</span>] - curr_r[c + <span style="color: #800080;">1</span>] -<span style="color: #000000;"> next_r[c]) ;
    }
}
sharpen_image.row(</span><span style="color: #800080;">0</span>).setTo(cv::Scalar(<span style="color: #800080;">0</span>, <span style="color: #800080;">0</span>, <span style="color: #800080;">0</span><span style="color: #000000;">));
sharpen_image.row(sharpen_image.rows</span>-<span style="color: #800080;">1</span>).setTo(cv::Scalar(<span style="color: #800080;">0</span>, <span style="color: #800080;">0</span>, <span style="color: #800080;">0</span><span style="color: #000000;">));
sharpen_image.col(</span><span style="color: #800080;">0</span>).setTo(cv::Scalar(<span style="color: #800080;">0</span>, <span style="color: #800080;">0</span>, <span style="color: #800080;">0</span><span style="color: #000000;">));
sharpen_image.col(sharpen_image.cols </span>- <span style="color: #800080;">1</span>).setTo(cv::Scalar(<span style="color: #800080;">0</span>, <span style="color: #800080;">0</span>, <span style="color: #800080;">0</span><span style="color: #000000;">));

}

复制代码

这里我使用了uchar型,好处是可以处理各种类型的图像,若是灰度图像,下面4行的cv::Scalar(0,0,0)需要变成cv::Scalar(0);若只处理RGB图像,也可以使用cv::Vec3b型:

复制代码
void sharpenRGB(cv::Mat image, cv::Mat sharpen_image)
{
    int num_channels = image.channels();
</span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> r = <span style="color: #800080;">1</span>; r &lt; image.rows - <span style="color: #800080;">1</span>; r++<span style="color: #000000;">)
{
    </span><span style="color: #0000ff;">const</span> cv::Vec3b* last_r = image.ptr&lt;cv::Vec3b&gt;(r - <span style="color: #800080;">1</span><span style="color: #000000;">);
    </span><span style="color: #0000ff;">const</span> cv::Vec3b* curr_r = image.ptr&lt;cv::Vec3b&gt;<span style="color: #000000;">(r);
    </span><span style="color: #0000ff;">const</span> cv::Vec3b* next_r = image.ptr&lt;cv::Vec3b&gt;(r + <span style="color: #800080;">1</span><span style="color: #000000;">);
    cv::Vec3b</span>* output = sharpen_image.ptr&lt;cv::Vec3b&gt;<span style="color: #000000;">(r);
    </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> c = <span style="color: #800080;">1</span>; c &lt; image.cols - <span style="color: #800080;">1</span>; c++<span style="color: #000000;">)
    {
        </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = <span style="color: #800080;">0</span>; i &lt; <span style="color: #800080;">3</span>;i++<span style="color: #000000;">)
            output[c] </span>= cv::saturate_cast&lt;uchar&gt; (<span style="color: #800080;">5</span> * curr_r[c][i] - last_r[c][i] - curr_r[c - <span style="color: #800080;">1</span>][i] - curr_r[c + <span style="color: #800080;">1</span>][i] -<span style="color: #000000;"> next_r[c][i]);
    }
}
sharpen_image.row(</span><span style="color: #800080;">0</span>).setTo(cv::Scalar(<span style="color: #800080;">0</span>, <span style="color: #800080;">0</span>, <span style="color: #800080;">0</span><span style="color: #000000;">));
sharpen_image.row(sharpen_image.rows </span>- <span style="color: #800080;">1</span>).setTo(cv::Scalar(<span style="color: #800080;">0</span>, <span style="color: #800080;">0</span>, <span style="color: #800080;">0</span><span style="color: #000000;">));
sharpen_image.col(</span><span style="color: #800080;">0</span>).setTo(cv::Scalar(<span style="color: #800080;">0</span>, <span style="color: #800080;">0</span>, <span style="color: #800080;">0</span><span style="color: #000000;">));
sharpen_image.col(sharpen_image.cols </span>- <span style="color: #800080;">1</span>).setTo(cv::Scalar(<span style="color: #800080;">0</span>, <span style="color: #800080;">0</span>, <span style="color: #800080;">0</span><span style="color: #000000;">));

}

复制代码

图像处理结果如下:

颜色对比度鲜明er。

2.使用自带函数进行2D滤波器运算

当然这个程序是纯手动挡的,OpenCV提供给了我们一些县城的函数,让我们直接可以基于算子进行运算:
cv::filter2D(输入图像名称,输出图像名称,输入图像名称.depth(),kernel);

kernel指代内核,即算子模型,其定义方法为:


cv::Mat kernel(3(尺寸),3(尺寸),CV_32F(浮点数),cv::Scalar(0)(所有元素初始化为0);

kernel.at<float>(1,1)=5.0;

kernel.at<float>(0,1)=-1.0;

kernel.at<float>(1,0)=-1.0;

kernel.at<float>(2,1)=-1.0;

kernel.at<float>(1,2)=-1.0;

这样可以提高效率,并易于改变算子进行新的运算。

3.自带的滤波函数

3.1均值滤波器

均值滤波器在OpenCV中用blur(模糊)定义,函数为:

cv::blur(输入图片名称,输出图片名称,cv::Size(5(尺寸),5(尺寸)));

复制代码
int _tmain(int argc, _TCHAR* argv[])
{
    cv::Mat image;
    cv::Mat result;
    image = cv::imread("D://OpenCV//yedanshu.jpg");
    cv::namedWindow("Original");
    cv::blur(image, result, cv::Size(5, 5));
    cv::namedWindow("Filtered");
    cv::imshow("Original", image);
    cv::imshow("Filtered", result);
    cv::waitKey(0);
    return 0;
}
复制代码

 

3.2高斯加权的均值滤波:

这是为了让临近的像素具有更高的权值,所以在清晰度上相比于一般均值滤波有很大突破,实现代码为:

cv::GaussianBlur(image, result, cv::Size(5, 5),1.5); //1.5代表方差

3.3中值滤波器

对于椒盐噪声来说,最好的处理办法即是中值滤波,中值滤波在OpenCV中也有直接的办法:

cv::medianBlur(输入图片名称,输出图片名称,int 滤波器尺寸);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值