OpenCV干货4:几何变换
根据OpenCV函数的不同,将映射关系划分为缩放、翻转、仿射变换、透视、重映射等。
缩放
OpenCV中,使用函数cv2.resize()实现对图像的缩放
代码格式如下:
dst=cv2.resize(src,dsize[,fx[,fy[,interpolation]]])
-
dst代表输出的目标图像,该图像的类型与src相同,其大小为dsize(当该值非零时),或可以通过src.size()、fx、fy计算得到;
-
src代表需要缩放的原始图像;
-
dsize代表输出图像大小,x、y方向缩放大小为
f x = ( d o u b l e ) d s i z e . w i d t h / s r c . c o l s fx=(double)dsize.width/src.cols fx=(double)dsize.width/src.colsf y = ( d o u b l e ) d s i z e . h e i g h t / s r c . r o w s fy=(double)dsize.height/src.rows fy=(double)dsize.height/src.rows
-
fx代表水平方向的缩放比例, fy代表垂直方向的缩放比例,则目标图像大小为
d s i z e = S i z e ( r o u n d ( f x ∗ s r c . c o l s ) , r o u n d ( f y ∗ s r c . r o w s ) ) dsize=Size(round(fx*src.cols),round(fy*src.rows)) dsize=Size(round(fx∗src.cols),round(fy∗src.rows)) -
interpolation代表插值方式,指在对图像进行几何处理时,给无法直接通过映射得到值的
像素点赋值。
缩小图像时,使用区域插值方式(INTER_AREA)能得到最好的效果;
放大图像时,使用三次样条插值(INTER_CUBIC)、双线性插值(INTER_LINEAR)都能取得较好的效果。三次样条插值速度较慢,双线性插值速度相对较快且效果并不逊色。
函数cv2.resize()内dsize参数与图像shape属性在行、列的顺序上是不一致的:
- shape属性中,第1个值对应行数,第2个值对应列数;
- dsize参数中,第1个值对应列数,第2个值对应行数。
翻转
OpenCV中,图像的翻转采用函数cv2.flip()实现
代码格式如下:
dst=cv2.flip(src,flipCode)
- src 代表要处理的原始图像
- flipCode 代表旋转类型:0绕x轴,正数绕y轴,负数绕x、y同时翻转。
仿射
仿射变换是指图像通过一系列几何变换实现平移、旋转等操作。
OpenCV中的仿射函数为cv2.warpAffine(),其通过一个变换矩阵(映射矩阵)M实现变换
d
s
t
(
x
,
y
)
=
s
r
c
(
M
11
x
+
M
12
y
+
M
13
,
M
21
x
+
M
22
y
+
M
23
)
dst(x,y)=src(M11x+M12y+M13,M21x+M22y+M23)
dst(x,y)=src(M11x+M12y+M13,M21x+M22y+M23)
代码格式如下:
dst=cv2.warpAffine(src,M,dsize[,flags[,borderMode[,borderValue]]])
- M代表变换矩阵。使用不同变换矩阵,可实现不同仿射变换
- flags代表插值方法,默认为INTER_LINEAR。当该值为WARP_INVERSE_MAP时,意味着M是逆变换类型,实现从目标图像dst到原始图像src的逆变换
- borderMode 代表边类型,默认为 BORDER_CONSTANT。当该值为BORDER_TRANSPARENT 时,意味着目标图像内的值不做改变,这些值对应原始图像内的异常值
- borderValue代表边界值,默认是0
若忽略可选参数,则代码格式为:
dst=cv2.warpAffine(src ,M ,dsize)
平移
根据公式可以很方便地口算出转换矩阵
旋转
可以通过函数cv2.getRotationMatrix2D()获取转换矩阵,代码格式如下:
retval=cv2.getRotationMatrix2D(center,angle,scale)
- center为旋转的中心点
- angle为旋转角度,正数表示逆时针旋转,负数表示顺时针旋转
- scale为变换尺度(缩放大小)
例如,想要以图像中心为圆点,逆时针旋转45°,并将目标图像缩小为原始图像的0.6倍
M=cv2.getRotationMatrix2D((height/2,width/2),45,0.6)
生成转换矩阵
OpenCV提供了函数cv2.getAffineTransform()来生成仿射函数cv2.warpAffine()所使用的转换矩阵M
代码格式如下:
retval=cv2.getAffineTransform(src,dst)
- src代表输入图像的三个点坐标;
- dst代表输出图像的三个点坐标。
透视
透视变换可以将矩形映射为任意四边形,通过函数cv2.warpPerspective()实现。
代码格式如下:
dst=cv2.warpPerspective(src,M,dsize[,flags[,borderMode[,borderValue]]])
- src 代表要透视的图像。
- M 代表一个3×3的变换矩阵。
- dsize代表输出图像的尺寸大小。
- flags 代表插值方法,默认为INTER_LINEAR。当该值为WARP_INVERSE_MAP时,意味着M是逆变换类型,能实现从目标图像dst到原始图像src的逆变换。
- borderMode 代表边类型,默认为 BORDER_CONSTANT。当该值为 BORDER_TRANSPARENT时,意味着目标图像内的值不做改变,这些值对应原始图像内的异常值。
- borderValue 代表边界值,默认是0。
生成转换矩阵
使用函数cv2.getPerspectiveTransform()来生成函数cv2.warpPerspective()所使用的转换矩阵。
retval=cv2.getPerspectiveTransform(src,dst)
- src代表输入图像的四个顶点的坐标。
- dst代表输出图像的四个顶点的坐标。
重映射
把一幅图像内的像素点放置到另外一幅图像内的指定位置,这个过程称为重映射。
OpenCV内的重映射函数cv2.remap()提供了更方便、更自由的映射方式
dst=cv2.remap(src,map1,map2,interpolation[,borderMode[,borderValue]])
-
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时,表示目标图像内的对应源图像内奇异点(outliers)的像素不会被修改。
-
borderValue 代表边界值,该值默认为0。
复制
- 将map1的值设定为对应位置上的x轴坐标值。
- 将map2的值设定为对应位置上的y轴坐标值。
绕x轴翻转
- map1的值保持不变。
- map2的值调整为“总行数-1-当前行号”。
绕y轴翻转
- map1的值调整为“总列数-1-当前列号”。
- map2的值保持不变。
同时绕xy翻转
- map1的值调整为“总列数-1-当前列号”。
- map2的值调整为“总行数-1-当前行号”。
x、y轴互换
- mapx的值调整为所在行的行号。
- mapy的值调整为所在列的列号。
缩放
这段建议画图帮助理解,此处我引用书籍例子
缩小图像后,可以将图像固定在围绕其中心的某个区域。例如,将其x轴、y轴设置为:
- 在目标图像的x轴(0.25·x轴长度,0.75·x轴长度)区间内生成缩小图像;x轴其余区域的点取样自x轴上任意一点的值。
- 在目标图像的y轴(0.25·y轴长度,0.75·y轴长度)区间内生成缩小图像;y轴其余区域的点取样自y轴上任意一点的值。
为了处理方便,我们让不在上述区域的点都取(0,0)坐标点的值。
欢迎朋友们找我讨论学习中的问题
希望朋友们能点赞收藏加关注支持我的后续总结~