opencv入门:缩放,翻转,仿射,透视,重映射

几何变换

将一副图像映射到另一幅图像内的操作。

缩放

dst = cv2.resize( src, dsize[, fx[, fy[, interpolation]]] )

  • dst,输出图像,类型与原图相同,大小为dsize 或通过scr.size(),fx ,fy 计算得到
  • dsize,表示输出图像的大小(w,h),如果指定了dsize,就忽略fx,fy
  • fx,fy,水平垂直方向的缩放比例
  • interpolation,插值方式,在几何处理中,对无法直接通过影射得到值的像素点赋值。
    opencv入门:缩放,翻转,仿射,透视,重映射_第1张图片
    opencv入门:缩放,翻转,仿射,透视,重映射_第2张图片
    缩小图像时,使用区域插值方式 INTER_AREA,效果最好,放大图像使用三次样条插值和双线性插值,前者较慢。

cv2.resize() 的dsize 参数与图像shape 属性在行,列的顺序上是不一样的。shape中,(行,列),dsize中(列,行)

opencv入门:缩放,翻转,仿射,透视,重映射_第3张图片

翻转

dst=cv2.flip(src, flipCode) filpCode旋转类型
opencv入门:缩放,翻转,仿射,透视,重映射_第4张图片

img=cv2.imread("5.jpg")
x=cv2.flip(img,0)
y=cv2.flip(img,1)
xy=cv2.flip(img,-1)
cv2.imshow("img",img)
cv2.imshow("x",x)           # 沿x轴翻转
cv2.imshow("y",y)
cv2.imshow("xy",xy)             # 都翻一下。。。。
cv2.waitKey()
cv2.destroyAllWindows()

仿射

仿射变换是指图像可以通过一系列的几何变换实现平移,旋转等多种操作。改变换能够保持图像的平直性和平行性。平直性是经过仿射变换后直线还是直线,平行性是指,经过仿射变换后,平行线仍是平行线。

dst = cv2.warpAffine( src, M, dsize[, flags[, borderMode[, borderValue]]] )

  • dsize 输出图像的尺寸大小
  • M表示一个 2X3 的变换矩阵,使用不同的变换矩阵,可以实现不同的仿射变换。
  • flags表示插值方法,默认INTER_LINEAR,当是WARP_INVERSE_MAP 就表示M为逆变换类型,实现从目标图像到原始图像的逆变换。
  • borderMode 边类型,默认BORDER_CONSTANT。
  • boardVlude 代表边界值,默认0.

通过转换矩阵M 将原始图像src转换成目标图像dst。dst(, ) = src(11 + 12 + 13, 21 + 22 + 23)。所以,进行何种形式的仿射变换完全取决于转换矩阵M。下面介绍不同M实现的仿射变换。

平移

将原图右移100像素,向下200像素 dst (x, y) = src (1·x + 0·y + 100, 0·x + 1·y + 200)。得到转换矩阵 M=[[1,0,100],[0,1,200]]

img=cv2.imread("5.jpg")
height,width=img.shape[:2]
x=100
y=200
M = np.float32([[1, 0, x], [0, 1, y]])
move=cv2.warpAffine(img,M,(width,height))
cv2.imshow("original",img)
cv2.imshow("move",move)
cv2.waitKey()
cv2.destroyAllWindows()

opencv入门:缩放,翻转,仿射,透视,重映射_第5张图片

旋转

retval=cv2.getRotationMatrix2D(center, angle, scale) 通过这个函数获得转换矩阵,参数是中心点,旋转角度(正数逆时针),缩放大小。

height,width=img.shape[:2]
M=cv2.getRotationMatrix2D((width/2,height/2),45,0.6)# 以图形中心为圆点,逆时针45度,将图像缩小为原图的0.6倍。
rotate=cv2.warpAffine(img,M,(width,height))
cv2.imshow("original",img)
cv2.imshow("rotation",rotate)
cv2.waitKey()
cv2.destroyAllWindows()

更复杂的仿射变换

对于更复杂的仿射变换,Opencv提供了cv2.getAffineTransform() 来生成仿射函数 cv2.warpAffine() 所使用的转换矩阵M。

retval=cv2.getAffineTransform(src, dst) src 输入图像的三个点,dst 表示输出图像的三个点坐标。这两个参数是包含三个二维数组(x,y) 点的数组。函数定义了两个平行四边形,三个点分别对应四边形的左上角,右上角,左下角。函数 cv2.warpAffine()以函数 cv2.getAffineTransform()获取的
转换矩阵 M 为参数,将 src 中的点仿射到 dst 中。函数 cv2.getAffineTransform()对所指定的点
完成映射后,将所有其他点的映射关系按照指定点的关系计算确定。
opencv入门:缩放,翻转,仿射,透视,重映射_第6张图片

img=cv2.imread('5.jpg')
rows,cols,ch=img.shape
p1=np.float32([[0,0],[cols-1,0],[0,rows-1]]) # 原图三个角,左上,右上,左下
p2=np.float32([[0,rows*0.33],[cols*0.85,rows*0.25],[cols*0.15,rows*0.7]])
M=cv2.getAffineTransform(p1,p2)
dst=cv2.warpAffine(img,M,(cols,rows))
cv2.imshow("origianl",img)
cv2.imshow("result",dst)
cv2.waitKey()
cv2.destroyAllWindows()

opencv入门:缩放,翻转,仿射,透视,重映射_第7张图片

透视

仿射变换可以将矩形映射为任意平行四边形,透视变换则可以将矩形映射为任意四边形。

dst = cv2.warpPerspective( src, M, dsize[, flags[, borderMode[, borderValue]]] )

  • M 是一个 3X3 的变换矩阵。
  • dsize 输出图像大小 flags 插值方法 borderMode 边类型 borderValue 边界值

同样可以使用一个函数生成 cv2.warpPerspective() 所使用的转换矩阵,是cv2.getPerspecitveTransform(src, dst) 参数是图像四个顶点的坐标
opencv入门:缩放,翻转,仿射,透视,重映射_第8张图片
这里pts2 的坐标是(y,x) ,也不知道为啥。。。

重映射

把一副图像内的像素点放置到另外一副图像内的指定位置,这个过程为重映射。
dst = cv2.remap( src, map1, map2, interpolation[, borderMode[, borderValue]] )

  • map1参数有两种,表示(x,y) 点的一个映射,表示CV_16S2, CV_32FC1, CV_32FC2类型(x,y) 点的x值
  • map2也有两种,当map1 表示(x,y) 时,值为空。当map1表示(x,y) 点的x 值时,该值是CV_16UCI, CV_32FCI 类型(x,y) 点的y值。
  • Interpolation代表插值方式,这里不支持INTER_AREA方法
  • borderMode 边界模式 borderValue 代表边界值,默认0
参数理解

重映射通过修改像素点的位置得到一副新的图像。构建时需要确定新图像中每个像素在原图中的位置,映射函数的作用就是查找新图像在原图像的位置。也成为反向映射。参数map1,2 用来说明反向映射,分别对应x,y 坐标

这两个参数都是浮点数。所以目标图像可以反向映射到原始图像的两个像素点之间的位置(当然是不存在像素值的)。这是就可以使用 interpolation 的插值方式。也是因为map1,2 是浮点数,可以实现更加随意的映射。

map1 指代像素点所在位置的列号,map2指行号。例如,将结果图像某个点像素点映射为原图的 0行 3列 的像素点,map1=3,map2=0

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=
 [[217  62 124  22 219]
 [245 228 169 240 164]
 [  7 244  49   0 135]
 [232 245 161  28  49]]
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=
 [[22 22 22 22 22]
 [22 22 22 22 22]
 [22 22 22 22 22]
 [22 22 22 22 22]]
复制

通过该函数实现图像的复制

  • 将map1 设定为对应位置上的x轴坐标值
  • 将map2 设定为对应位置上的y轴坐标值
img=cv2.imread("lena.bmp")
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("original",img)                # 就不贴图了。。
cv2.imshow("result",rst)
cv2.waitKey()
cv2.destroyAllWindows()

# 就是类似这样的,两个矩阵组合对应每个点的坐标
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.]]
绕轴翻转

绕 x 轴翻转

  • x轴不变,,map1 不变
  • y轴的值以x轴为对称轴交换,,map2 改为 总行数-1-当前行号 注意行号下表从0开始。。就是map2倒过来。。
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),rows-1-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=
 [[187 203  30 126 192]
 [113 122 142 108  81]
 [190 232 114  72 243]
 [106  41 192 178 211]]
mapx=
 [[0. 1. 2. 3. 4.]
 [0. 1. 2. 3. 4.]
 [0. 1. 2. 3. 4.]
 [0. 1. 2. 3. 4.]]
mapy=
 [[3. 3. 3. 3. 3.]
 [2. 2. 2. 2. 2.]
 [1. 1. 1. 1. 1.]
 [0. 0. 0. 0. 0.]]
rst=                                  # 对图像就是倒过来
 [[106  41 192 178 211]
 [190 232 114  72 243]
 [113 122 142 108  81]
 [187 203  30 126 192]]


mapx.itemset((i,j),cols-1-j)          # 这是绕Y 轴翻转
mapy.itemset((i,j),i)


mapx.itemset((i,j),cols-1-j)
mapy.itemset((i,j),rows-1-i)          # 绕 xy 翻转

mapx.itemset((i,j),i)
mapy.itemset((i,j),j)                 # x,y轴互换
图像缩放

opencv入门:缩放,翻转,仿射,透视,重映射_第9张图片

你可能感兴趣的:(opencv从入门到放弃,opencv)