计算机视觉中的图像扭曲
图像中的图像
仿射扭曲的一个简单例子是,将图像或者图像的一部分放置在另一幅图像中,使得它们能够和指定的区域或者标记物对齐。
1.以下是实现代码:
# -*- coding: utf-8 -*-
from PCV.geometry import homography, warp
from PIL import Image
from pylab import *
from scipy import ndimage
# example of affine warp of im1 onto im2
im1 = array(Image.open('F:/VSCode/pcv-book-code-master/ch03/36.jpg').convert('L'))
im2 = array(Image.open('F:/VSCode/pcv-book-code-master/ch03/35.jpeg').convert('L'))
# set to points
tp = array([[240,520,520,240],[600,620,1200,1230],[1,1,1,1]])
#tp = array([[675,826,826,677],[55,52,281,277],[1,1,1,1]])
im3 = warp.image_in_image(im1,im2,tp)
figure()
gray()
subplot(141)
axis('off')
imshow(im1)
subplot(142)
axis('off')
imshow(im2)
subplot(143)
axis('off')
imshow(im3)
# set from points to corners of im1
m,n = im1.shape[:2]
fp = array([[0,m,m,0],[0,0,n,n],[1,1,1,1]])
# first triangle
tp2 = tp[:,:3]
fp2 = fp[:,:3]
# compute H
H = homography.Haffine_from_points(tp2,fp2)
im1_t = ndimage.affine_transform(im1,H[:2,:2],
(H[0,2],H[1,2]),im2.shape[:2])
# alpha for triangle
alpha = warp.alpha_for_triangle(tp2,im2.shape[0],im2.shape[1])
im3 = (1-alpha)*im2 + alpha*im1_t
# second triangle
tp2 = tp[:,[0,2,3]]
fp2 = fp[:,[0,2,3]]
# compute H
H = homography.Haffine_from_points(tp2,fp2)
im1_t = ndimage.affine_transform(im1,H[:2,:2],
(H[0,2],H[1,2]),im2.shape[:2])
# alpha for triangle
alpha = warp.alpha_for_triangle(tp2,im2.shape[0],im2.shape[1])
im4 = (1-alpha)*im3 + alpha*im1_t
subplot(144)
imshow(im4)
axis('off')
show()
2.实现如图:
对于其中的这一行代码tp = array([[240,520,520,240],[600,620,1200,1230],[1,1,1,1]])
,
前面的[240,520,520,240]是四个角点的纵坐标,[600,620,1200,1230]是横坐标,四个角点坐标顺序是左上角[600,240],左下角[620,520],右下角[1200,520],右上角[1230,240]。最后四个1就表示四个角点的透明度为不透明,以此实现图像的完全覆盖。修改数据展示如下:
修改数据为tp = array([[120,260,260,120],[16,16,305,305],[1,1,1,1]])
时候:
修改数据为tp = array([[120,520,520,120],[600,620,1200,1230],[1,1,1,1]])
时候:
3.其中warp.py的代码如下
from scipy.spatial import Delaunay
from scipy import ndimage
from pylab import *
from numpy import *
from PCV.geometry import homography
def image_in_image(im1,im2,tp):
""" Put im1 in im2 with an affine transformation
such that corners are as close to tp as possible.
tp are homogeneous and counter-clockwise from top left. """
# points to warp from
m,n = im1.shape[:2]
fp = array([[0,m,m,0],[0,0,n,n],[1,1,1,1]])
# compute affine transform and apply
H = homography.Haffine_from_points(tp,fp)
im1_t = ndimage.affine_transform(im1,H[:2,:2],
(H[0,2],H[1,2]),im2.shape[:2])
alpha = (im1_t > 0)
return (1-alpha)*im2 + alpha*im1_t
def combine_images(im1,im2,alpha):
""" Blend two images with weights as in alpha. """
return (1-alpha)*im1 + alpha*im2
def alpha_for_triangle(points,m,n):
""" Creates alpha map of size (m,n)
for a triangle with corners defined by points
(given in normalized homogeneous coordinates). """
alpha = zeros((m,n))
for i in range(min(points[0]),max(points[0])):
for j in range(min(points[1]),max(points[1])):
x = linalg.solve(points,[i,j,1])
if min(x) > 0: #all coefficients positive
alpha[i,j] = 1
return alpha
def triangulate_points(x,y):
""" Delaunay triangulation of 2D points. """
tri = Delaunay(np.c_[x,y]).simplices
return tri
def plot_mesh(x,y,tri):
""" Plot triangles. """
for t in tri:
t_ext = [t[0], t[1], t[2], t[0]] # add first point to end
plot(x[t_ext],y[t_ext],'r')
def pw_affine(fromim,toim,fp,tp,tri):
""" Warp triangular patches from an image.
fromim = image to warp
toim = destination image
fp = from points in hom. coordinates
tp = to points in hom. coordinates
tri = triangulation. """
im = toim.copy()
# check if image is grayscale or color
is_color = len(fromim.shape) == 3
# create image to warp to (needed if iterate colors)
im_t = zeros(im.shape, 'uint8')
for t in tri:
# compute affine transformation
H = homography.Haffine_from_points(tp[:,t],fp[:,t])
if is_color:
for col in range(fromim.shape[2]):
im_t[:,:,col] = ndimage.affine_transform(
fromim[:,:,col],H[:2,:2],(H[0,2],H[1,2]),im.shape[:2])
else:
im_t = ndimage.affine_transform(
fromim,H[:2,:2],(H[0,2],H[1,2]),im.shape[:2])
# alpha for triangle
alpha = alpha_for_triangle(tp[:,t],im.shape[0],im.shape[1])
# add triangle to image
im[alpha>0] = im_t[alpha>0]
return im
def panorama(H,fromim,toim,padding=2400,delta=2400):
""" Create horizontal panorama by blending two images
using a homography H (preferably estimated using RANSAC).
The result is an image with the same height as toim. 'padding'
specifies number of fill pixels and 'delta' additional translation. """
# check if images are grayscale or color
is_color = len(fromim.shape) == 3
# homography transformation for geometric_transform()
def transf(p):
p2 = dot(H,[p[0],p[1],1])
return (p2[0]/p2[2],p2[1]/p2[2])
if H[1,2]<0: # fromim is to the right
print ('warp - right')
# transform fromim
if is_color:
# pad the destination image with zeros to the right
toim_t = hstack((toim,zeros((toim.shape[0],padding,3))))
fromim_t = zeros((toim.shape[0],toim.shape[1]+padding,toim.shape[2]))
for col in range(3):
fromim_t[:,:,col] = ndimage.geometric_transform(fromim[:,:,col],
transf,(toim.shape[0],toim.shape[1]+padding))
else:
# pad the destination image with zeros to the right
toim_t = hstack((toim,zeros((toim.shape[0],padding))))
fromim_t = ndimage.geometric_transform(fromim,transf,
(toim.shape[0],toim.shape[1]+padding))
else:
print ('warp - left')
# add translation to compensate for padding to the left
H_delta = array([[1,0,0],[0,1,-delta],[0,0,1]])
H = dot(H,H_delta)
# transform fromim
if is_color:
# pad the destination image with zeros to the left
toim_t = hstack((zeros((toim.shape[0],padding,3)),toim))
fromim_t = zeros((toim.shape[0],toim.shape[1]+padding,toim.shape[2]))
for col in range(3):
fromim_t[:,:,col] = ndimage.geometric_transform(fromim[:,:,col],
transf,(toim.shape[0],toim.shape[1]+padding))
else:
# pad the destination image with zeros to the left
toim_t = hstack((zeros((toim.shape[0],padding)),toim))
fromim_t = ndimage.geometric_transform(fromim,
transf,(toim.shape[0],toim.shape[1]+padding))
# blend and return (put fromim above toim)
if is_color:
# all non black pixels
alpha = ((fromim_t[:,:,0] * fromim_t[:,:,1] * fromim_t[:,:,2] ) > 0)
for col in range(3):
toim_t[:,:,col] = fromim_t[:,:,col]*alpha + toim_t[:,:,col]*(1-alpha)
else:
alpha = (fromim_t > 0)
toim_t = fromim_t*alpha + toim_t*(1-alpha)
return toim_t