python opencv笔记
Posted 比特纳斯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python opencv笔记相关的知识,希望对你有一定的参考价值。
这一次来学习图像金字塔啦,是一个很有趣的内容。
——————————
原理:
一般情况下,我们要处理是一副具有固定分辨率的图像,但是有些情况下,需要对同一图像的不同分辨率的子图像进行处理。比如,我们要在一幅图像中查找某个目标,比如脸,我们不知道目标在图像中的尺寸大小,这种情况下,我们需要创建创建一组图像,这些图像是具有不同分辨率的原始图像。我们把这组图像叫做图像金字塔(简单来说就是同一图像的不同分辨率的子图集合)。如果我们把最大的图像放在底部,最小的放在顶部,看起来像一座金字塔,故而得名图像金字塔。
有两类图像金字塔:高斯金字塔和拉普拉斯金字塔。
??高斯金字塔的顶部是通过将底部图像中的连续的行和列去除得到的,顶部图像中的每个像素值等于下一层图像中 5 个像素的高斯加权平均值。这样操作一次一个 MxN 的图像就变成了一个 M/2xN/2 的图像。所以这幅图像的面积就变为原来图像面积的四分之一,这被称为 Octave。连续进行这样的操作我们就会得到一个分辨率不断下降的图像金字塔。使用函数
cv2.pyrDown() 和 cv2.pyrUp() 构建图像金字塔。
————————————
图像金字塔融合算法主要用在两幅图像的拼接中。两幅有重合区域的图片,如果直接个根据位置来拼接,那么由于两幅图片自身的差异,拼接完的图片上会有很明显的拼接线存在。
解决这个问题,最简单的方法是对两幅图片的重合区域的像素进行加权相加(这个操作可以理解为一种羽化的处理效果)。
设定一个权重w,就有公式:PB(i,j) = (1-w)*PA(i,j) + w*PB(i,j)可以计算重合区域融合后的像素值。
但是,这种简单的羽化对两幅图片的质量要求非常高,很对情况下并不能得到一个理想的效果。
因此,很多情况下,我们会选择稍微复杂的图像金字塔融合算法来处理这个重合区域。
先简单描述一下整个算法的流程,然后再具体介绍
1.用待处理的图像生成一系列的高斯金字塔图像。
2.根据高斯金字塔图像,计算出拉普拉斯金字塔图像。
3.根据高斯金字塔图像和拉普拉斯金子塔图像去重建重合区域的融合后的图像。
建立高斯金字塔的过程如下:
先对原图像进行高斯滤波,再去掉滤波之后的图像的的偶数行和偶数列(这样,这幅图像大小就是原图像的1/4了)。不断重复这个过程,直到达到要求的金子塔层数。(层数越高,那幅图就越小,这里定义第0层最高)
建立拉普拉斯金子塔的过程如下:
首先,我们要用高层的高斯金字塔图像去重建(expand)低层的图像。这里,我们假定用第0层的图像去重建第1层的图像,由于0层图像的大小是1层图像的1/4,所以我们必须对0层图像进行插值,使它达到1层图像的大小。这里,一般用0去作为偶数行和偶数列加入到原图像中,然后再进行高斯滤波。(注意,这里得到的重建后的第一层的图像跟原来的第一层的图像肯定不一样,因为高斯滤波丢失的信息是不可逆的)。
得到了重建后的1层图像,然后我们用原来的1层图像减去这个重建的图像,就得到了这一层的拉普拉斯金字塔图像。然后还是不断重复这个过程,就可以的得到整个的拉普拉斯图像金字塔了。
得到融合图像的过程如下:
用第n层的高斯金字塔图像加上第n层的拉普拉斯金字塔图像,然后用高斯插值的方法对这幅相加完的图像重建它第n-1层的图像。然后再用这个重建完的第n-1层的图像加上第n-1层图像的拉普拉斯金字塔图像,去重建第n-2层的图像...不断重复这个过程直到图像的大小合适。
以下逐一学习:
函数 cv2.pyrDown() 从一个高分辨率大尺寸的图像向上构建一个金字塔(尺寸变小,分辨率降低)。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('yangmi.png',255)
img1 = cv2.pyrDown(img) # 得到高一层的金字塔图像
img2 = cv2.pyrDown(img1) # 得到再高一层的金字塔图像
plt.subplot(131) #此为建立子图的函数,可搜网上
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.title('Original')
plt.subplot(132)
plt.imshow(cv2.cvtColor(img1,cv2.COLOR_BGR2RGB))
plt.title('Gaussion_1')
plt.subplot(133)
plt.imshow(cv2.cvtColor(img2,cv2.COLOR_BGR2RGB))
plt.title('Gaussion_2')
plt.show()
从坐标轴看大小,图像缩小了一倍。像素上可以看出变得更模糊。
函数 cv2.pyrUp() 从一个低分辨率小尺寸的图像向下构建一个金子塔(尺寸变大,但分辨率不会)
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('yangmi.png',255)
img1 = cv2.pyrDown(img) # 得到高一层的金字塔图像
img2 = cv2.pyrUp(img1) # 得到img1的低一层的金字塔图像
plt.subplot(131)
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.title('Original')
plt.subplot(132)
plt.imshow(cv2.cvtColor(img1,cv2.COLOR_BGR2RGB))
plt.title('down')
plt.subplot(133)
plt.imshow(cv2.cvtColor(img2,cv2.COLOR_BGR2RGB))
plt.title('up')
plt.show()
拉普拉斯金字塔可以有高斯金字塔计算得来,公式如下:
Li = Gi - PyrUp(G[i+1])
拉普拉金字塔的图像看起来就像边界图,其中很多像素都是 0,经常被用在图像压缩中。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('yangmi.png',255)
img1 = cv2.pyrDown(img) # 得到高一层的金字塔图像
temp1 = cv2.pyrDown(img1)
temp2 = cv2.pyrUp(temp1)
img2 = img1 - temp2
plt.subplot(131)
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.title('Original')
plt.subplot(132)
plt.imshow(cv2.cvtColor(img1,cv2.COLOR_BGR2RGB))
plt.title('Gaussion')
plt.subplot(133)
plt.imshow(cv2.cvtColor(img2,cv2.COLOR_BGR2RGB))
plt.title('Laplacian')
plt.show()
图像金字塔的一个应用是图像融合。例如,在图像缝合中,你需要将两幅图叠在一起,但是由于连接区域图像像素的不连续性,整幅图的效果看起来会很差,这时图像金字塔就可以排上用场了,可以实现无缝连接。
实现俩图片融合的步骤如下:
1. 读入两幅图像
2. 构建图一和图二的高斯金字塔(6 层)
3. 根据高斯金字塔计算拉普拉斯金字塔
4. 在拉普拉斯的每一层进行图像融合(图一的左边与图二的右边融合)
5. 根据融合后的图像金字塔重建原始图像。
import cv2
import numpy as np
from matplotlib import pyplot as plt
#此函数使img1尺寸与img2相同
def sameSize(img1,img2):
rows,cols,dpt = img2.shape
dst = img1[:rows,:cols]
return dst
img1 = cv2.imread('bitnass.jpg')
img2 = cv2.imread('bless.jpg')
#得到img1的6层高斯金字塔图
G = img1.copy()
gp_img1 = [G]
for i in range(6):
G = cv2.pyrDown(G)
gp_img1.append(G)
#得到img2的6层高斯金字塔图
G = img2.copy()
gp_img2 = [G]
for j in range(6):
G = cv2.pyrDown(G)
gp_img2.append(G)
#得到img1的拉普拉斯金字塔图
lp_img1 = [gp_img1[5]]
for i in range(5,0,-1):
GE = cv2.pyrUp(gp_img1[i])
L = cv2.subtract(gp_img1[i-1],sameSize(GE,gp_img1[i-1]))#相减
lp_img1.append(L)
#得到img2的拉普拉斯金字塔图
lp_img2 = [gp_img2[5]]
for i in range(5,0,-1):
GE = cv2.pyrUp(gp_img2[i])
L = cv2.subtract(gp_img2[i-1],sameSize(GE,gp_img2[i-1]))
lp_img2.append(L)
#得到img1的左半边和img2的右半边
LS = []
for la,lb in zip(lp_img1,lp_img2):
rows,cols,dpt = la.shape
ls = np.hstack((la[:,0:cols//2],lb[:,cols//2:]))
LS.append(ls)
#得到拉普拉斯融合的图像
ls_reconstruct = LS[0]
for i in range(1,6):
ls_reconstruct = cv2.pyrUp(ls_reconstruct)
ls_reconstruct = cv2.add(sameSize(ls_reconstruct,LS[i]),LS[i])
#得到普通拼接的图像
r,c,depth = img1.shape
real = np.hstack((img1[:,0:c//2],img2[:,c//2:]))
plt.subplot(221)
plt.imshow(cv2.cvtColor(img1,cv2.COLOR_BGR2RGB))
plt.title('img1')
plt.xticks([]),plt.yticks([])
plt.subplot(222)
plt.imshow(cv2.cvtColor(img2,cv2.COLOR_BGR2RGB))
plt.title('img2')
plt.xticks([]),plt.yticks([])
plt.subplot(223)
plt.imshow(cv2.cvtColor(real,cv2.COLOR_BGR2RGB))
plt.title('real')
plt.xticks([]),plt.yticks([])
plt.subplot(224)
plt.imshow(cv2.cvtColor(ls_reconstruct,cv2.COLOR_BGR2RGB))
plt.title('laplace_pyramid')
plt.xticks([]),plt.yticks([])
plt.show()
这是这次所学的,很有趣是吧?
以上是关于python opencv笔记的主要内容,如果未能解决你的问题,请参考以下文章