OpenCV-2.2 图像平滑
程序员文章站
2022-05-25 13:55:57
...
目标
在本节教程中我们将学习如何使用不同的线性滤波器对图像进行平滑:
- blur()
- GaussianBlur()
- medianBlur()
- bilateralFilter()
理论
:
下述内容引用自书籍Computer Vision: Algorithms and Applications。
- 平滑同时也称作模糊,是一种常用的图像处理操作
- 需要对图像进行平滑处理的原因有很多,本教程中对图像进行平滑处理用于降低图像的噪声。
- 我们将使用对图像进行滤波操作实现平滑。最常见的滤波器类型是线性滤波器:输出像素值取决于所有输入像素值的加权求和。
h(k,l) 为核函数,里面包含了滤波器的各个系数。 - 滤波器的种类很多,我们只介绍最长用的几种
归一化块滤波器(Normalized Box Filter)
- 这是一种最简单的滤波器! 每一个输出像素的值是像素周围值的均值(所有领域像素的权重一致)
- 该核如下图所示:
高斯滤波器(Gaussian Filter)
- 该滤波器可能是最实用的滤波器(尽管不是最快的)。高速滤波器是针对每个输入像素施加一个高斯核,并且求和得到输出像素值。
- 为了直观的看出高斯核是什么样子 ,下面是一张1D高斯核的图:
由此假设我们的图像是1D的,我们可以观察到中间像素的值拥有最大的权重,随着距离中心像素越远,所占的权重越低
中值滤波器(Median Filter)
中值滤波器的原理是将像素值用该像素值周围像素值排序之后中间值替代。
双边滤波器(Bilateral Filter)
- 到目前位置我们介绍了一些滤波器,他们主要用于平滑图像。然和有时候滤波器不仅把噪声消除了,同时也丢失了部分的图像边缘信息。这种情况我们可以使用双边滤波器。
- 类比我们的高斯滤波器,双边滤波器同样是考虑不同的领域像素所占权重不一样,不过在这些权重有两部分组成。具体可以参考该文章
代码
- 代码实现的功能
- 载入图像
- 对图像进行四种不同的滤波处理并依次显示
class SmoothingRun{
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31;
Mat src =new Mat(),dst =new Mat();
String windowName = "Filter Demo 1";
public void run()
{
String filename = "images/lena.jpg";
src = imread(filename);
if (displayCaption("Original Image")!= 0 ){
System.exit(0);
}
dst = src.clone();
if (displayDst(DELAY_CAPTION)!=0){
System.exit(0);
}
if (displayCaption("Homogeneous Blur")!=0){
System.exit(0);
}
for (int i = 1; i < MAX_KERNEL_LENGTH; i+=2) {
blur(src,dst,new Size(i,i),new Point(-1,-1));
displayDst(DELAY_BLUR);
}
if( displayCaption( "Gaussian Blur" ) != 0 ) { System.exit(0); }
for (int i = 1; i < MAX_KERNEL_LENGTH; i+=2) {
GaussianBlur(src,dst,new Size(i,i),0,0);
displayDst(DELAY_BLUR);
}
if( displayCaption( "Median Blur" ) != 0 ) { System.exit(0); }
for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
medianBlur(src, dst, i);
displayDst(DELAY_BLUR);
}
if( displayCaption( "Bilateral Blur" ) != 0 ) { System.exit(0); }
for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
bilateralFilter(src, dst, i, i * 2, i / 2);
displayDst(DELAY_BLUR);
}
displayCaption( "Done!" );
System.exit(0);
}
private int displayCaption(String caption){
dst = Mat.zeros(src.size(),src.type());
putText(dst,caption,new Point(src.cols()/4,src.rows()/2),
FONT_HERSHEY_COMPLEX,
1,
new Scalar(255,255,255));
return displayDst(DELAY_CAPTION);
}
int displayDst(int delay){
imshow(windowName,dst);
int c = waitKey(delay);
if (c>=0)
{
return -1;
}
return 0;
}
}
public class Main {
public static void main(String[] args) {
System.loadLibrary("libs/"+ Core.NATIVE_LIBRARY_NAME);
new SmoothingRun().run();
}
}
解释
让我们关注下有关平滑的操作,其他代码在之前的教程中已经掌握了。
归一化块滤波(Normalized Block Filter)
- OpenCV提供blur()方法实现该滤波器。我们着重说明下四个参数(其他参数参考手册):
- src:源图像
- dst:目标图像
- Size(w,h):定义核的大小,分别宽度为w,高度h
- Point(-1,-1):定义锚点,也就是核计算的时候输出的位置,如果为负数则代表核的中心为锚点。
for (int i = 1; i < MAX_KERNEL_LENGTH; i+=2) {
blur(src,dst,new Size(i,i),new Point(-1,-1));
displayDst(DELAY_BLUR);
}
高斯滤波(Gaussian Filter)
- OpenCV提供 GaussianBlur()方法实现该滤波器。我们着重说明下四个参数(其他参数参考手册):
- src:源图像
- dst:目标图像
- Size(w,h):定义核的大小,分别宽度为w,高度h,高度核宽度必须为整奇数,否则将自动由 σx 和 σy参数计算。
- σx:x方向上的标准差,0代表由核大小计算
- σy:y方向上的标准差,0代表由核大小计算
for (int i = 1; i < MAX_KERNEL_LENGTH; i+=2) {
GaussianBlur(src,dst,new Size(i,i),0,0);
displayDst(DELAY_BLUR);
}
中值滤波(Median Filter)
- OpenCV提供 medianBlur()方法实现该滤波器。我们着重说明下三个参数:
- src:源图像
- dst:目标图像
- i:定义核的大小 ,为奇数正整数
for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
medianBlur(src, dst, i );
displayDst(DELAY_BLUR);
}
双边滤波(Bilateral Filter)
- OpenCV提供 bilateralFilter()方法实现该滤波器。我们使用五个参数:
- src:源图像
- dst:目标图像
- d:每个像素领域直径
- σColor:颜色空间标准差
- σSpace:坐标空间标准差
for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
bilateralFilter(src, dst, i, i * 2, i / 2);
displayDst(DELAY_BLUR);
}
结果
自行代码验证