opencv warpAffine()函数理解--图像仿射变换

opencv怎么学?
首先你对opencv要有一个比较粗浅的认识,下方是介绍的链接;

  1. opencv中文教程:http://www.woshicver.com/FirstSection/0_OpenCV-Python Tutorials/
    没事打开看看前几节,就到看小说了。
  2. Mat - 基本图像容器,你有必要了解一番,这是图像数据的底层数据结构,你不了解能行吗?链接:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/core/mat - the basic image container/mat - the basic image container.html#matthebasicimagecontainer

接下来就是具体遇到一个陌生函数了,怎么了解呢?
譬如说本文的warpAffine函数,首先是不是应该看看帮助文档,如果是在jupyter notebook中,Shift+Tab键就可以查看其docstring,内容如下:

warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) -> dst
.   @brief Applies an affine transformation to an image.
.   The function warpAffine transforms the source image using the specified matrix:

dst ( x , y ) = src ( M 11 x + M 12 y + M 13 , M 21 x + M 22 y + M 23 ) \texttt{dst} (x,y) = \texttt{src} ( \texttt{M} _{11} x + \texttt{M} _{12} y + \texttt{M} _{13}, \texttt{M} _{21} x + \texttt{M} _{22} y + \texttt{M} _{23}) dst(x,y)=src(M11x+M12y+M13,M21x+M22y+M23)
还有其他内容我就不再粘贴,最关键的参数就是变换矩阵M,它是一个 2 × 3 2\times3 2×3的变换矩阵。那么核心问题就是你对变换矩阵有多少了解,对线性变换了解多少,对旋转矩阵有没有印象,对于放缩有没有了解,对平移操作有多少认识,最终归结于对矩阵分析有多少认识。仿射变换本质上就是线性变换+平移
需要明确的是仿射变换是对坐标、位置进行变换,变换前后相应位置的像素内容是不变的,两像素之间的位置空隙是通过插值方式填充的。

接下来可以搜一些博客看看他们的描述以及我认为最为重要的是例子,下面这个链接是我觉得不错的内容,不妨看看:https://blog.csdn.net/keith_bb/article/details/56331356?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase

再看看opencv中文教程的示例:
http://www.woshicver.com/FifthSection/4_2_图像几何变换/

还有一个需要注意的参数,就是dsize
他决定着输出图像的尺寸大小,从变换后的图像的左上角开始计数的。不管经过仿射变换后,图像的大小是什么情况,只从左上角开始选取指定dsize边长的图像块里的像素进行显示。仿射变换拆解开来,有一步就是平移,平移的过程中就会涉及到空白区域的填充,会用boardvalue指定的值进行填充。

举例:本例是缩放+平移仿射变换

import cv2
import numpy as np

def crop_hwc(image, bbox, out_sz, padding=(0, 0, 0)):
    a = (out_sz-1) / (bbox[2]-bbox[0])
    b = (out_sz-1) / (bbox[3]-bbox[1])
    c = -a * bbox[0]  # c,d计算的是水平方向和竖直方向平移的距离
    d = -b * bbox[1]
    mapping = np.array([[a, 0, c],   # a、b分别表示水平方向和竖直方向缩放的比例
                        [0, b, d]]).astype(np.float)
    crop = cv2.warpAffine(image, mapping, (out_sz, out_sz),
                          borderMode=cv2.BORDER_CONSTANT, borderValue=padding)
    return crop

def pos_s_2_bbox(pos, s):
    # 计算裁切的框的左上角和右下角的坐标位置(小数)
    return [pos[0]-s/2, pos[1]-s/2, pos[0]+s/2, pos[1]+s/2]

img = cv2.imread('Cambridge.jpeg')
img.shape   # 本行输出为: (347, 474, 3)

avg_chans = np.mean(img, axis=(0, 1))  # 计算三通道各自的均值,为填充空白区域指定数值

target_pos = [100,100] # 选定框的中心坐标为(100,100)
s_x = 300  # 表示在原图选定边长为400的框。这里说的原图就是我们通过cv2.imread读入的原图
search_size = 400 # 表示最终的输出尺寸的边长是400
x = crop_hwc(img,pos_s_2_bbox(target_pos,s_x),search_size,avg_chans)
cv2.imshow('cropped',x)
# cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出仿射变换后的图片如下:

opencv warpAffine()函数理解--图像仿射变换_第1张图片

原图是如下:

opencv warpAffine()函数理解--图像仿射变换_第2张图片

你可能感兴趣的:(OpenCV,计算机视觉,opencv)