当前位置:   article > 正文

[图片校准(矫正)]——透射变换应用

透射变换

如果想要对图像进行校准,那么透射变换是非常有效的变换方法。

  • 透射变换的定义如下:将图像投影到一个新的视平面,通常也成为投影映射。
  • 详情参考链接:透射变换介绍

1、举例说明 

直观的来看,透视变换的作用就是将左侧图像的坐标点 [[50,0],[150,0],[0,200],[200,200]]
转化为新的坐标 [[0,0],[200,0],[0,200],[200,200]]

 2、应用

原图是一个旋转过的图片,现在需要做图片矫正,将图片放正。

  • 做法:手工选去需要矫正区域四个角上的点(顺序:左上、右上、右下、左下),使用透射变换对所选区域进行矫正

原图如下:

 代码:

  1. import numpy as np
  2. import cv2
  3. def order_points(pts):
  4. # 初始化坐标点
  5. rect = np.zeros((4, 2), dtype="float32")
  6. # 获取左上角和右下角坐标点
  7. s = pts.sum(axis=1)
  8. rect[0] = pts[np.argmin(s)]
  9. rect[2] = pts[np.argmax(s)]
  10. # 分别计算左上角和右下角的离散差值
  11. diff = np.diff(pts, axis=1)
  12. rect[1] = pts[np.argmin(diff)]
  13. rect[3] = pts[np.argmax(diff)]
  14. return rect
  15. def four_point_transform(image, pts):
  16. """
  17. :param image: 图片
  18. :param pts: 鼠标选中的点集
  19. :return: 返回变换后的图片
  20. """
  21. # 获取坐标点,并将它们分离开来
  22. rect = order_points(pts)
  23. (tl, tr, br, bl) = rect
  24. # 计算新图片的宽度值,选取水平差值的最大值
  25. widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
  26. widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
  27. maxWidth = max(int(widthA), int(widthB))
  28. # 计算新图片的高度值,选取垂直差值的最大值
  29. heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
  30. heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
  31. maxHeight = max(int(heightA), int(heightB))
  32. # 构建新图片的4个坐标点
  33. dst = np.array([
  34. [0, 0],
  35. [maxWidth - 1, 0],
  36. [maxWidth - 1, maxHeight - 1],
  37. [0, maxHeight - 1]], dtype="float32")
  38. # 获取仿射变换矩阵并应用它
  39. M = cv2.getPerspectiveTransform(rect, dst)
  40. # 进行仿射变换
  41. warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
  42. # 返回变换后的结果
  43. return warped
  44. def on_mouse(event, x, y, flags, param):
  45. global timg, points
  46. img2 = timg.copy()
  47. point0 = (0, 0)
  48. if event == cv2.EVENT_LBUTTONDOWN: # 左键点击
  49. point1 = (x, y)
  50. points.append([x, y])
  51. #print(x, y)
  52. cv2.circle(img2, point1, 4, (0, 255, 0), 4)
  53. cv2.imshow('origin', img2)
  54. return point0
  55. #程序获取需要矫正的区域
  56. def rectification(img_file, points):
  57. xscale, yscale = 0.9, 0.9
  58. oimg = cv2.imread(img_file)
  59. oshape = oimg.shape
  60. timg = cv2.resize(oimg, (int(oshape[1] / xscale), int(oshape[0] / yscale))) # 放大图像
  61. points = np.array(points, dtype=np.float32)
  62. points[:, 0] *= oshape[1] / int(oshape[1] / xscale) # 还原像素位置的大小
  63. points[:, 1] *= oshape[0] / int(oshape[0] / yscale)
  64. warped = four_point_transform(oimg, points)
  65. cv2.imwrite('images/final.png', warped ) # 保存图像
  66. cv2.imshow('final', warped)
  67. cv2.waitKey(0)
  68. cv2.destroyAllWindows()
  69. #手工选择区域进行图片矫正
  70. def image_rectification(img_file):
  71. global points, timg
  72. #xscale, yscale = 0.5, 0.5 # 通过放大图像来使得点击位置更加精确
  73. xscale, yscale = 0.9, 0.9
  74. points = []
  75. oimg = cv2.imread(img_file)
  76. oshape = oimg.shape #图形规格
  77. timg = cv2.resize(oimg, (int(oshape[1] / xscale), int(oshape[0] / yscale))) # 放大图像
  78. print(timg.shape)
  79. cv2.imshow('origin', timg)
  80. cv2.setMouseCallback('origin', on_mouse)
  81. cv2.waitKey(0) # 点完4个角点之后随便按一个键盘按键结束操作
  82. cv2.destroyAllWindows()
  83. points = np.array(points, dtype=np.float32)
  84. points[:, 0] *= oshape[1] / int(oshape[1] / xscale) # 还原像素位置的大小
  85. points[:, 1] *= oshape[0] / int(oshape[0] / yscale)
  86. warped = four_point_transform(oimg, points)
  87. # cv2.imwrite('warped.png', warped ) # 保存图像
  88. cv2.imshow('origin', warped)
  89. cv2.waitKey(0)
  90. cv2.destroyAllWindows()
  91. if __name__ == '__main__':
  92. points = []
  93. rectification('images/test.png', points)

 矫正后的图片:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/153347?site
推荐阅读
相关标签
  

闽ICP备14008679号