图像的错切实际上是平面景物在投影平面上的非垂直投影。错切使图像中的图形产生扭变
我们来看看错切的两种情况:
- 水平方向错切
- 垂直方向错切
水平方向错切
我们来直观看看错切的效果吧
其数学表达式为:
矩阵变换为:
其中b为tan(a),a为错切角度
好啦,我们还是写程序来看看效果吧
import math
def Warp(image,angle):
a = math.tan(angle * math.pi / 180.0 )
W = image.width
H = int(image.height + W * a)
size = (W,H)
iWarp = cv.CreateImage(size,image.depth,image.nChannels)
for i in range(image.height):
for j in range(image.width):
x = int(i + j * a)
iWarp[x,j] = image[i,j]
return iWarp
image = cv.LoadImage( ' lena.jpg ' , 1 )
iWarp1 = Warp(image, 15 )
cv.ShowImage( ' image ' ,image)
cv.ShowImage( ' 1 ' ,iWarp1)
cv.WaitKey(0)
效果如下:
好了。垂直方向的就不多讲了。和水平方向的基本相同。
我们来考虑下之前讲过的“蜂窝煤”吧
左图是我们希望得到的图,而在计算机中图像只能一个像素一个像素的现实
所以,可能出现左边的两个像素点映射取整后都映射到右图中的同一点,那另一点就形成空穴,就是我们之前提到的“蜂窝煤”
解决这个问题的方法应该有很多种,我想到两种比较直观的。
第一种是在有空穴的地方插值,但这种方法要进行冗余标记并增加计算
第二种方法是从右边的图往左边映射,迫使右边的每个像素点都可以取到值,但这样也会出现一个问题,右边的两个点可能在映射取整后,同样映射到一个点,那原图中的某些像素信息就会丢失。同样的,我们从左边映射到右边时,对于映射到同一点的像素,后面的映射点会覆盖前面的映射点,也会丢失信息。看来第二种方法简单,并解决了“蜂窝煤”现象
那有没有什么方法能不丢失信息呢?
我们来看看
好啦。你可能要头疼了。
其实我们可以把旋转操作看成3个错切操作
错切操作是不会舍弃任何点的
第一个矩阵是水平错切-tan(a/2)
第二个矩阵是垂直错切sina
第三个矩阵是水平错切-tan(a/2)
我发现我前面的程序出了些问题
是的,我前面的第二个参数用的是角度。但垂直变换时是sin a 不是 tan a
好吧,我们再重写一个函数
import math
def XWarp(image,angle):
a = math.tan(angle * math.pi / 180.0 )
W = image.width
H = int(image.height + W * a)
size = (W,H)
iWarp = cv.CreateImage(size,image.depth,image.nChannels)
for i in range(image.height):
for j in range(image.width):
x = int(i + j * a)
iWarp[x,j] = image[i,j]
return iWarp
def YWarp(image,angle):
a = math.tan(angle * math.pi / 180.0 )
H = image.height
W = int(image.width + H * a)
size = (W,H)
iYWarp = cv.CreateImage(size,image.depth,image.nChannels)
for i in range(image.height):
for j in range(image.width):
y = int((H - i) * a + j)
iYWarp[i,y] = image[i,j]
return iYWarp
def TYWarp(image,angle):
a = math.sin(angle * math.pi / 180.0 )
H = image.height
W = int(image.width + H * a)
size = (W,H)
iTYWarp = cv.CreateImage(size,image.depth,image.nChannels)
for i in range(image.height):
for j in range(image.width):
y = int((H - i) * a + j)
iTYWarp[i,y] = image[i,j]
return iTYWarp
image = cv.LoadImage( ' lena.jpg ' , 1 )
iWarp1 = XWarp(image, 15 )
iWarp2 = TYWarp(iWarp1, 30 )
iWarp3 = XWarp(iWarp2, 15 )
cv.ShowImage( ' image ' ,image)
cv.ShowImage( ' 1 ' ,iWarp1)
cv.ShowImage( ' 2 ' ,iWarp2)
cv.ShowImage( ' 3 ' ,iWarp3)
cv.WaitKey(0)
看看变换过程吧
好啦。“蜂窝煤”没有啦
恩,想一想,错切还是有点用的嘛