时间为友,记录点滴。
我们之前有用到过resize的API,它既可以放大,也可以缩小。其中:
在图像缩放的世界里,还有另外一种方式----图像金字塔
啥是图像金字塔?
一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低,且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。我们将一层一层的图像比喻成金字塔,层级越高,则图像越小,分辨率越低。就像这样:
它有什么作用?
图像金字塔是图像中多尺度表达的一种,最初用于机器视觉和图像压缩,最主要用于图像的分割、融合。
怎么实现?
一般来说,我们可以先讨论两种典型的图像金字塔:
高斯金字塔是由底部的最大分辨率图像逐次向下采样得到的一系列图像。最下面的图像分辨率最高,越往上图像分辨率越低。
高斯金字塔的模型示意高斯金字塔的向下采样过程是:
1) 对于给定的图像先做一次高斯平滑处理,也就是使用一个大小为的卷积核对图像进行卷积操作.
OpenCv 中使用的高斯核2) 然后再对图像采样,去除图像中的偶数行和偶数列,然后就得到一张图片
3) 对这张图片循环1) 和 2)操作就可以得到高斯金字塔。
如模型可以看出,一次循环得到的图像即为G_(i+1)的图像,显而易见,结果图像只有原图的四分之一。通过对输入图像G_i(原始图像)不停迭代以上步骤就会得到整个金字塔。同时我们也可以看到,向下取样会逐渐丢失图像的信息。以上就是对图像的向下取样操作,即缩小图像。
高斯金字塔的向上采样过程是:
1) 将图像在每个方向扩大为原来的两倍,新增的行和列以0填充
2) 使用先前同样的内核(乘以4)与放大后的图像卷积,获得 “新增像素”的近似值
得到的图像即为放大后的图像,但是与原来的图像相比会发觉比较模糊,因为在缩放的过程中已经丢失了一些信息,如果想在缩小和放大整个过程中减少信息的丢失,这些数据形成了拉普拉斯金字塔。
注意:上采样和下采样是非线性处理,不可逆,有损的处理!
用来从金字塔低层图像重建上层未采样图像,在数字图像处理中也即是预测残差,可以对图像进行最大程度的还原,配合高斯金字塔一起使用。
拉普拉斯金字塔的生成和高斯金字塔的关系好在拉普拉斯金字塔有现成的公式:
因此在OpenCv中的拉普拉斯公式等价于
也就是说,拉普拉斯金字塔是通过源图像减去先缩小后再放大的图像的一系列图像构成的。保留的是残差!为图像还原做准备!
参考雷神的图还好,OpenCv中都给我们提供好了API:
高斯金字塔向下采样:
CV_EXPORTS_W
高斯金字塔向上采样:
CV_EXPORTS_W
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)