文章目录

  • opencv函数cv2.warpAffine 和 cv2.warpPerspective 的理解和复现
    • 1. warpAffine 函数处理仿射变换
    • 2. warp_perspective
    • 3, 实验

opencv函数cv2.warpAffine 和 cv2.warpPerspective 的理解和复现

1. warpAffine 函数处理仿射变换

仿射矩阵是2 * 3的矩阵。

首先进行坐标转换,然后应用插值

具体代码如下, 与opencv一致:

def warp_affine_forward(image, rot_mat, dst_h, dst_w):M = rot_mat.reshape([2, 3])hs, ws, cs = image.shapehh, ww = np.arange(hs), np.arange(ws)xx, yy = np.meshgrid(ww, hh)sx, sy = xx, yy # 不缩放图像tx, ty = M[0, 0] * sx + M[0, 1] * sy + M[0, 2], M[1, 0] * sx + M[1, 1] * sy + M[1, 2]# tx = np.sum(M[0, :].reshape([1, 1, 3]) * np.dstack((sx, sy, np.ones_like(sx))), axis=-1)# ty = np.sum(M[1, :].reshape([1, 1, 3]) * np.dstack((sx, sy, np.ones_like(sx))), axis=-1)dhh, dww = np.arange(dst_h), np.arange(dst_w)dxx, dyy = np.meshgrid(dww, dhh)grid_x, grid_y = dxx, dyypoints = np.dstack((tx, ty))# print(points.shape, image.shape, grid_x.shape)out = griddata(points.reshape(-1, 2), image.reshape(-1, 3), (grid_x, grid_y), method='linear')out[np.isnan(out)] = 0return out

逆变换代码:

def warp_affine(image, rot_mat, dst_h, dst_w):M = rot_mat.reshape([2, 3])hs, ws, cs = image.shapehh, ww = np.arange(dst_h), np.arange(dst_w)xx, yy = np.meshgrid(ww, hh)sx, sy = (xx + 0.5) * (ws / ws) - 0.5, (yy + 0.5) * (hs / hs) - 0.5 # 不缩放图像。# sx, sy = (xx + 0.5) * (ws / dst_w) - 0.5, (yy + 0.5) * (hs / dst_h) - 0.5 # 缩放图像tx, ty = M[0, 0] * sx + M[0, 1] * sy + M[0, 2], M[1, 0] * sx + M[1, 1] * sy + M[1, 2]# tx = np.sum(M[0, :].reshape([1, 1, 3]) * np.dstack((sx, sy, np.ones_like(sx))), axis=-1)# ty = np.sum(M[1, :].reshape([1, 1, 3]) * np.dstack((sx, sy, np.ones_like(sx))), axis=-1)mask = ((tx < 0) + (ty < 0) + (tx > ws - 1) + (ty > hs - 1)) > 0# print(mask.shape, mask.dtype, np.sum(mask))out = interp_linear(image, tx, ty)out[mask] = 0return out

也可以求解转换矩阵的逆后,再正变换,结果相同。

其中用到重查找函数:根据tx,ty坐标位置,获取值
和cv2.remap函数相同。

def interp_linear(image, tx, ty):'''类似 cv2.remap 函数:param image: h,w,c image  np.float:param tx:  dst_h * dst_w, float , 目标位置x方向:param ty:  dst_h * dst_w, float , 目标位置y方向:return:'''h, w, c = image.shapehv, wv = ty, txhh = np.floor(hv).astype(np.int32)ww = np.floor(wv).astype(np.int32)u = hv - hhv = wv - ww# special caseu[hh < 0] = 0hh[hh < 0] = 0u[hh >= h - 1] = 1.0hh[hh >= h - 1] = h - 2v[ww < 0] = 0ww[ww < 0] = 0v[ww >= w - 1] = 1.0ww[ww >= w - 1] = w - 2# v = v.reshape(-1)w00 = (1-u)*(1-v)w01 = u * (1-v)w10 = (1-u) * vw11 = u*vout = w00[..., None] * image[hh, ww] + w10[..., None]  * image[hh, ww + 1] + w01[..., None]  * image[(hh + 1), ww] + w11[..., None]  * image[hh + 1, ww + 1]return out

2. warp_perspective

warpPerspective 和 warpAffine 是类似的。
但是warpPerspective的转换矩阵是3*3的透视变换矩阵,经过变换后平行线可能不在平行

一个逆变换 和 两个正变换的代码如下:

# 逆变换函数
def warp_perspective(image, pers_mat, dst_h, dst_w):M = pers_mat.reshape([3, 3])hs, ws, cs = image.shapehh, ww = np.arange(dst_h), np.arange(dst_w)xx, yy = np.meshgrid(ww, hh)sx, sy = (xx + 0.5) * (ws / ws) - 0.5, (yy + 0.5)* (hs / hs) - 0.5# sx, sy = (xx + 0.5) * (ws / dst_w) - 0.5, (yy + 0.5) * (hs / dst_h) - 0.5  # 缩放图像t = M[2, 0] * sx + M[2, 1] * sy + M[2, 2]tx, ty = M[0, 0] * sx + M[0, 1] * sy + M[0, 2] , M[1, 0] * sx + M[1, 1] * sy + M[1, 2]tx, ty = tx / t, ty / t# out = np.zeros_like(image)mask = ((tx < 0 ) + (ty < 0) + (tx > ws - 1) + (ty > hs - 1)) > 0print(mask.shape, mask.dtype, np.sum(mask))# out = interp_linear(image, tx, ty)out = cv2.remap(image, tx.astype(np.float32), ty.astype(np.float32), interpolation=cv2.INTER_LINEAR)out[mask] = 0return out
# 正变化函数
def warp_perspective_forward(image, pers_mat, dst_h, dst_w):M = pers_mat.reshape([3, 3])hs, ws, cs = image.shapehh, ww = np.arange(hs), np.arange(ws)xx, yy = np.meshgrid(ww, hh)sx, sy = xx, yy  # 不缩放图像t = M[2, 0] * sx + M[2, 1] * sy + M[2, 2]tx, ty = M[0, 0] * sx + M[0, 1] * sy + M[0, 2] , M[1, 0] * sx + M[1, 1] * sy + M[1, 2]tx, ty = tx / t, ty / t# interpdhh, dww = np.arange(dst_h), np.arange(dst_w)dxx, dyy = np.meshgrid(dww, dhh)grid_x, grid_y = dxx, dyypoints = np.dstack((tx, ty))# print(points.shape, image.shape, grid_x.shape)out = griddata(points.reshape(-1, 2), image.reshape(-1, 3), (grid_x, grid_y), method='linear')out[np.isnan(out)] = 0return out# 正变换函数:这里利用np.linalg.inv 求逆矩阵,然后按照warp_perspective的方式进行
def warp_perspective_forward2(image, pers_mat, dst_h, dst_w):M = pers_mat.reshape([3, 3])M_inv = np.linalg.inv(M)M = M_invhs, ws, cs = image.shapehh, ww = np.arange(dst_h), np.arange(dst_w)xx, yy = np.meshgrid(ww, hh)sx, sy = (xx + 0.5) * (ws / ws) - 0.5, (yy + 0.5) * (hs / hs) - 0.5# sx, sy = (xx + 0.5) * (ws / dst_w) - 0.5, (yy + 0.5) * (hs / dst_h) - 0.5  # 缩放图像t = M[2, 0] * sx + M[2, 1] * sy + M[2, 2]tx, ty = M[0, 0] * sx + M[0, 1] * sy + M[0, 2], M[1, 0] * sx + M[1, 1] * sy + M[1, 2]tx, ty = tx / t, ty / t# out = np.zeros_like(image)mask = ((tx < 0) + (ty < 0) + (tx > ws - 1) + (ty > hs - 1)) > 0print(mask.shape, mask.dtype, np.sum(mask))# out = interp_linear(image, tx, ty)out = cv2.remap(image, tx.astype(np.float32), ty.astype(np.float32), interpolation=cv2.INTER_LINEAR)out[mask] = 0return out

3, 实验

验证以上代码和opencv中的一致性

import cv2
import numpy as np
from matplotlib import pyplot as plt
from scipy.interpolate import griddata
def cal_sobel(img):#分别求X,Y方向的梯度grad_X=cv2.Sobel(img,-1,1,0)grad_Y=cv2.Sobel(img,-1,0,1)#求梯度图像grad=cv2.addWeighted(grad_X,0.5,grad_Y,0.5,0)return grad
if __name__ == "__main__":file1 = r'test.jpg'image1 = cv2.imread(file1) / 255image1 = cv2.resize(image1, (0, 0), fx=0.5, fy=0.5)h, w, c = image1.shapeprint(h, w, c)center = (w // 2, h // 2)angle = -50scale = 0.6rot_mat = cv2.getRotationMatrix2D(center, angle, scale)print(rot_mat)dst_h, dst_w = int(image1.shape[0] * 0.7), int(image1.shape[1]* 0.7)image2 = cv2.warpAffine(image1, rot_mat, (dst_w, dst_h))center = (w // 2, h // 2)angle = 50scale = 1 / 0.6rot_mat2 = cv2.getRotationMatrix2D(center, angle, scale)print(rot_mat2)image3 = warp_affine(image1, rot_mat2, dst_h, dst_w)image4 = warp_affine_forward(image1, rot_mat, dst_h, dst_w)plt.figure()plt.subplot(221)plt.imshow(image1)plt.subplot(222)plt.imshow(image2)plt.subplot(223)plt.imshow(image3)plt.subplot(224)plt.imshow(image4)plt.show()# 根据4个点求透视转换pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])pts2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])M = cv2.getPerspectiveTransform(pts1, pts2)image2 = cv2.warpPerspective(image1, M, (dst_w, dst_h), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)image3 = warp_perspective(image1, M, dst_h, dst_w)image4 = cv2.warpPerspective(image1, M, (dst_w, dst_h), flags=cv2.INTER_LINEAR)image5 = warp_perspective_forward(image1, M, dst_h, dst_w)image6 = warp_perspective_forward2(image1, M, dst_h, dst_w)plt.figure()plt.subplot(231)plt.imshow(image1)plt.subplot(232)plt.imshow(image2)plt.subplot(233)plt.imshow(image3)plt.subplot(234)plt.imshow(image4)plt.subplot(235)plt.imshow(image5)plt.subplot(236)plt.imshow(image6)plt.show()

运行上面的代码,实验结果如下:
warp affine实验结果:

warp perspective 实验结果

opencv函数cv2.warpAffine 和 cv2.warpPerspective 的理解和复现相关推荐

  1. opencv中cv2.warpAffine 和 cv2.warpPerspective的广泛应用

    大家不要再理解错了!warpPerspective和warpAffine 不仅仅只有透视变换一个作用. 上一次做理论题时,搜索warpPerspective,结果给我弹出来一个透视变换,如下: 当时的 ...

  2. cv2.warpAffine和cv2.warpPerspective

    Opencv仿射变换(Affine Transformation)函数:cv2.warpAffine Affine Transformation:可实现旋转,平移,缩放,变换后的平行线依旧平行. Op ...

  3. python的cv2.warpAffine()和cv2.warpPerspective()解析对比

    1.cv2.warpAffine()放射变换函数,可实现旋转,平移,缩放:变换后的平行线依旧平行 cv2.warpAffine(src, M, dsize, dst=None, flags=None, ...

  4. opencv和pytorch中的warp操作函数:cv2.warpAffine, torch.nn.functional.grid_sample, cv2.warpPerspective

    关于图像的warp操作是指利用一个旋转缩放矩阵对图像进行操作. 常见的操作有,平移,绕某个点旋转,缩放. opencv中有getRotationMatrix2D,warpAffine, getAffi ...

  5. Opencv:图像旋转,cv2.getRotationMatrix2D 和 cv2.warpAffine 函数

    学习记录如何使用opencv实现对图像的旋转操作. 1 cv2.getRotationMatrix2D(center, angle, scale) 图像的旋转矩阵一般为: 但是单纯的这个矩阵是在原点处 ...

  6. opencv学习笔记五:cv2.warpAffine()函数详解

    cv2.warpAffine()函数主要是利用变换矩阵M对图像进行如旋转.仿射.平移等变换,只需要我们提供一个2*3的变换矩阵M,就可以对图像进行变换.它一般是和cv2.getRotationMatr ...

  7. opencv图像仿射变换,cv2.warpAffine

    目录 仿射变换原理介绍 cv2.warpAffine函数介绍 代码实例 仿射变换原理介绍 仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间. 在有 ...

  8. 【OpenCV 例程200篇】25. 图像的平移(cv2.warpAffine)

    『youcans 的 OpenCV 例程200篇 - 总目录』 [youcans 的 OpenCV 例程200篇]25. 图像的平移 平移是物体位置在水平和垂直方向的移动. 像素点 (x,y) 沿 x ...

  9. OpenCV绘图函数:cv2.line、cv2.circle、cv2.rectangle、cv2.ellipse、 cv2.putText()、cv2.setMouseCallback

    ​OpenCV是一个用于图像处理.分析.机器视觉方面的开源函数库. 不管你是做科学研究,还是商业应用,opencv都能够作为你理想的工具,它可以运行在Linux.Windows.Android和Mac ...

最新文章

  1. Java线程入门第三篇
  2. 打开eclipse出现an error has occurred.see the loh file
  3. Ex 5_33 实现一个关于公式长度(其中所有文字总的出现次数)为线性时间的Horn公式可满足性问题_第十次作业...
  4. [python opencv 计算机视觉零基础到实战] 十一找到图片中指定内容
  5. matlab gui 密码登录 论文,MATLAB GUI 密码输入
  6. java中如何做模糊查询_到底Java里的模糊查询语句该怎么写
  7. [转]资本经营董事长班告诉你:不只企业有商业模式,个人商业价值更重要
  8. ES6高级使用技巧(reduce,filter篇)
  9. 花滑三周连跳_花滑女单短节目惊现三周半跳 称就像做梦一样
  10. 基于JAVA+SpringMVC+Mybatis+MYSQL的医学药品信息管理系统
  11. freemarker 导出html格式word_如何导出 Kindle 上的读书笔记
  12. 231 · 自动补全
  13. php分享十八七:mysql基础
  14. 阿里巴巴商学院计算机考研,2017年杭州师范大学阿里巴巴商学院826计算机基础之C程序设计考研仿真模拟题...
  15. mac 中用到的svn命令 持续更新
  16. 无人驾驶汽车系统入门(十四)——ROS入门与实践(1)
  17. STM32——WAVWM8978简介
  18. Elasticsearch Refresh vs Flush
  19. 国开大学 C语言程序 形考任务4,[国家开放大学] 国开电大人体生理学形考任务4...
  20. 大数据毕设/课设 - 水质情况实时监测预警可视化设计与实现

热门文章

  1. 电子科技大学--大数据论坛--相关资料
  2. iOS - iPhone手机刘海屏判断
  3. bilibili 镜像
  4. 对 cplex/gurobi MPS/LP文件格式的理解
  5. android qq隐藏功能,90﹪的人都不知道--手机QQ这些隐藏的功能!
  6. 非计算机专业全国壹级,非计算机专业专科学生全国计算机一级等级考试应试策略...
  7. 【GraphVisual】画节点与线以及移动节点线随着移动
  8. python画带权重的图
  9. 数据分析系列 9/32 | Excel进行回归分析,预测真实值
  10. 研究生联系导师需要注意什么