OpenCV-Python开发指南(14)---几何变换之重映射

什么是重映射

把一副图像内的像素点放置到另一幅图像内的指定位置,这个过程我们称为重映射。简单点理解,也就是copy一个图像到另一个图像中。

在OpenCV中,它给我们提供了cv2.remap()函数作为重映射,其定义如下:

def remap(src, map1, map2, interpolation, dst=None, borderMode=None, borderValue=None): 

src:代表原始图像

map1:可以表示(x,y)点的一个映射,也可以表示CV_16SC2、CV_32FC1、CV_32FC2类型(x,y)点的x值

map2:当前map1表示(x,y)点的一个映射时,该值为空。当map1表示CV_16SC2、CV_32FC1、CV_32FC2类型(x,y)点的x值时,该值时CV_16UC1、CV_32FC1类型(x,y)点的y值。

interpolation,borderMode,borderValue与前文类似。

需要注意,map1指代的是像素点所在位置的列号,map2指代的是像素点所在位置的行号。

copy像素点

现在我们假设有一个需求,将目标图像内的所有像素点都映射为原始图像内的第100行,200列上的像素点。具体实现如下:

import cv2
import numpy as np

img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32) * 200
mapy = np.ones(img.shape[:2], np.float32) * 100
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()

如上面代码所示,我们将所有像素点都设置为原始图像(100,200)点的像素点,会得到一个非常纯色的图像,效果如下所示:
点像素设置

copy整个图像

那么既然能copy某个像素点,那么也肯定能copy整个图像。下面,我们将上图左边的图像全部copy到右边,具体代码如下:

import cv2
import numpy as np

img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32)
mapy = np.ones(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i,j),j)#设置每个点映射原图的Y坐标
        mapy.itemset((i,j),i)#设置每个点映射原图的X坐标
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()

这里,我们将所有点映射到所有点,每个像素点一一对应,就完成了copy原图像。运行之后,效果如下所示:
copy

绕X轴翻转

通过cv2.remap()函数,我们不仅可以重映射像素点,还可以翻转过来映射,也就是通过它实现X轴的翻转效果,只要保证X轴不变,并且Y坐标值以X轴为对称进行交换即可。

修改上面代码中的某一行,代码如下:

import cv2
import numpy as np

img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32)
mapy = np.ones(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i,j),j)
        mapy.itemset((i,j),rows-1-i)#修改这一行即可,对称
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()

运行之后,我们得到了绕X轴翻转的图像,效果如下:
绕X轴翻转

绕Y轴翻转

既然我们可以通过cv2.remap()函数绕X翻转,那么肯定的也可以绕Y轴翻转,只要将X坐标值以Y轴为对称进行交换即可。

话不多说,直接上代码:

import cv2
import numpy as np

img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32)
mapy = np.ones(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i,j),cols-1-j)#修改这一行即可
        mapy.itemset((i,j),i)#
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()

运行之后,我们得到绕Y轴翻转的图像:
绕Y轴翻转

绕XY轴翻转

那么绕XY轴一起翻转呢?这里二行代码一起更改:

import cv2
import numpy as np

img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32)
mapy = np.ones(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i,j),cols-1-j)
        mapy.itemset((i,j),rows-1-i)
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()

运行之后,效果如下所示:
绕XY轴翻转

压缩一半

也就是将原图缩小一般,按将Y轴缩小一般,只需要将X轴设置为2倍即可。具体代码如下所示:

import cv2
import numpy as np

img = cv2.imread("4.jpg")
rows, cols, ch = img.shape
mapx = np.ones(img.shape[:2], np.float32)
mapy = np.ones(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i,j),j)
        mapy.itemset((i,j),2*i)#修改这行代码即可
result_img = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow("img", img)
cv2.imshow("result_img", result_img)
cv2.waitKey()
cv2.destroyAllWindows()

运行之后,效果显示如下:
压缩原图像

既然能压缩,意味着也可以实现缩小,缩小的具体实现,可以当作训练的习题,方便大家巩固掌握,博主在这里就不在赘述了。

猜你喜欢

转载自blog.csdn.net/liyuanjinglyj/article/details/113807048