【干货】计算机视觉实战系列08——用Python做图像处理

【导读】在前面几讲中,专知成员Hui介绍了PIL、Matplotlib、Numpy、SciPy等Python图像处理的工具包。这一讲中,我们将介绍一个具体的实例——图像去噪,作为前面几讲的总结。

【干货】计算机视觉实战系列01——用Python做图像处理(基本的图像操作和处理)

【干货】计算机视觉实战系列02——用Python做图像处理(Matplotlib基本的图像操作和处理)

【干货】计算机视觉实战系列03——用Python做图像处理(Numpy基本操作和图像灰度变换)

【干货】计算机视觉实战系列04——用Python做图像处理(图像的缩放、均匀操作和直方图均衡化)

【干货】计算机视觉实战系列05——用Python做图像处理(主成分分析)

【干货】计算机视觉实战系列06——用Python做图像处理(图像高斯模糊分析)

【干货】计算机视觉实战系列07——用Python做图像处理(SciPy库的应用——图像导数实战)

图像去噪

图像去噪

图像去噪是给定一幅受损图像,在去除图像噪声的同时,尽可能地保留图像细节和结构的处理技术。图像去噪对于很多应用来说都非常重要;这些应用范围很广,小到让你的照片看起来更漂亮,大到提高卫星图像的质量。我们这里使用ROF去噪模型,ROF模型具有很好的性质;使处理后的图像更加平滑,同时保留图像边缘和结构信息。

ROF模型的数学基础和处理技巧非常高深,有兴趣的读者可以自学深入了解,本文只是做一个简单介绍。

ROF模型

一副图像I的全变差(Total Variation,TV)定义为梯度范数之和。

在连续表示的情况下,全变差表示为:

在离散表示的情况下,全变差表示为:

其中,上面的式子是在所有图像坐标x=[x,y]上取和。

在ROF模型里,目标函数是为了寻找降噪后的图像U,使下式最小:

其中范数||I-U||是去噪后图像U和原始图像I差异的度量。也就是说,本质上该模型使去噪后的图像像素值“平坦变化”,但是在图像区域的边缘上,允许图像像素值“跳跃变化”。

代码

from numpy import *
from numpy import linalg as LA
from numpy import random
from scipy.ndimage import filters
from scipy.misc import imsave
from PIL import Image


def denoise(im, U_init, tolerance=0.1, tau=0.125, tv_weight=100):
    m, n = im.shape  # 噪声图像的大小
    U = U_init
    Px = im  # 对偶域的x 分量
    Py = im  # 对偶域的y 分量
    error = 1

    while (error > tolerance):
        Uold = U

        # 原始变量的梯度
        GradUx = roll(U, -1, axis=1) - U  # 变量U 梯度的x 分量
        GradUy = roll(U, -1, axis=0) - U  # 变量U 梯度的y 分量

        # 更新对偶变量  
        PxNew = Px + (tau / tv_weight) * GradUx
        PyNew = Py + (tau / tv_weight) * GradUy
        NormNew = maximum(1, sqrt(PxNew ** 2 + PyNew ** 2))

        Px = PxNew / NormNew  # 更新x 分量(对偶)
        Py = PyNew / NormNew  # 更新y 分量(对偶)

        # 更新原始变量
        RxPx = roll(Px, 1, axis=1)
        RyPy = roll(Py, 1, axis=0)

        DivP = (Px - RxPx) + (Py - RyPy)  # 对偶域的散度
        U = im + tv_weight * DivP  # 更新原始变量

        # 更新误差
        error = linalg.norm(U - Uold) / sqrt(n * m)
    return U, im - U


im = zeros((500, 500))
im[100:400, 100:400] = 128
im[200:300, 200:300] = 255
im = im + 30 * random.standard_normal((500, 500))

U, T = denoise(im, im)
G = filters.gaussian_filter(im, 10)

from scipy.misc import imsave

imsave('test1.pdf', U)
imsave('test2.pdf', G)

输出结果如下:

(a)

(b)

图中(a)为经过高斯模糊的图像,(b)为经过ROF模型去噪后的图像

在上面代码中,输入为含有噪声的灰度图像、U 的初始值、TV 正则项权值、步长、停业条件;输出:去噪和去除纹理后的图像、纹理残留。im.shape表示噪声图像的大小;Px和Py分别表示对偶域的x分量和对偶域的y分量;GtandUx和GrandUy分别表示变量U梯度的x分量和y分量; RxPx = roll(Px,1,axis=1)和 RyPy = roll(Py,1,axis=0)分别表示对x 分量进行向右x 轴平移和对y 分量进行向右y 轴平移;denoise方法最终返回去早后的图像和纹理残余。

在这个例子中,我们使用了roll() 函数。顾名思义,在一个坐标轴上,它循环“滚动”数组中的元素值。该函数可以非常方便地计算邻域元素的差异,比如这里的导数。我们还使用了linalg.norm() 函数,该函数可以衡量两个数组间(这个例子中是指图像矩阵U 和Uold)的差异。

下面,我们使用Erza Scarlet的图像进行去噪的实战练习

代码如下:

from numpy import *
from numpy import linalg as LA
from numpy import random
from scipy.ndimage import filters
from scipy.misc import imsave
from PIL import Image
import matplotlib.pyplot as plt


def denoise(im, U_init, tolerance=0.1, tau=0.125, tv_weight=100):
    m, n = im.shape  # 噪声图像的大小
    U = U_init
    Px = im  # 对偶域的x 分量
    Py = im  # 对偶域的y 分量
    error = 1

    while (error > tolerance):
        Uold = U

        GradUx = roll(U, -1, axis=1) - U  # 变量U 梯度的x 分量
        GradUy = roll(U, -1, axis=0) - U  # 变量U 梯度的y 分量

        PxNew = Px + (tau / tv_weight) * GradUx
        PyNew = Py + (tau / tv_weight) * GradUy
        NormNew = maximum(1, sqrt(PxNew ** 2 + PyNew ** 2))

        Px = PxNew / NormNew  # 更新x 分量(对偶)
        Py = PyNew / NormNew  # 更新y 分量(对偶)

        RxPx = roll(Px, 1, axis=1)  # 对x 分量进行向右x 轴平移
        RyPy = roll(Py, 1, axis=0)  # 对y 分量进行向右y 轴平移

        DivP = (Px - RxPx) + (Py - RyPy)  # 对偶域的散度
        U = im + tv_weight * DivP  # 更新原始变量

        # 更新误差
        error = linalg.norm(U - Uold) / sqrt(n * m)
    return U, im - U


fig = plt.figure(figsize=(15, 15))
im = array(Image.open('test.jpg').convert('L'))
U, T = denoise(im, im)
plt.imshow(U, plt.cm.gray)
plt.axis('equal')
plt.axis("off")
plt.show()

输出如下:

参考文献:

python计算机视觉编程:http://yongyuan.name/pcvwithpython/

-END-

原文发布于微信公众号 - 专知(Quan_Zhuanzhi)

原文发表时间:2018-04-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AI研习社

史上最好记的神经网络结构速记表(下)

翻译 / 唐青 校对 / 李宇琛 整理 / 雷锋字幕组 本文提供了神经网络结构速查表,全面盘点神经网络的大量框架,并绘制直观示意图进行说明,是人手必备的神经网络...

481110
来自专栏AI研习社

史上最好记的神经网络结构速记表(上)

翻译 / 陈俊雅 校对 / 李傲 整理 / 雷锋字幕组 本文提供了神经网络结构速查表,盘点了神经网络的大量框架,并绘制了直观示意图进行说明,是人手必备的神经网络...

429120
来自专栏鹅厂优文

AI从入门到放弃:CNN的导火索,用MLP做图像分类识别?

图片标题会显示Accuracy(准确度),准确度的计算公式是: 识别正确图片数/图片总数。

59890
来自专栏Coding迪斯尼

详解神经网络中的神经元和激活函数

13830
来自专栏机器学习算法工程师

不懂word2vec,还敢说自己是做NLP?

如今,深度学习炙手可热,deep learning在图像处理领域已经取得了长足的进展。随着Google发布word2vec,深度学习在自然语言处理领域也掀起了一...

14950
来自专栏AI科技评论

干货 | 史上最好记的神经网络结构速记表(下)

翻译 / 唐青 校对 / 李宇琛 整理 / 雷锋字幕组 本文提供了神经网络结构速查表,全面盘点神经网络的大量框架,并绘制直观示意图进行说明,是人手必备的神经网...

413120
来自专栏AI研习社

教你从零开始检测皮卡丘-CNN目标检测入门教程(下)

本文为大家介绍实验过程中训练、测试过程及结果。算法和数据集参见《从零开始码一个皮卡丘检测器-CNN目标检测入门教程(上)》 训练 Train 损失函数 Lo...

33830
来自专栏IT派

PyTorch之迁移学习实战

迁移学习是把一个领域(即源领域)的知识,迁移到另外一个领域(即目标领域),使得目标领域能够取得更好的学习效果。通常,源领域数据量充足,而目标领域数据量较小,迁移...

12510
来自专栏杂七杂八

机器学习分类

机器学习通常分为四类 监督学习 无监督学习 半监督学习 强化学习 监督学习 监督学习是从标记的训练数据来推断一个功能的机器学习任务。在监督学习中,每个实例都是由...

37860
来自专栏PPV课数据科学社区

机器学习系列:(四)从线性回归到逻辑回归

从线性回归到逻辑回归 在第2章,线性回归里面,我们介绍了一元线性回归,多元线性回归和多项式回归。这些模型都是广义线性回归模型的具体形式,广义线性回归是一种灵活的...

57360

扫码关注云+社区

领取腾讯云代金券