python实现warpaffine,配上原理和代码

16 篇文章 2 订阅

代码来源:https://github.com/shouxieai/tensorRT_Pro

 

 

 

 

 

 

 

# 实现一个仿射变换,采用双线性插值方式实现一个warpaffine
def pyWarpAffine(image, M, dst_size, constant=(0,0,0)):
    M = cv.invertAffineTransform(M) # 求仿射变换的逆矩阵,因为我们是把目的图片作为输入图片,因此需要使用逆矩阵求取原始图片的点
    constant = np.array(constant)
    ih,iw = image.shape[:2]
    dw,dh = dst_size
    dst = np.full((dh,dw,3), constant, dtype=np.uint8)
    irange = lambda p:p[0]>=0 and p[0]<iw and p[1]>=0 and p[1]<ih  # 边界判断

    # 开始遍历像素点
    # 这里需要确定的是这里为了尽量降低计算量,采用遍历目标图片的像素,显然目标图片的像素大小是确定的,无论输入的图片大小是多大
    # 最后我都会变换到目标图片大小,如输入到深度学习模型的图片应该是640x640,原始图片的大小为1080x1920,显然遍历原始图片的计算很大
    # 遍历目标的图片是固定的且不大,那么这个仿射变换如何做呢?
    # 1. 首先输入的仿射变换矩阵是从原始图片的点--->目标图片的点,因此需要取逆变换获取到从目标图像的点--->原始图片的点
    # 2. 当变换到原始图片的点位置时,将采用双线性变换的方法计算该点在原始位置的像素值
    # 3. 如何计算呢?这里需要想明白,双线的本质是通过四个点的值计算一个点的值,那么变换到原始图片的点就是我们需要求的点值,
    #    这个计算出来的值将直接赋值到目标图片对应位置,但是这四个点如何选取?其实很简单,就取相邻的四个点即可如:
    #     (0,0) (1,0)      (250,250)  (251,250)
    #     (0,1) (1,1)      (250,251)  (251,251)
    #    这个四个点的选取就是变换过来的点的相邻四个点即可,如何做呢?上下取整即可如上面我举例两个点,
    #    假如从目标的点变换到原始图片的点为(250.35,250.65),那么这个点正好在上面的四个点的范围内,计算相对位置就是(0.35,0.65)
    #    然后通过双线性计算该点的值,把该点的值直接赋值目标待求点位置即可,理解到这一步基本就完全理解了
    for y in range(dh):
        for x in range(dw):
            # 构造一个齐次矩阵
            homogeneous = np.array([[x,y,1]]).T # 一个列矩阵
            ox, oy = M @ homogeneous # 把目标的点仿射变换为原始图像的点
            low_ox = int(np.floor(ox)) # 向下取整
            low_oy = int(np.floor(oy)) # 向下取整
            high_ox = low_ox + 1 # 向上取整
            high_oy = low_oy + 1 # 向上取整
            # 双线性插值
            # p0        p1
            #       0
            # p2        p3
            # 针对图片来说
            pos = ox - low_ox, oy - low_oy # 获取相对位置
            p0_area = (1 - pos[0]) * (1 - pos[1])
            p1_area = pos[0] * (1 - pos[1])
            p2_area = (1 - pos[0]) * pos[1]
            p3_area = pos[0] * pos[1]
            
            p0 = low_ox, low_oy
            p1 = high_ox, low_oy
            p2 = low_ox, high_oy
            p3 = high_ox, high_oy
            print(image[p0[1], p0[0]])
            
            p0_value = image[p0[1], p0[0]] if irange(p0) else constant
            p1_value = image[p1[1], p1[0]] if irange(p1) else constant
            p2_value = image[p2[1], p2[0]] if irange(p2) else constant
            p3_value = image[p3[1], p3[0]] if irange(p3) else constant
            dst[y, x] = p0_area * p0_value + p1_area * p1_value + p2_area * p2_value + p3_area * p3_value

    return dst


cat1 = cv.imread("cat1.png")
#acat1_cv, M, inv = align(cat1, (100, 100))
M = cv.getRotationMatrix2D((0, 0), -30, 3)
acat1_cv = cv.warpAffine(cat1, M, (640, 640))
acat1_py = pyWarpAffine(cat1, M, (640, 640))

plt.figure(figsize=(10, 10))
plt.subplot(1, 2, 1)
plt.title("OpenCV")
plt.imshow(acat1_cv[..., ::-1])

plt.subplot(1, 2, 2)
plt.title("PyWarpAffine")
plt.imshow(acat1_py[..., ::-1])

plt.show()

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值