精华内容
下载资源
问答
  • 图像处理仿射变换
    2022-07-24 15:53:43

    一. 仿射变换

    仿射变换都是借助cv2.wrapAffine函数。关键在于计算M矩阵

    关于wrapAffine函数,有一个细节需要注意:参数dst尺寸,最开始我是以为resize的,但结果不是resize,而是裁剪。下面细细解释:原图如下:尺寸为 364 x 480

     通过以下的代码:

        M = np.float32([[1, 0, -240],
                      [0, 1, -182]])
        height, width = img.shape[:2]
        img2 = cv2.warpAffine(img, M, dsize=(int(width), int(height)), flags=cv2.INTER_AREA, borderValue=(128,128,128))
        cv2.namedWindow('fig2',cv2.WINDOW_NORMAL)
        cv2.imshow('fig2',img2)

    图像变为:尺寸依旧是 364 x 480

    此时,若我们单纯把输出的尺寸变一下如下,变成1/2,

        img2 = cv2.wa
    更多相关内容
  • 图像仿射变换

    2022-04-26 19:03:10
    常见的图像映射关系有缩放、翻转、仿射变换、透视、重映射。 1.缩放   在OpenCV中提供函数cv2.resize()实现对图像的缩放,该函数的具体形式如下: dst = cv2.resize( src, dsize[, fx[, fy[, interpolation]]] ) ...

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

      在OpenCV中仿射函数为cv2.warpAffine(),它通过一个变换矩阵(映射矩阵)M 实现变换,具体为:dst(𝑥, 𝑦) = src(𝑀11𝑥 + 𝑀12𝑦 + 𝑀13, 𝑀21𝑥 + 𝑀22𝑦 + 𝑀23)。如下图所示,通过一个变换矩阵M将原始图像O变换为仿射图像R
    在这里插入图片描述
    图1  仿射图像R=变换矩阵M × 原始图像O

       利用仿射函数cv2.warpAffine()可以实现对图像的旋转,其函数的语法格式如下:dst = cv2.warpAffine( src, M, dsize[, flags[, borderMode[, borderValue]]] )

    参数解析:
    dst :仿射变换后输出的图像,该图像的类型与原始图像的类型相同,由dsize 决定它的的实际大小。
    src :要进行仿射变换的原始图像。
    M :一个 2×3 的变换矩阵。使用不同的变换矩阵可以实现不同的仿射变换。
    dsize:输出图像的尺寸大小。
    flags :插值方法,默认为 INTER_LINEAR。当该值为 WARP_INVERSE_MAP 时,意味着 M 是逆变换类型,实现从目标图像 dst 到原始图像 src 的逆变换。具体可选值可见下表。

    类型说明
    cv2.INTER_NEAREST最临近插值
    cv2.INTER_LINEAR双线性插值(默认方式)
    cv2.INTER_CUBIC三次样条插值。首先对源图像附近的 4×4 近邻区域进行三次样条拟合,然后将目标像素对应的三次样条值作为目标图像对应像素点的值
    cv2.INTER_AREA区域插值,根据当前像素点周边区域的像素实现当前像素点的采样。该方法类似最临近插值方式
    cv2.INTER_LANCZOS4一种使用 8×8 近邻的 Lanczos 插值方法
    cv2.INTER_LINEAR_EXACT位精确双线性插值
    cv2.INTER_MAX差值编码掩码
    cv2.WARP_FILL_OUTLIERS标志,填补目标图像中的所有像素。如果它们中的一些对应源图像中的奇异点(离群值),则将它们设置为零
    cv2.WARP_INVERSE_MAP标志,逆变换。例如,极坐标变换: 如果 flag 未被设置,则进行转换:dst(∅, 𝜌) = src(𝑥, 𝑦);如果 flag 被设置,则进行转换:dst(x, y) = src(∅, ρ)

    borderMode :边类型, 默认为 BORDER_CONSTANT。当 该值为 BORDER_TRANSPARENT 时,意味着目标图像内的值不做改变,这些值对应原始图像内的异常值。
    borderValue:边界值,默认为 0。

      由此可见,通过转换矩阵M将原始图像src转换为目标图像dst:dst(𝑥, 𝑦) = src(𝑀11𝑥 + 𝑀12𝑦 + 𝑀13, 𝑀21𝑥 + 𝑀22𝑦 + 𝑀23)

      因此所进行仿射变换种类完全取决于转换矩阵 M

    1. 平移

      通过转换矩阵M可以实现将原始图像src转换为目标图像dst: dst(𝑥, 𝑦) = src(𝑀11𝑥 + 𝑀12𝑦 + 𝑀13, 𝑀21𝑥 + 𝑀22𝑦 + 𝑀23)

      将原始图像src向右侧移动150个像素、向下方移动250个像素,其对应关系为:dst (x, y) = src (x + 100, y + 200)。完整的表达式为dst (x, y) = src (1·x + 0·y + 100, 0·x + 1·y + 200)

      根据上述表达式可以确定对应的转换矩阵 M 中各个元素的值为:

    元素
    𝑀111
    𝑀120
    𝑀13150
    𝑀210
    𝑀221
    𝑀23250

      将上述值代入转换矩阵M,得到:
    [ 1 0 150 0 1 200 ] \begin{bmatrix} 1&0&150\\ 0&1&200\\ \end{bmatrix} [1001150200]

    程序示例一

    利用仿射函数 cv2.warpAffine()实现对图像的平移操作。

    import cv2
    import numpy as np
    lena = cv2.imread("./lena.jpg")  # 读取原图
    height, width = lena.shape[:2]  # 获取图像的高度和宽度
    x = 120 #向右侧移动 120 个像素
    y = 200 #向下方移动 200 个像素
    M = np.float32([[1, 0, x], [0, 1, y]])  #转换矩阵M
    Panned_lena = cv2.warpAffine(lena, M, (width, height))
    cv2.imshow("原始图像", lena)
    cv2.imshow("平移图像", Panned_lena)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    程序运行结果如下:
    在这里插入图片描述
    图2  原始图像

    在这里插入图片描述
    图3  平移图像

    2. 旋转

      在使用函数 cv2.warpAffine()对图像进行旋转时,可以通过函数 cv2.getRotationMatrix2D()获取转换矩阵。该函数的语法格式为:retval=cv2.getRotationMatrix2D(center, angle, scale)

    参数解析:
    center :旋转中心点。
    angle :旋转角度,正数表示逆时针旋转,负数表示顺时针旋转。
    scale :变换尺度(缩放大小)。 利用函cv2.getRotationMatrix2D()可以直接生成要使用的转换矩阵 M。例如,想要以图像中心为圆点,逆时针旋转 60°,并将目标图像缩小为原始图像的 0.7 倍,则在调用函数 cv2.getRotationMatrix2D()生成转换矩阵 M 时所使用的语句为: M=cv2.getRotationMatrix2D((height/2,width/2),60,0.7)

    程序示例二

    通过函数 cv2.warpAffine()实现图像的旋转。

    import cv2
    lena = cv2.imread("./lena.jpg")  # 读取原图
    height, width = lena.shape[:2]  # 获取图像的高度和宽度
    # 以图像中心为圆点,逆时针旋转 60°,并将目标图像缩小为原始图像的 0.7 倍
    M = cv2.getRotationMatrix2D((width/2, height/2), 60, 0.7)   #生成转换矩阵M
    rotate_lena = cv2.warpAffine(lena, M, (width, height))
    cv2.imshow("原始图像", lena)
    cv2.imshow("旋转图像", rotate_lena)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    程序运行结果如下:
    在这里插入图片描述
    图4  原始图像

    在这里插入图片描述
    图5  旋转图像

    3. 更复杂的仿射变换

      对于更复杂仿射变换,OpenCV 提供了函数cv2.getAffineTransform()来生成仿射函数 cv2.warpAffine()所使用的转换矩阵 M。该函数的语法格式为:retval=cv2.getAffineTransform(src, dst)

    参数解析:
    src:输入图像的三个点坐标。
    dst:输出图像的三个点坐标。

      在该函数中,参数 srcdst 是包含三个二维数组(x, y)点的数组。上述参数通过函数cv2.getAffineTransform()定义了两个平行四边形。srcdst 中的三个点分别对应平行四边形的左上角、右上角、左下角三个点。函数 cv2.warpAffine()以函数cv2.getAffineTransform()获取的转换矩阵 M 为参数,将 src 中的点仿射到 dst 中。函数 cv2.getAffineTransform()对所指定的点完成映射后,将所有其他点的映射关系按照指定点的关系计算确定。

    程序示例三

    设计程序完成图像仿射变换。

    import cv2
    import numpy as np
    lena=cv2.imread('./lena.jpg')
    rows,cols,ch=lena.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) #转换矩阵 M
    dst=cv2.warpAffine(lena,M,(cols,rows))  # 将所有其他点的映射关系按照指定点的关系计算确定
    cv2.imshow("原始图像",lena)
    cv2.imshow("仿射变换图像",dst)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    程序运行结果如下:
    在这里插入图片描述
    图5  原始图像
    在这里插入图片描述
    图6  仿射变换图像

    4.透视

      仿射变换可以将矩形映射为任意平行四边形,而透视变换可以将矩形映射为任意四边形。通过函数cv2.warpPerspective()可以实现透视变换,其语法为dst = cv2.warpPerspective( src, M, dsize[, flags[, borderMode[, borderValue]]] )

    参数解析:
    dst :透视处理后的输出图像,与原始图像具有相同的类型。dsize 决定输出图像的实际大小。
    src:要进行透视变换的图像。
    M :一个 3×3 的变换矩阵。
    dsize :输出图像的尺寸大小。
    flags :插值方法,默认为 INTER_LINEAR。当该值为WARP_INVERSE_MAP 时,意味着 M 是逆变换类型,能实现从目标图像 dst 到原始图像 src 的逆变换,具体可选值参见下表。

    类型说明
    cv2.INTER_NEAREST最临近插值
    cv2.INTER_LINEAR双线性插值(默认方式)
    cv2.INTER_CUBIC三次样条插值。首先对源图像附近的 4×4 近邻区域进行三次样条拟合,然后将目标像素对应的三次样条值作为目标图像对应像素点的值
    cv2.INTER_AREA区域插值,根据当前像素点周边区域的像素实现当前像素点的采样。该方法类似最临近插值方式
    cv2.INTER_LANCZOS4一种使用 8×8 近邻的 Lanczos 插值方法
    cv2.INTER_LINEAR_EXACT位精确双线性插值
    cv2.INTER_MAX差值编码掩码
    cv2.WARP_FILL_OUTLIERS标志,填补目标图像中的所有像素。如果它们中的一些对应源图像中的奇异点(离群值),则将它们设置为零
    cv2.WARP_INVERSE_MAP标志,逆变换。例如,极坐标变换: 如果 flag 未被设置,则进行转换:dst(∅, 𝜌) = src(𝑥, 𝑦);如果 flag 被设置,则进行转换:dst(x, y) = src(∅, ρ)

    borderMode :边类型, 默认为 BORDER_CONSTANT 。 当 该值为 BORDER_TRANSPARENT 时,意味着目标图像内的值不做改变,这些值对应原始图像内的异常值。
    borderValue :边界值,默认为 0。

      与仿射变换函数一样,同样可以使用一个函数来生成函数 cv2.warpPerspective()所使用的转换矩
    阵。该函数是 cv2.getPerspectiveTransform(),其语法格式为:retval = cv2.getPerspectiveTransform( src, dst )

    参数解析:
    src :输入图像的四个顶点的坐标。
    dst :输出图像的四个顶点的坐标。


      与仿射变换函数cv2.getAffineTransform()不同的。需要注意的是, src 参数和 dst 参数是包含四个点的数组,实际使用中,可以根据需要控制 src 中的四个点映射到 dst 中的四个点。

    程序示例四

    设计程序,完成图像透视。

    import cv2
    import numpy as np
    lena=cv2.imread('./lena.jpg')    #导入原图
    rows,cols=lena.shape[:2] #获取图像的行数和列数
    pts1 = np.float32([[150,50],[400,50],[60,450],[310,450]])
    pts2 = np.float32([[50,50],[rows-50,50],[50,cols-50],[rows-50,cols-50]])
    M=cv2.getPerspectiveTransform(pts1,pts2)    #转换矩阵M
    dst=cv2.warpPerspective(lena,M,(cols,rows))
    cv2.imshow("lena",lena)
    cv2.imshow("dst",dst)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

      在指定原始图像中的平行四边形顶点pts1,指定目标图像中矩形的四个顶点pts2,使用M=cv2.getPerspectiveTransform(pts1,pts2)生成转换矩阵 M。接下来,使用语句dst=cv2.warpPerspective(img,M,(cols,rows))完成从平行四边形到矩形的转换。程序运行结果如下:
    在这里插入图片描述
    图7  原始图像
    在这里插入图片描述
    图8  透视变换图像

    5. 重映射

      把一幅图像中的某个位置的像素点放置到另一幅图像内的指定位置的过程为图像的重映射。OpenCV提供的重映射函数 cv2.remap()可以实现自定义的方式的重映射。其语法格式为dst = cv2.remap( src, map1, map2, interpolation[, borderMode[, borderValue]] )

    参数解析:
    dst :目标图像,与src 有相同的大小和类型。
    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 方法,具体值参见下表。

    类型说明
    cv2.INTER_NEAREST最临近插值
    cv2.INTER_LINEAR双线性插值(默认方式)
    cv2.INTER_CUBIC三次样条插值。首先对源图像附近的 4×4 近邻区域进行三次样条拟合,然后将目标像素对应的三次样条值作为目标图像对应像素点的值
    cv2.INTER_LANCZOS4一种使用 8×8 近邻的 Lanczos 插值方法
    cv2.INTER_LINEAR_EXACT位精确双线性插值
    cv2.INTER_MAX差值编码掩码
    cv2.WARP_FILL_OUTLIERS标志,填补目标图像中的所有像素。如果它们中的一些对应源图像中的奇异点(离群值),则将它们设置为零
    cv2.WARP_INVERSE_MAP标志,逆变换。例如,极坐标变换: 如果 flag 未被设置,则进行转换:dst(∅, 𝜌) = src(𝑥, 𝑦);如果 flag 被设置,则进行转换:dst(x, y) = src(∅, ρ)

    borderMode :边界模式。当该值为 BORDER_TRANSPARENT 时,表示目标图像内的对应源图像内奇异点的像素不会被修改。
    borderValue:边界值,默认为 0。

      重映射是通过修改像素点的位置得到一幅新图像。在构建新图像时,需要确定新图像中每个像素点在原始图像中的位置。因此,映射函数的作用是查找新图像像素在原始图像内的位置

      重映射是将新图像像素映射到原始图像的过程,因此被称为反向映射。在函数 cv2.remap()中,参数 map1 和参数 map2 用来说明反向映射,map1 针对的是坐标 xmap2 针对的是坐标 y

      因为参数 map1 和参数 map2 的值是浮点数,所以目标图像可以映射回一个非整数的值,这意味着目标图像可以“反向映射”到原始图像中两个像素点之间的位置(当然,该位置是不存在像素值的)。而且由于参数 map1 和参数 map2 的值是浮点数,所以通过函数 cv2.remamp()实现的映射关系变得更加随意,可以通过自定义映射参数实现不同形式的映射。

    5.1 复制

      在映射时,通过将 map1map2的值分别设定为对应位置上的 x 轴坐标和 y 轴坐标值,可以让函数 cv2.remap()实现图像复制。

    程序示例五

    使用函数 cv2.remap()完成对图像的复制。

    import cv2
    import numpy as np
    lena = cv2.imread("./lena.jpg")
    rows, cols = lena.shape[:2]
    map1 = np.zeros(lena.shape[:2], np.float32)	#设置x轴方向的坐标
    map2 = np.zeros(lena.shape[:2], np.float32)	#设置y轴方向的坐标
    
    for i in range(rows):
        for j in range(cols):
            map1.itemset((i, j), j)
            map2.itemset((i, j), i)
            
    rst = cv2.remap(lena, map1, map2, cv2.INTER_LINEAR)
    cv2.imshow("原始图像", lena)
    cv2.imshow("复制图像", rst)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    程序运行结果如下

    在这里插入图片描述
    图9  原始图像

    在这里插入图片描述
    图10  复制图像

    5.2 绕x轴旋转

      如果想要图像绕x轴翻转,则在映射过程中需要满足:①x坐标轴的值保持不变;②y坐标轴的值以x轴为对称轴进行交换。

      反映在 map1map2 上就是map1 的值保持不变,map2 的值调整为“总行数-1-当前行号”。

      需要注意,OpenCV 中行号的下标是从 0 开始的,所以在对称关系中存在“当前行号+对称行号=总行数-1”的关系。因此在绕着 x 轴翻转时,map2 中当前行的行号调整为“总行数-1-当前行号”。

    程序示例六

    使用函数 cv2.remap()实现对图像绕 x 轴翻转。

    import cv2
    import numpy as np
    lena=cv2.imread("./lena.jpg")
    rows,cols=lena.shape[:2]
    map1 = np.zeros(lena.shape[:2],np.float32)
    map2 = np.zeros(lena.shape[:2],np.float32)
    
    for i in range(rows):
        for j in range(cols):
            map1.itemset((i,j),j)
            map2.itemset((i,j),rows-1-i)
    rst=cv2.remap(lena,map1,map2,cv2.INTER_LINEAR)
    
    cv2.imshow("原始图像",lena)
    cv2.imshow("绕x轴旋转图像",rst)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    程序运行结果如下
    在这里插入图片描述
    图11  原始图像

    在这里插入图片描述
    图12  绕x轴旋转图像

    5.3 绕y轴旋转

      如果想要图像绕y轴翻转,则在映射过程中需要满足:①y坐标轴的值保持不变;②x坐标轴的值以y轴为对称轴进行交换。

      反映在 map1map2 上就是map2 的值保持不变,map1 的值调整为“总行数-1-当前列号”。

      需要注意,OpenCV 中列号的下标是从 0 开始的,所以在对称关系中存在“当前列号+对称列号=总列数-1”的关系。因此在绕着 y 轴翻转时,map2 中当前行的行号调整为“总列数-1-当前列号”。

    程序示例七

    使用函数 cv2.remap()实现对图像绕 y 轴翻转。

    import cv2
    import numpy as np
    lena=cv2.imread("./lena.jpg")
    rows,cols=lena.shape[:2]
    map1 = np.zeros(lena.shape[:2],np.float32)
    map2 = np.zeros(lena.shape[:2],np.float32)
    
    for i in range(rows):
        for j in range(cols):
            map1.itemset((i,j),cols-1-j)
            map2.itemset((i,j),i)
    rst=cv2.remap(lena,map1,map2,cv2.INTER_LINEAR)
    
    cv2.imshow("原始图像",lena)
    cv2.imshow("绕y轴旋转图像",rst)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    在这里插入图片描述
    图13  原始图像

    在这里插入图片描述
    图14  绕y轴旋转图像

    5.4 绕x轴、y轴翻转

      如果想让图像绕着 x 轴、y 轴翻转,意味着在映射过程中:①x 坐标轴的值以 y 轴为对称轴进行交换;②y 坐标轴的值以 x 轴为对称轴进行交换

      反映在 map1map2 上: map1 的值调整为“总列数-1-当前列号”; map2 的值调整为“总行数-1-当前行号”。

    程序示例八

    使用函数 cv2.remap()实现图像绕 x 轴、y 轴翻转。

    import cv2
    import numpy as np
    lena=cv2.imread("./lena.jpg")
    rows,cols=lena.shape[:2]
    map1 = np.zeros(lena.shape[:2],np.float32)
    map2 = np.zeros(lena.shape[:2],np.float32)
    
    for i in range(rows):
        for j in range(cols):
            map1.itemset((i,j),cols-j-1)
            map2.itemset((i,j),rows-1-i)
    rst=cv2.remap(lena,map1,map2,cv2.INTER_LINEAR)
    
    cv2.imshow("原始图像",lena)
    cv2.imshow("绕x轴、y轴旋转图像",rst)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    在这里插入图片描述
    图15  原始图像

    在这里插入图片描述
    图16  绕x轴、y轴旋转图像

    5.5 x轴、y轴互换

      如果想让图像的 x 轴、y 轴互换,意味着在映射过程中,对于任意一点,都需要将其 x 轴、y 轴坐标互换。反映在 map1 和 map2 上就是:①map1 的值调整为所在行的行号;②map2 的值调整为所在列的列号。

      需要注意的是,如果行数和列数不一致,上述运算可能存在值无法映射的情况。默认情况下,无法完成映射的值会被处理为 0

    程序示例九

    使用函数 cv2.remap()实现图像绕 x 轴、y 轴互换。

    import cv2
    import numpy as np
    lena=cv2.imread("./lena.jpg")
    rows,cols=lena.shape[:2]
    map1 = np.zeros(lena.shape[:2],np.float32)
    map2 = np.zeros(lena.shape[:2],np.float32)
    
    for i in range(rows):
        for j in range(cols):
            map1.itemset((i,j),i)
            map2.itemset((i,j),j)
    rst=cv2.remap(lena,map1,map2,cv2.INTER_LINEAR)
    
    cv2.imshow("原始图像",lena)
    cv2.imshow("x轴、y轴互换图像",rst)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    在这里插入图片描述
    图17  原始图像

    在这里插入图片描述
    图18  x轴、y轴互换图像

    展开全文
  • 数字图像处理 - 仿射变换

    千次阅读 2020-08-22 22:02:12
    设为原图像中的坐标,为变换后图像中的坐标,图像仿射变换可以表示为: 对应的矩阵表示为: 【注】:添加 1 是为了和平移变换中的维度对其,添加 1 只是为了和对应。 其中 T 可以有如下几种形式(皆为...

    几何变换

    几何变换 = 坐标的空间变换(最常用的就是 仿射变换) + 插值

    仿射变换

    设 (x, y) 为原图像中的坐标,(v,w) 为变换后图像中的坐标,图像的仿射变换可以表示为:

    \left\{\begin{matrix} x=a_1v+b_1w+c_1 \\ \\ y=a_2v+b_2w+c_2 \end{matrix}\right.

    对应的矩阵表示为:

    \begin{bmatrix} x & y & 1 \end{bmatrix}=\begin{bmatrix} v & w & 1 \end{bmatrix} \begin{bmatrix} a_1 & a_2 & 0 \\ b_1 & b_2 & 0 \\ c_1 & c_2 & 1 \end{bmatrix}=\begin{bmatrix} v & w & 1 \end{bmatrix} T

    【注】\begin{bmatrix} u & w & 1 \end{bmatrix}添加 1 是为了和平移变换中的 c 维度对其,\begin{bmatrix} x & y & 1 \end{bmatrix} 添加 1 只是为了和 \begin{bmatrix} u & w & 1 \end{bmatrix} 对应。

    其中 T 可以有如下几种形式(皆为线性变换):

    什么是线性变换?

    设算子 H,对线性空间 V 上的任意元素 a 和 b,以及数域 P 中任意 k,都有:

    H(a+b)=H(a)+H(b)

    H(ka) = kH(a)

    这两个标准可以整合为一个:

    H(ka+wb)=kH(a)+wH(b)

    而对于上述图像的仿射变换来说

    对坐标 (v_1,w_1) 和 (v_2,w_2),进行线性变换

    H[k_1(v_1,w_1)+k_2(v_2,w_2)]=k_1H[(v_1,w_1)]+k_2H[(v_2,w_2)]

    令变换后 H[(v_1,w_1)] = (x_1,y_1)H[(v_2,w_2)] = (x_2,y_2)

    则有:

    H[k_1(v_1,w_1)+k_2(v_2,w_2)]=k_1(x_1,y_1)+k_2(x_2,y_2)

    举个例子

    证明一下(垂直)偏移变换

    H[k_1(v_1,w_1)+k_2(v_2,w_2)] \\ =(k_1[v_1,w_1,1]+k_2[v_2,w_2,1] )\begin{bmatrix} 1 & 0 & 0\\ s_v & 1 & 0\\ 0 & 0 & 1 \end{bmatrix}      计算的时候将坐标转为了向量表示 {\color{Blue} (v,w) \rightarrow [v,w,1]}

    =(k_1[v_1,w_1,1])\begin{bmatrix} 1 & 0 & 0\\ s_v & 1 & 0\\ 0 & 0 & 1 \end{bmatrix} +(k_2[v_2,w_2,1] )\begin{bmatrix} 1 & 0 & 0\\ s_v & 1 & 0\\ 0 & 0 & 1 \end{bmatrix}      矩阵乘法:(A+B)C = AC+BC

    =k_1([v_1,w_1,1]\begin{bmatrix} 1 & 0 & 0\\ s_v & 1 & 0\\ 0 & 0 & 1 \end{bmatrix} )+k_2([v_2,w_2,1] \begin{bmatrix} 1 & 0 & 0\\ s_v & 1 & 0\\ 0 & 0 & 1 \end{bmatrix})   

    =k_1H([v_1,w_1,1])+k_2H([v_2,w_2,1])

    =k_1H(v_1,w_1)+k_2H(v_2,w_2)   向量转为坐标表示:  {\color{Blue} [v,w,1] \rightarrow (v,w)}

    可以得到:

    H[k_1(v_1,w_1)+k_2(v_2,w_2)]=k_1H(v_1,w_1)+k_2H(v_2,w_2)

    【注】:其实可以看到,计算过程中与变换矩阵 T 的值没有关系,换句话说,只要是矩阵变换,就一定是线性变换

     【注】:同时,也证明了神经网络模型为什么需要激活函数,因为权重计算过程本质就是矩阵计算,而单纯的矩阵计算一定是线性变换,而多层的网络模型只是多布线性变换的叠加,最终还是可以表示为一个变换,如下:

    XW_1W_2\cdots W_n=XW

    所以,神经网络模型为了表示更加复杂的变换(拟合更加复杂的函数),必须为其添加非线性变换,也就是激活函数 g

    A = g(XW)

    换种表示方法

    其实,对于神经网络来说,因为权重参数有很多层,如果采用像图像处理中仿射变换那样给向量添加 1 来进行维度对齐,则对于内存的利用率太低(行和列都多添加了一层 0)

    所以,一般的形式都改为了这样:A = g(XW)+b

    对应到图像处理的仿射变换中就是如下形式:

    \begin{bmatrix} x & y \end{bmatrix}=\begin{bmatrix} v & w \end{bmatrix} \begin{bmatrix} a_1 & a_2 \\ b_1 & b_2 \end{bmatrix}+[c_1, c_2]

    不过一般情况,图像处理中仿射变换的计算次数远没有神经网络这么多次,所以,传统的表示方式会更加方便

    前向映射的完整过程

    上述所提到的仿射变换的表示方式,属于前向映射,他的完整过程是:

    输入图像上的整数点坐标经过仿射变换到输出图像上之后,基本都会变成非整数坐标,因此,像素值会按照一定的权重分配到其周围的四个坐标上,而对于输出图像来说,其整数点坐标的像素值是由很多输入图像中的像素映射并分配过来的,所有被分配的像素值进行叠加,才是输出图像该整数点的像素值

    这样有个问题就是,输出图像某一点的像素值不能直接得到,需要遍历输入图像的所有像素值,对其进行坐标变换,分配像素值到整数位置,才能得到输出图像各像素点的像素值。这是向前映射法的缺点

    【注】:对于输出图像,还有一种可能是某些输出位置完全没有要赋值的像素。

    反向映射

    目前最常使用的(如Matlab)则是反向映射,该方法是直接通过输出图像上整数点的坐标 (x,y) 反向计算输入图像上的坐标 (v,w) ,基本上,计算后的 (v,w) 也是非整数坐标,利用其周围整数点的输入图像的像素值进行插值,就得到了点 (x,y) 的坐标值

    这样的好处就是可以计算输出图像中任意点的像素值,同时不存在空像素值的情况

    【注】:可选用的插值算法则有很多,最邻近插值、双线性插值、三线性插值等

     

     

     

     

     

     

     

     

    展开全文
  • 文章目录仿射变换平移缩放旋转斜切 仿射变换 仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。在改变过程中保持直线和平行线关系不变。数学表示如下图。...

    仿射变换

    仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。在改变过程中保持直线和平行线关系不变。数学表示如下图。
    在这里插入图片描述

    这里需要使用到齐次坐标的概念:

    齐次坐标就是将原本是N维的向量用一个n+1维向量来表示,例如二维点 p(x,y)->p(x,y,1)就成了其次坐标,同理三维点p(x,y,z)->p(x,y,z,1)也成了齐次坐标。
    齐次坐标是表示计算机图形学的重要手段之一,它既能否用来明确区分向量和点,同时也更易于进行 几何变换

    平移

    将原图每个点移动到(x + tx , y + ty)变换矩阵如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    缩放

    将每一点的横坐标放大(缩小)至sx倍,纵坐标放大(缩小)至sy倍,
    变换矩阵为:
    在这里插入图片描述
    如果需要将参考点设置在 Px Py 则需要首先将目标移动到 -Px -Py 点进行缩放 在移动回原来位置。
    在这里插入图片描述
    在这里插入图片描述
    翻转

    翻转可以分为 行方向 或者列方向取反 只需要将初始矩阵中对应着改为 -1即可

    在这里插入图片描述
    在这里插入图片描述

    旋转

    旋转矩阵如下,角度0度角为水平方向由左向右指向。顺时针为负,逆时针为正
    在这里插入图片描述

    如果需要将参考点设置在 Px Py 则需要首先将目标移动到 -Px -Py 点进行旋转 在移动回原来位置。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    斜切

    斜切矩阵如下,角度0度角为水平方向由左向右指向。顺时针为负,逆时针为正

    在这里插入图片描述
    如果需要将参考点设置在 Px Py 则需要首先将目标移动到 -Px -Py 点进行斜切变换 在移动回原来位置。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 图像仿射变换

    千次阅读 2021-07-15 20:07:11
    什么是仿射变换?3. 定义4. 常用的转换矩阵5.实际应用5.1 栗子15.2 栗子2 1. 引用 opencv学习(三十五)之仿射变换warpAffine 2. 什么是仿射变换? 3. 定义 向量空间中进行一次线性变换(乘以一个矩阵A)再加上一个平...
  • 该算法对水印图像的预处理采用有限整数域上的拟仿射变换,拟仿射变换有较好的置乱效果及较大的置乱周期,从图像信息加密的安全性角度来看,它优于Arnold等常见的几何置乱变换,利用混沌序列提取原始图像的若干块组...
  • 上一篇文章,我们讲解了图像金字塔,这篇文章我们来了解仿射变换。 仿射? 任何仿射变换都可以转换成,乘以一个矩阵(线性变化),再加上一个向量(平移变化)。 实际上仿射是两幅图片的变换关系。 例如我们可以通过...
  • 文章目录[仿射变换(Affine Transformation)]...仿射变换(Affine Transformation) 转自:https://www.cnblogs.com/bnuvincent/p/6691189.html http://www.cnblogs.com/ghj1
  • CV小白从0开始学数字图像处理 30 仿射变换( Afine Transformations )——旋转 使用仿射变换,逆时针旋转30度。 使用仿射变换,逆时针旋转30度并且能让全部图像显现(也就是说,单纯地做仿射变换会让图片边缘丢失...
  • 图像处理-仿射变换

    2020-06-27 18:25:46
     这五种变化由原图像转变到变换图像的过程,可以用仿射变换矩阵进行描述。这个变换过程可以用一个2*3的矩阵与原图进行相乘得到。不共线的三对点决定了唯一的仿射变换。  由公式看到,仿射变换可以描述为一个线性...
  • 本节介绍了仿射变换的概念、类型、基本仿射变换矩阵、OpenCV-Python与仿射变换相关的主要函数及语法说明,并提供了两种不同方式实现的图像旋转和任选三个点将圈定子图放大的示例。通过阅读相关内容可以有助于大家...
  • 本文介绍了仿射变换的类型及其关系以及仿射...实际中一般图像仿射变换就是平移、旋转、缩放和错切的叠加组合,每叠加一个处理,就进行一次仿射变换矩阵和齐次坐标的乘法,再进行一次处理则再乘一次对应变换的矩阵。
  • MATLAB中应用于图像仿射变换

    千次阅读 2022-01-06 11:28:55
    仿射变换的类型如下表所示 以函数checkerboard中生成的棋盘图像进行顺时针旋转30°为例 注意:imtransform在默认的情况下将输出范围之外的位置全部重为0! 代码如下: f=checkerboard(50);%生成棋盘图像 angle=pi/6...
  • 图像仿射变换原理和实现发布时间:2018-05-06 01:03,浏览次数:1148仿射变换能够保持图像的“平直性”,包括旋转,缩放,平移,错切操作。一般而言,仿射变换矩阵为2*3的矩阵,第三列的元素起着平移的作用,前面...
  • 仿射变换与透视变换
  • 仿射变换图像中的平行关系、面积比、共线线段或平行线段的长度比、矢量的线性组合不变,仿射变换是旋转和非均匀缩放的复合。
  • OpenCV-Python图像处理仿射变换详解及案例.rar
  • 一、图像仿射变换 1.原理 仿射变换(Affine Transformation 或Affine Map)是一种二维坐标(x, y)到二维坐标(u, v)的线性变换,转换过程坐标点的相对位置和属性不发生变换,是一个线性变换,该过程只发生旋转和...
  • 图像仿射变换python实现

    千次阅读 2020-03-18 21:54:21
    写文章不易,如果您觉得此文对您有所帮助,请帮忙点赞、评论、收藏,感谢您! 一. 仿射变换介绍: 请参考:图解图像仿射变换... 图像仿射变换图像平移:https://www.cnblogs.com/wojianxin/p/12519498.html 二...
  • 【Opencv图像处理】透视与仿射变换

    千次阅读 2022-03-07 10:07:30
    C++透视与仿射变换透视与仿射变换Opencv代码仿射变换代码透视变换代码 透视与仿射变换 你有没有注意到,当你拍摄一个矩形平面物体的图像时,角落角度很少是90°? 这种现象是透视投影的一个特征,其中 3D 场景中的点...
  • C++与opencv实现常用图像处理仿射变换 包括 旋转、平移、缩放、偏移、组合变换等
  • 当分镜头中动画图像场景较为复杂时,仿射变换主要采用图像跟踪的方法对图像之间的帧数进行关联处理,通过数据运算来判断图像之间的匹配程度,确立仿射变换的目标、完成动画图像的合成。实验结果表明,基于仿射变换的...
  • 有的时候,我们想要计算指标,我们在裁剪出来以后发现图像是Geotiff,是具有地理坐标的。而利用shp裁剪或者用行列...这个时候就需要使用仿射变换来解决这个问题。 参考: https://zhuanlan.zhihu.com/p/220109909 ...
  • 变换模型是指根据待匹配图像与背景图像之间几何畸变的情况,所选择的能最佳拟合两幅图像之间变化的几何变换模型。可采用的变换模型有如下几种:刚性变换、... 其中第三个的仿射变换就是我们这节要讨论的。 仿射变换...
  • 利用Python实现图像仿射变换   仿射变换通常用于图像的几何矫正、图像配准   在透视映射下,物体的形状会失真。例如,虽然原本矩形的窗户、书本,由于成像角度的原因,最终呈现在图像上,便会是另外一种不太...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,013
精华内容 5,205
关键字:

图像处理仿射变换