图像映射(remap)是 OpenCV 中灵活调整图像像素位置的核心操作,通过自定义像素坐标映射规则,可实现图像缩放、对称、旋转等效果。本文用极简代码演示 remap 的基础用法,新手可快速掌握自定义映射逻辑。
核心代码实现
python
import cv2 as cv
import numpy as np
# 1. 读取图像并校验
src = cv.imread(".\image\1.bmp")
if src is None:
print('could not load image')
exit()
rows, cols, channels = src.shape # 获取图像尺寸:行(高)、列(宽)、通道数
# 2. 创建映射矩阵(float32类型,与原图尺寸一致)
img_x = np.zeros((rows, cols), np.float32) # x轴(列)映射矩阵
img_y = np.zeros((rows, cols), np.float32) # y轴(行)映射矩阵
# 3. 遍历每个像素,定义映射规则(按需注释/启用不同效果)
for y in range(rows):
for x in range(cols):
# 效果1:缩小一半(需注释其他效果)
# img_x[y, x] = 2 * (x - cols * 0.25)
# img_y[y, x] = 2 * (y - rows * 0.25)
# 效果2:左右对称(镜像)
# img_x[y, x] = cols - x - 1
# img_y[y, x] = y
# 效果3:上下对称
# img_x[y, x] = x
# img_y[y, x] = rows - y - 1
# 效果4:中心旋转180°
img_x[y, x] = cols - x - 1
img_y[y, x] = rows - y - 1
# 4. 执行图像映射(线性插值,保证过渡平滑)
dst = cv.remap(src, img_x, img_y, cv.INTER_LINEAR)
# 5. 显示原图与映射结果
cv.imshow('outimage1(原图)', src)
cv.imshow('outimage2(映射后)', dst)
cv.waitKeyEx(0)
cv.destroyAllWindows()
关键知识点解析
1. remap 核心逻辑
- 映射矩阵 :
img_x[y,x]表示目标图像 (y,x) 位置的像素,来源于原图的img_x[y,x]列;img_y[y,x]对应原图的行; - 数据类型 :映射矩阵必须为
float32,否则会导致映射失效; - 插值方式 :
cv.INTER_LINEAR(线性插值)是默认最优选择,保证映射后图像无锯齿,也可选用cv.INTER_NEAREST(最近邻插值,速度更快但效果粗糙)。
2. 常用映射规则拆解
| 效果 | 映射公式 | 原理说明 |
|---|---|---|
| 左右对称 | img_x=cols-x-1; img_y=y |
列坐标取反,行坐标不变 |
| 上下对称 | img_x=x; img_y=rows-y-1 |
行坐标取反,列坐标不变 |
| 180° 旋转 | img_x=cols-x-1; img_y=rows-y-1 |
行列坐标同时取反 |
| 缩小一半 | img_x=2*(x-cols*0.25) |
坐标缩放 + 偏移,避免图像偏移 |
3. 避坑与优化技巧
-
坐标偏移 :缩放映射时需添加偏移量(如
cols*0.25),否则图像会偏离画布; -
遍历效率 :双层 for 循环效率较低,可改用
np.meshgrid生成映射矩阵,大幅提升速度:python
运行
x, y = np.meshgrid(np.arange(cols), np.arange(rows)) img_x = cols - x - 1 # 直接批量赋值,替代循环 img_y = y -
边界处理:映射后超出原图范围的像素会填充为 0(黑色),可通过调整映射公式避免。
总结
- remap 的核心是自定义
img_x/img_y映射矩阵,定义目标像素的原图坐标来源; - 映射矩阵必须为 float32 类型,插值方式优先选 INTER_LINEAR;
- 常用对称 / 旋转效果可通过行列坐标取反实现,缩放需配合偏移量避免图像偏移。