OpenCV 中的图像处理 004_平滑图像

本文主要内容来自于 OpenCV-Python 教程OpenCV 中的图像处理 部分,这部分的全部主要内容如下:

目标

学习:

  • 使用各种低通滤波器模糊图像
  • 将定制过滤器应用于图像(2D 卷积)

2D卷积(图像过滤)

与一维信号一样,图像也可以使用各种低通滤波器 (LPF)、高通滤波器 (HPF) 等进行滤波。LPF 有助于消除噪声、模糊图像等。HPF 过滤器有助于在图像中找到边缘。

OpenCV 提供了一个函数 cv.filter2D()来将内核与图像进行卷积。例如,我们将在图像上尝试平均滤波器。一个 5x5 平均滤波器内核如下所示:

K = \frac{1}{25} \begin{bmatrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \end{bmatrix}

操作是这样的:保持这个内核高于一个像素,将所有低于这个内核的 25 个像素相加,取平均值,然后用新的平均值替换中心像素。对图像中的所有像素继续该操作。试试这段代码并检查结果:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

def image_filtering():
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    img = cv.imread(cv.samples.findFile('opencv-logo.png'))

    kernel = np.ones((5, 5), np.float32) / 25
    dst = cv.filter2D(img, -1, kernel)

    row, col, _ = img.shape

    edge = np.full((row, 10, 3), (255, 255, 255), np.uint8);
    images = [img, edge, dst]
    dst = cv.hconcat(images)

    cv.imshow("Image", dst)

    cv.waitKey(-1)
    cv.destroyAllWindows()


if __name__ == "__main__":
    image_filtering()

结果如下:

Image

图像模糊(图像平滑)

图像模糊是通过将图像与低通滤波器内核进行卷积来实现的。它对于去除噪声很有用。它实际上从图像中去除了高频内容(比如噪声,边缘)。所以在这个操作中边缘有点模糊(也有不模糊边缘的模糊技术)。OpenCV 提供了四种主要的模糊技术类型。

1. 平均

这是通过将图像与归一化框滤波器进行卷积来完成的。它只是取内核区域下所有像素的平均值并替换中心元素。这通过函数 cv.blur()cv.boxFilter() 完成。检查关于内核的文档来了解更多细节。我们应该指定内核的宽度和高度。一个 3x3 归一化框滤波器将看起来像下面这样:

K = \frac{1}{9} \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix}

注意
如果不想使用归一化的框滤波器,则使用 cv.boxFilter()。给函数传递一个参数 normalize=False

看一下下面的示例演示,它使用一个 5x5 大小的内核:

def averaging_filter():
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    img = cv.imread(cv.samples.findFile('opencv-logo-white.png'))

    blur = cv.blur(img, (5, 5))

    plt.subplot(121), plt.imshow(img), plt.title('Original')
    plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(blur), plt.title('Blurred')
    plt.xticks([]), plt.yticks([])
    plt.show()


if __name__ == "__main__":
    averaging_filter()

结果如下:


Image

高斯模糊

在这个方法中,不是使用框滤波器,而是使用一个高斯内核。它通过函数 cv.GaussianBlur() 完成。我们应该指定内核的宽度和高度,它们应该是正奇数。我们还应该指定 X 和 Y 方向的标准差,sigmaX 和 sigmaY。如果只指定了 sigmaX,sigmaY 将取与 sigmaX 相同的值。如果两者都为零,则它们根据内核大小计算得出。高斯模糊在从图像中移除高斯噪声非常有效。

如果你想,你可以使用函数 cv.getGaussianKernel() 创建一个高斯内核。

上面的代码可以修改以用于高斯模糊:

    blur = cv.GaussianBlur(img, (5, 5), 0)

如果使用函数 cv.getGaussianKernel(),则需要如下的代码:

    kernel = cv.getGaussianKernel(5, 0)
    kernel_2D = kernel @ kernel.transpose()
    blur = cv.filter2D(img, -1, kernel_2D)

结果如下:


Image

3. 中值模糊

这里,函数 cv.medianBlur() 取内核区域下所有像素的中值,并将中心元素替换为该中值。这对图像中的椒盐噪声非常有效。有趣的是,在上述滤波器中,中心元素是新计算的值,可能是图像中的像素值或新值。但是在中值模糊中,中心元素总是被图像中的某个像素值替换。它有效地降低了噪音。它的内核大小应该是一个正奇数。

在这个演示中,我为原始图像添加了 50% 的噪点并应用了中值模糊。添加噪点,通过如下的 salt_and_pepper(image, n) 函数完成。检查结果:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
import random

def salt_and_pepper(image, n):
    print(image.shape)
    for i in range(int(n / 2)):
        row = random.randint(0, image.shape[0] - 1)
        col = random.randint(0, image.shape[1] - 1)

        write_black = random.randint(0, 2)
        if write_black == 0:
            image[row][col] = (255, 255, 255)
        else:
            image[row][col] = (0, 0, 0)
    return image


def median_blurring():
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    img = cv.imread(cv.samples.findFile('opencv-logo-white.png'))

    img = salt_and_pepper(img, img.shape[0] * img.shape[1])

    median = cv.medianBlur(img, 5)

    plt.subplot(121), plt.imshow(img), plt.title('Original')
    plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(median), plt.title('Blurred')
    plt.xticks([]), plt.yticks([])
    plt.show()


if __name__ == "__main__":
    median_blurring()

结果如下:

Image

4. 双边滤波

cv.bilateralFilter() 函数在保持边缘锐利的同时去除噪声非常有效。但与其它滤波器相比,这个操作速度较慢。我们已经看到高斯滤波器采用像素周围的邻域,并找到其高斯加权平均值。这个高斯滤波器是一个单独的空间函数,即在滤波时考虑附近的像素。它不考虑像素是否具有几乎相同的强度。它不考虑像素是否是边缘像素。所以它也模糊了边缘,这是我们不想做的。

双边滤波在空间上也采用了高斯滤波器,但多了一个高斯滤波器,它是像素差的函数。空间的高斯函数确保只考虑附近的像素进行模糊处理,而强度差异的高斯函数确保只考虑那些与中心像素具有相似强度的像素进行模糊处理。所以它保留了边缘,因为边缘处的像素会有很大的强度变化。

下面的示例显示了双边滤波器的使用(有关参数的详细信息,请访问文档)。

def bilateral_blurring():
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    img = cv.imread(cv.samples.findFile('bilateral.jpg'))

    img = img[0:img.shape[0], 0:int(img.shape[1] / 2)]

    blur = cv.bilateralFilter(img, 9, 75, 75)

    images = [img, blur]
    dest = cv.hconcat(images)

    cv.imshow("Image", dest)
    cv.waitKey(-1)
    cv.destroyAllWindows()


if __name__ == "__main__":
    bilateral_blurring()

结果如下:


Image

看,表面上的纹理消失了,但边缘依然存在。

其它资源

  1. 关于 双边滤波 的详细信息

练习

参考文档

Smoothing Images

使用带有高斯核的cv2.GaussianBlur和cv2.filter2D的不同结果?

利用OpenCV给彩色图像添加椒盐噪声的方法

使用Python-OpenCV向图片添加噪声的实现(高斯噪声、椒盐噪声)

Python 随机数生成

Done.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容