python高斯噪声怎么去除_(二十六)图像金字塔----高斯和拉普拉斯

python高斯噪声怎么去除_(二十六)图像金字塔----高斯和拉普拉斯_第1张图片

时间为友,记录点滴。

我们之前有用到过resize的API,它既可以放大,也可以缩小。其中:

  • 缩小图像,一般推荐使用CV_INETR_AREA(区域插值)来插值;
  • 放大图像,推荐使用CV_INTER_LINEAR(线性插值)

在图像缩放的世界里,还有另外一种方式----图像金字塔

啥是图像金字塔?

一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低,且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。我们将一层一层的图像比喻成金字塔,层级越高,则图像越小,分辨率越低。就像这样:

python高斯噪声怎么去除_(二十六)图像金字塔----高斯和拉普拉斯_第2张图片
它有什么作用?

图像金字塔是图像中多尺度表达的一种,最初用于机器视觉和图像压缩,最主要用于图像的分割、融合。

怎么实现?

一般来说,我们可以先讨论两种典型的图像金字塔:

高斯金字塔 ( Gaussian pyramid):

高斯金字塔是由底部的最大分辨率图像逐次向下采样得到的一系列图像。最下面的图像分辨率最高,越往上图像分辨率越低。

python高斯噪声怎么去除_(二十六)图像金字塔----高斯和拉普拉斯_第3张图片
高斯金字塔的模型示意

高斯金字塔的向下采样过程是:

1) 对于给定的图像先做一次高斯平滑处理,也就是使用一个大小为的卷积核对图像进行卷积操作.

520aca7598ac1670d8a5b0f09e76494d.png
OpenCv 中使用的高斯核

2) 然后再对图像采样,去除图像中的偶数行和偶数列,然后就得到一张图片

3) 对这张图片循环1) 和 2)操作就可以得到高斯金字塔。

如模型可以看出,一次循环得到的图像即为G_(i+1)的图像,显而易见,结果图像只有原图的四分之一。通过对输入图像G_i(原始图像)不停迭代以上步骤就会得到整个金字塔。同时我们也可以看到,向下取样会逐渐丢失图像的信息。以上就是对图像的向下取样操作,即缩小图像。

高斯金字塔的向上采样过程是:

1) 将图像在每个方向扩大为原来的两倍,新增的行和列以0填充

2) 使用先前同样的内核(乘以4)与放大后的图像卷积,获得 “新增像素”的近似值

得到的图像即为放大后的图像,但是与原来的图像相比会发觉比较模糊,因为在缩放的过程中已经丢失了一些信息,如果想在缩小和放大整个过程中减少信息的丢失,这些数据形成了拉普拉斯金字塔

注意:上采样和下采样是非线性处理,不可逆,有损的处理!

拉普拉斯金字塔(Laplacian pyramid):

用来从金字塔低层图像重建上层未采样图像,在数字图像处理中也即是预测残差,可以对图像进行最大程度的还原,配合高斯金字塔一起使用。

python高斯噪声怎么去除_(二十六)图像金字塔----高斯和拉普拉斯_第4张图片
拉普拉斯金字塔的生成和高斯金字塔的关系

好在拉普拉斯金字塔有现成的公式:

  1. 表示第i层的高斯图像
  2. 表示第i+1层的高斯图像
  3. 表示向上采样,将源图像中位置为(x,y)的像素映射到目标图像的(2x+1,2y+1)位置
  4. 用来表示卷积
  5. 表示5*5的内核(参考上面的高斯内核)

因此在OpenCv中的拉普拉斯公式等价于

也就是说,拉普拉斯金字塔是通过源图像减去先缩小后再放大的图像的一系列图像构成的。保留的是残差!为图像还原做准备!

python高斯噪声怎么去除_(二十六)图像金字塔----高斯和拉普拉斯_第5张图片
参考雷神的图

还好,OpenCv中都给我们提供好了API:

高斯金字塔向下采样:
CV_EXPORTS_W 
高斯金字塔向上采样:
CV_EXPORTS_W 
  • 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。
  • 第二个参数,OutputArray类型的dst,输出图像,和源图片有一样的尺寸和类型。
  • 第三个参数,const Size&类型的dstsize,输出图像的大小;有默认值Size(),即默认情况下,由Size(src.cols*2,src.rows*2)来进行计算,且一直需要满足下列条件:

  • 第四个参数,int类型的borderType,又来了,边界模式,一般我们不用去管它

C++

注意点:

1. 如果要计算拉普拉斯金字塔,那么UP时要对应好size。
#include 

Python:

注意点:

1. plt的整个图像的title命名应该用plt.figure
2. 自己做的UP函数跟标准的pyrUp函数之间的差别应该是由kernel的选择导致的(注意UP的kernel应该乘以4)
3. filter2D可以用这个函数来选择用自己的kernel,其中第三个参数-1代表ddepth跟src的detype相同
4. 对行和列插入0时,采用的是np的insert,这里可以通过axis选择行或者列。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:lowkeyway time:8/31/2019

import sys
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

def showImgPara(img):
    print("Sizeof img is: " + str(img.size))
    print("rows x cols is: " + str(np.size(img, 0)) + " x " + str(np.size(img, 1)))
    print("dimension is: ", img.ndim)
    print("dtype is: ", img.dtype)
    print("itemsize is: ", img.itemsize)
    print("shape is(rows, cols, depth): ", img.shape)
    print("n")

def myPyramidLa(imgOri):
    if 3 == len(imgOri.shape):
        imgOri = cv.cvtColor(imgOri, cv.COLOR_BGR2GRAY)

    temp = myPyramidDown(imgOri)
    temp = myPyramidUp(temp)
    pyLa = cv.subtract(imgOri, temp)+127

    plt.figure("myPyramidLa")
    plt.subplot(131), plt.imshow(imgOri, "gray"), plt.title("imgOri")
    plt.subplot(132), plt.imshow(temp, "gray"), plt.title("temp")
    plt.subplot(133), plt.imshow(pyLa, "gray"), plt.title("pyLa")

    print("n----myPyramidLa----")
    showImgPara(imgOri)
    showImgPara(temp)
    showImgPara(pyLa)

    x, y = imgOri.shape
    imgOut = np.zeros([y, x*3], dtype=imgOri.dtype)
    imgOut[:y, :x] = imgOri
    imgOut[:y, x:2*x] = temp
    imgOut[:y, 2*x:3*x] = pyLa
    cv.imshow("pyLa", imgOut)

def myPyramidUp(imgOri):
    kernel = (4/256 * np.array(
        [
            [1,  4,  6,  4, 1],
            [4, 16, 24, 16, 4],
            [6, 24, 36, 24, 6],
            [4, 16, 24, 16, 4],
            [1,  4,  6,  4, 1]
        ]
    ))

    if 3 == len(imgOri.shape):
        imgOri = cv.cvtColor(imgOri, cv.COLOR_BGR2GRAY)
    x, y = imgOri.shape
    temp = np.copy(imgOri)

    # Resize
    for index in range(x):
        temp = np.insert(temp, 2*index+1, 0, axis=1)
    for index in range(y):
        temp = np.insert(temp, 2*index+1, 0, axis=0)

    myDst = cv.filter2D(temp, -1, kernel=kernel)

    pyDst = cv.pyrUp(imgOri)
    diff = cv.subtract(pyDst, myDst)

    plt.figure("myPyramidUp")
    plt.subplot(223), plt.imshow(imgOri, "gray"), plt.title("imgOri")
    plt.subplot(221), plt.imshow(myDst, "gray"), plt.title("myDst")
    plt.subplot(222), plt.imshow(myDst, "gray"), plt.title("pyDst")
    plt.subplot(224), plt.imshow(diff, "gray"), plt.title("Diff")



    # plt.show()
    return myDst


def myPyramidDown(imgOri):
    kernel = (1/256 * np.array(
        [
            [1,  4,  6,  4, 1],
            [4, 16, 24, 16, 4],
            [6, 24, 36, 24, 6],
            [4, 16, 24, 16, 4],
            [1,  4,  6,  4, 1]
        ]
    ))
    if 3 == len(imgOri.shape):
        imgOri = cv.cvtColor(imgOri, cv.COLOR_BGR2GRAY)

    x, y = imgOri.shape
    temp = cv.filter2D(imgOri, -1, kernel=kernel)
    myDst = temp[::2, ::2]

    pyDst = cv.pyrDown(imgOri)
    diff = cv.subtract(pyDst, myDst)

    plt.figure("myPyramidDown")
    plt.subplot(223), plt.imshow(imgOri, "gray"), plt.title("imgOri")
    plt.subplot(221), plt.imshow(myDst, "gray"), plt.title("myDst")
    plt.subplot(222), plt.imshow(pyDst, "gray"), plt.title("pyDst")
    plt.subplot(224), plt.imshow(diff, "gray"), plt.title("Diff")
    # plt.show()

    return myDst

def main_func(argv):
    imgOri = cv.imread("Fig0701.tif")
    # myPyramidDown(imgOri)
    imgOri = cv.imread("lowkeyway.jpg")
    # myPyramidUp(imgOri)
    myPyramidLa(imgOri)

    # plt.show()
    cv.waitKey(0)

if __name__ == '__main__':
    main_func(sys.argv)

python高斯噪声怎么去除_(二十六)图像金字塔----高斯和拉普拉斯_第6张图片
运行结果

你可能感兴趣的:(python高斯噪声怎么去除,线性插值改变图像尺寸)