OpenCV之图像金字塔(Image Pyramids)

1、Theory

图像金字塔一般有两种类型在实际应用及文献中,他们分别是高斯金字塔及拉布拉斯金字塔。

高斯金字塔(Gaussianpyramid)——主要用来向下采用,图片和像素都不断变少。

拉布拉斯金字塔(Laplacianpyramid)——主要通过预测残差来重建上层图像,对图像最大程度地还原。

2、Function

函数1: cv2.pyrUp(),

功能说明:Upsamples an image and then blurs it. (图片变大)

参数

src    input image.

dst   output image. It has the specified size and the same type as src .

dstsize     size of the output image.

borderType     Pixel extrapolation method, see cv::BorderTypes (only BORDER_DEFAULT is supported)

函数2cv2.pyrDown()

功能说明:Blurs an image and downsamples it. (图片变少)

参数

src    input image.

dst   output image; it has the specified size and the same type as src.

dstsize     size of the output image.

borderType     Pixel extrapolation method, see cv::BorderTypes (BORDER_CONSTANT isn't supported)

 

3、Image Blending using Pyramids

import cv2
import numpy as np,sys
A = cv2.imread('../../image/apple1.jpg')
B = cv2.imread('../../image/orange1.jpg')
# generate Gaussian pyramid for A
G = A.copy()
gpA = [G]
for i in xrange(6):
G = cv2.pyrDown(G)
gpA.append(G)
# generate Gaussian pyramid for B
G = B.copy()
gpB = [G]
for i in xrange(6):
G = cv2.pyrDown(G)
gpB.append(G)
# generate Laplacian Pyramid for A
lpA = [gpA[5]]
for i in xrange(5,0,-1):
GE = cv2.pyrUp(gpA[i])
L = cv2.subtract(gpA[i-1],GE)
lpA.append(L)
# generate Laplacian Pyramid for B
lpB = [gpB[5]]
for i in xrange(5,0,-1):
GE = cv2.pyrUp(gpB[i])
L = cv2.subtract(gpB[i-1],GE)
lpB.append(L)
# Now add left and right halves of images in each level
LS = []
for la,lb in zip(lpA,lpB):
rows,cols,dpt = la.shape
ls = np.hstack((la[:,0:cols/2], lb[:,cols/2:]))
LS.append(ls)
# now reconstruct
ls_ = LS[0]
for i in xrange(1,6):
ls_ = cv2.pyrUp(ls_)
ls_ = cv2.add(ls_, LS[i])
# image with direct connecting each half
real = np.hstack((A[:,:cols/2],B[:,cols/2:]))
cv2.imwrite('Pyramid_blending2.jpg',ls_)
cv2.imwrite('Direct_blending.jpg',real)

代码位置:

E:\IdeaProjects_Python\faceprojects\imageProcessing\imagePyramids\imageBlendingUsingPyramids.py

改函数在跑的时候,出现如下错误,还在定位问题。先这里记录一下。。。

Traceback (most recent call last):

File "E:/IdeaProjects_Python/faceprojects/imageProcessing/imagePyramids/imageBlendingUsingPyramids.py", line 24, in <module>

L = cv2.subtract(gpA[i-1],GE)

cv2.error: ..\..\..\modules\core\src\arithm.cpp:639: error: (-209) The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array' in function cv::arithm_op

 

4、Image Blending using Pyramids by myself with openCV

# -*- coding: utf-8 -*-
# https://compvisionlab.wordpress.com/2013/05/13/image-blending-using-pyramid/
import sys
import os
import numpy as np
import cv2
import scipy
from scipy.stats import norm
from scipy.signal import convolve2d
import math

'''split rgb image to its channels'''
def
split_rgb(image):  # 把图像转换成BGR
red = None
green = None
blue = None
(blue, green, red) = cv2.split(image)
return red, green, blue

'''generate a 5x5 kernel'''
def
generating_kernel(a): # 通过一个数,生成一个5X5的内核
w_1d = np.array([0.25 - a / 2.0, 0.25, a, 0.25, 0.25 - a / 2.0])
return np.outer(w_1d, w_1d) # 一维数组 行向量和列向量相乘

'''reduce image by 1/2'''
def
ireduce(image): # 把图片缩减一半
out = None
kernel = generating_kernel(0.4)
outimage = scipy.signal.convolve2d(image, kernel, 'same') # Convolve two 2-dimensional arrays.
out = outimage[::2, ::2]  # 维度及 行、列、步长
return out

'''expand image by factor of 2'''
def
iexpand(image): # 把图片扩展一半
out = None
kernel = generating_kernel(0.4)
outimage = np.zeros((image.shape[0] * 2, image.shape[1] * 2), dtype=np.float64)
outimage[::2, ::2] = image[:, :]
out = 4 * scipy.signal.convolve2d(outimage, kernel, 'same')
return out

'''create a gaussain pyramid of a given image'''
def
gauss_pyramid(image, levels): # 高斯金字塔
output = []
output.append(image)
tmp = image
for i in range(0, levels):
tmp = ireduce(tmp)
output.append(tmp)
return output

'''build a laplacian pyramid'''
def
lapl_pyramid(gauss_pyr): # 建立拉布拉斯金字塔
output = []
k = len(gauss_pyr)
for i in range(0, k - 1):
gu = gauss_pyr[i]
egu = iexpand(gauss_pyr[i + 1])
if egu.shape[0] > gu.shape[0]:
egu = np.delete(egu, (-1), axis=0)
if egu.shape[1] > gu.shape[1]:
egu = np.delete(egu, (-1), axis=1)
output.append(gu - egu)
output.append(gauss_pyr.pop())
return output

'''Blend the two laplacian pyramids by weighting them according to the mask.'''
def
blend(lapl_pyr_white, lapl_pyr_black, gauss_pyr_mask):
blended_pyr = []
k = len(gauss_pyr_mask)
for i in range(0, k):
p1 = gauss_pyr_mask[i] * lapl_pyr_white[i]
p2 = (1 - gauss_pyr_mask[i]) * lapl_pyr_black[i]
blended_pyr.append(p1 + p2)
return blended_pyr

'''Reconstruct the image based on its laplacian pyramid.'''
def
collapse(lapl_pyr):
output = None
output = np.zeros((lapl_pyr[0].shape[0], lapl_pyr[0].shape[1]), dtype=np.float64)
for i in range(len(lapl_pyr) - 1, 0, -1):
lap = iexpand(lapl_pyr[i])
lapb = lapl_pyr[i - 1]
if lap.shape[0] > lapb.shape[0]:
lap = np.delete(lap, (-1), axis=0)
if lap.shape[1] > lapb.shape[1]:
lap = np.delete(lap, (-1), axis=1)
tmp = lap + lapb
lapl_pyr.pop()
lapl_pyr.pop()
lapl_pyr.append(tmp)
output = tmp
return output

def main():
image1 = cv2.imread('../../image/apple1.jpg')
image2 = cv2.imread('../../image/orange1.jpg')
mask = cv2.imread('../../image/mask512.jpg')
r1 = None
g1 = None
b1 = None
r2 = None
g2 = None
b2 = None
rm = None
gm = None
bm = None

(r1, g1, b1) = split_rgb(image1)
(r2, g2, b2) = split_rgb(image2)
(rm, gm, bm) = split_rgb(mask)

r1 = r1.astype(float)
g1 = g1.astype(float)
b1 = b1.astype(float)

r2 = r2.astype(float)
g2 = g2.astype(float)
b2 = b2.astype(float)

rm = rm.astype(float) / 255
gm = gm.astype(float) / 255
bm = bm.astype(float) / 255

# Automatically figure out the size
min_size = min(r1.shape)
depth = int(math.floor(math.log(min_size, 2))) - 4  # at least 16x16 at the highest level.

gauss_pyr_maskr = gauss_pyramid(rm, depth)
gauss_pyr_maskg = gauss_pyramid(gm, depth)
gauss_pyr_maskb = gauss_pyramid(bm, depth)

gauss_pyr_image1r = gauss_pyramid(r1, depth)
gauss_pyr_image1g = gauss_pyramid(g1, depth)
gauss_pyr_image1b = gauss_pyramid(b1, depth)

gauss_pyr_image2r = gauss_pyramid(r2, depth)
gauss_pyr_image2g = gauss_pyramid(g2, depth)
gauss_pyr_image2b = gauss_pyramid(b2, depth)

lapl_pyr_image1r = lapl_pyramid(gauss_pyr_image1r)
lapl_pyr_image1g = lapl_pyramid(gauss_pyr_image1g)
lapl_pyr_image1b = lapl_pyramid(gauss_pyr_image1b)

lapl_pyr_image2r = lapl_pyramid(gauss_pyr_image2r)
lapl_pyr_image2g = lapl_pyramid(gauss_pyr_image2g)
lapl_pyr_image2b = lapl_pyramid(gauss_pyr_image2b)

outpyrr = blend(lapl_pyr_image2r, lapl_pyr_image1r, gauss_pyr_maskr)
outpyrg = blend(lapl_pyr_image2g, lapl_pyr_image1g, gauss_pyr_maskg)
outpyrb = blend(lapl_pyr_image2b, lapl_pyr_image1b, gauss_pyr_maskb)

outimgr = collapse(blend(lapl_pyr_image2r, lapl_pyr_image1r, gauss_pyr_maskr))
outimgg = collapse(blend(lapl_pyr_image2g, lapl_pyr_image1g, gauss_pyr_maskg))
outimgb = collapse(blend(lapl_pyr_image2b, lapl_pyr_image1b, gauss_pyr_maskb))
# blending sometimes results in slightly out of bound numbers.
outimgr[outimgr < 0] = 0
outimgr[outimgr > 255] = 255
outimgr = outimgr.astype(np.uint8)

outimgg[outimgg < 0] = 0
outimgg[outimgg > 255] = 255
outimgg = outimgg.astype(np.uint8)

outimgb[outimgb < 0] = 0
outimgb[outimgb > 255] = 255
outimgb = outimgb.astype(np.uint8)

result = np.zeros(image1.shape, dtype=image1.dtype)
tmp = []
tmp.append(outimgb)
tmp.append(outimgg)
tmp.append(outimgr)
result = cv2.merge(tmp, result)
cv2.imwrite('d:/blended.jpg', result)

if __name__ == '__main__':
main()

代码位置:

E:\IdeaProjects_Python\faceprojects\imageProcessing\imagePyramids\imageBlendingUsingPyramids2.py

 

5、Reference Material

资料1:http://docs.opencv.org/3.3.0/dc/dff/tutorial_py_pyramids.html

资料2(函数pyrUp):

http://docs.opencv.org/3.3.0/d4/d86/group__imgproc__filter.html#gada75b59bdaaca411ed6fee10085eb784

资料3(函数pyrDown):

http://docs.opencv.org/3.3.0/d4/d86/group__imgproc__filter.html#gaf9bba239dfca11654cb7f50f889fc2ff

资料4(Computer Vision from theory to code – Image blending using pyramid):

https://compvisionlab.wordpress.com/2013/05/13/image-blending-using-pyramid/

资料5:OpenCV3编程入门(毛星云编著)

资料6:Practical Python and OpenCV -- An Introductory, Example Driven Guide to Image Processiong and Computer Vision 2ND Edition.

http://opencv.org/new-opencv-books.html

资料7:Practical Python and OpenCV: Case Studies 2nd Edition

https://www.pyimagesearch.com/practical-python-opencv/

资料8(scipy.signal.convolve2d):

https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve2d.html

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: