把一幅图像内的像素点放置到另一幅图像内的指定位置,这个过程称之为重映射。本节主要讲述重映射里的一系列变换操作,包括复制、翻转和缩放。重点需要加强对参数的理解。

重映射函数函数

OpenCV中重映射函数为cv2.remap(),语法格式如下:

dst = cv2.remap(src, map1, map2, interpolation[, borderMode, [,borderValue]])
  • dst代表目标图像
  • src代表原始图像
  • map1参数有两种可能
    • 表示(x,y)点的映射
    • 表示CV_16SC2, CV_32FC1, CV_32FC2类型(x,y)点的x值
  • map2参数有两种可能
    • 当map1表示(x,y)时,该值为空
    • 当map1表示(x,y)时的x值时,该值是CV_16UC1, CV_32FC1类型(x,y)点的y值
  • interpolation表示差值方式,不支持INTER_AREA方法
  • borderMode代表边界模式,值为BORDER_TRANSPARENT时,表示目标图像内的对应源图像内奇异点的像素不会被修改
  • borderValue表示边界值,该值默认为0

插值方式表

映射参数的理解

映射函数的作用是查找新图像像素在原始像素图像内的位置。该过程是将新图像像素映射到原始图像的过程,也称为反向映射。在函数cv2.remap()中,参数map1和参数map2用来说明反向映射,map1针对的是坐标x,map2针对的是坐标y。通常将map1写成mapx,map2写成mapy,以方便理解。

例如想将目标图像(映射结果图像dst)中的某个点A映射为原始图像处第0行第3列上的像素点B,那么需要将A点所对应的参数map1对应位置上的值设为3,参数map2对应的位置上的值设为0。

例1:程序设计,使用cv2.remap()完成数组映射,将目标数组内的所有点都映射为原始图像内第0行第3列上的像素点,以此来了解map1和map2的含义。

import cv2
import numpy as np
img = np.random.randint(0, 256, size=[4, 5], dtype=np.uint8)
rows, cols = img.shape
mapx = np.ones(img.shape, np.float32) * 3
mapy = np.ones(img.shape, np.float32) * 0
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
print('img=\n', img)
print('mapx=\n', mapx)
print('mapy=\n', mapy)
print('rst=\n', rst)

结果:

img=
 [[168 176  36 233  60]
 [ 41 190  64 145   1]
 [ 88  73 235 224 194]
 [189 198 220 102 200]]
mapx=
 [[3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]]
mapy=
 [[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]
rst=
 [[233 233 233 233 233]
 [233 233 233 233 233]
 [233 233 233 233 233]
 [233 233 233 233 233]]

复 制

  • 将map1的值设定为对应位置上的x轴坐标值
  • 将map2的值设定为对应位值上的y轴坐标值

通过上述处理,就可以实现图像复制。

例:使用cv2.remap()完成数组复制,了解参数map1和map2的使用。

import cv2
import numpy as np
img = np.random.randint(0, 256, size=[4, 5], dtype=np.uint8)
rows, cols = img.shape

mapx = np.zeros(img.shape, np.float32)
mapy = np.zeros(img.shape, np.float32)

for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), j)
        mapy.itemset((i, j), i)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)

print('img=\n', img)
print('mapx=\n', mapx)
print('mapy=\n', mapy)
print('rst=\n', rst)

运行结果:

img=
 [[214 127  71 191 112]
 [ 86  57 141  21  21]
 [114 142 212   7 230]
 [225  37 182 108 115]]
mapx=
 [[0. 1. 2. 3. 4.]
 [0. 1. 2. 3. 4.]
 [0. 1. 2. 3. 4.]
 [0. 1. 2. 3. 4.]]
mapy=
 [[0. 0. 0. 0. 0.]
 [1. 1. 1. 1. 1.]
 [2. 2. 2. 2. 2.]
 [3. 3. 3. 3. 3.]]
rst=
 [[214 127  71 191 112]
 [ 86  57 141  21  21]
 [114 142 212   7 230]
 [225  37 182 108 115]]

例:使用cv2.remap()完成图片的复制

import cv2
import numpy as np
img = cv2.imread('boy.png')
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), j)
        mapy.itemset((i, j), i)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()

效果:

复制效果

绕X轴翻转/对称

让图像让x轴对称,则有:

  • x坐标系的值保持不变
  • y坐标轴的值以x轴为对称进行交换

反映在mapx和mapy中:

  • map1的值保持不变
  • map2的值调整为“总行数-1-当前行号”

(OpenCV中行列起始于0索引,在对称关系中,有关系式 “当前行号 + 对称行号 = 总行数 - 1”)

import cv2
import numpy as np
img = cv2.imread('boy.png')
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(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)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()

运行结果

绕Y轴翻转/对称

让图像绕y轴对称,则有:

  • y坐标系的值保持不变
  • x坐标轴的值以y轴为对称进行交换

反映在mapx和mapy中:

  • map2的值保持不变
  • map1的值调整为“总列数-1-当前列号”

(OpenCV中行列起始于0索引,在对称关系中,有关系式 “当前列号 + 对称列号 = 总列数 - 1”)

import cv2
import numpy as np
img = cv2.imread('boy.png')
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(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)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()

实验结果

绕X轴、Y轴翻转

让图像绕x轴、y轴对称,则有:

  • y坐标轴的值以x轴为对称进行交换
  • x坐标轴的值以y轴为对称进行交换

反映在mapx和mapy中:

  • map2的值调整为“总列数-1-当前列号”
  • map1的值调整为“总行数-1-当前行号”
import cv2
import numpy as np
img = cv2.imread('boy.png')
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(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)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()

绕X轴、Y轴对称

X轴、Y轴互换

需要注意的是,当行数和列数不一致的时候,运算可能存在无法映射的情况,默认会将无法映射的值处理为0(黑色)

  • mapx的值调整为所在行的行号
  • mapy的值调整为所在列的列号
import cv2
import numpy as np
img = cv2.imread('boy.png')
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), i)
        mapy.itemset((i, j), j)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()

XY轴互换


博主个人公众号
版权声明 ▶ 本网站名称:陶小桃Blog
▶ 本文链接:https://www.52txr.cn/2021/OpenCV17.html
▶ 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行核实删除。
▶ 转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处!!

最后修改:2022 年 05 月 16 日
如果觉得我的文章对你有用,请随意赞赏