赞
踩
自己用opencv-python做基于薄板样条图像配准时踩了不少坑。网上现有关于thinplatetransformer的内容太少,这里跟大家分享下错误经验。
需要注意opencv-python、opencv-python-contrib、numpy版本一定要匹配,不然会出现查看不了注释的情况,详见: Pycharm配置opencv与numpy
我是用的版本是如下:
python-3.8.0
numpy-1.22.4+kml
opencv&opencv-contrib-4.5.5 (.62)
类说明文档: ThinPlateSplineShapeTransformer OpenCV Documentation
我自己写的例程如下:
- def TPSTransformWithPoints(pts1, pts2, img=None, ptm=None):
- """
- Editor: 五月的白杨 CSDN
- Perform thin plate spline transform
- inputs:
- pts1---marker points on moving image, with size (m,2), ndarray, dtpye numeric, float or int
- pts2---marker points on fixed image, with size (m,2), ndarray, dtpye numeric, float or int
- img ---moving image, an cv2 image
- ptm ---other points needed to be transformed on moving image,
- outputs:
- result registrated moving image
- p_iter registrated points of moving image
- """
- m = pts1.shape[0]
- # Reshape pts1 & pts2
- pts1 = pts1.reshape(1, -1, 2)
- pts2 = pts2.reshape(1, -1, 2)
- matches = []
- # Create Matches
- for i in range(m):
- matches.append(cv2.DMatch(i, i, 0))
- # Estimate Transformation
- tps_img = cv2.createThinPlateSplineShapeTransformer()
- tps_pts = cv2.createThinPlateSplineShapeTransformer()
- tps_img.estimateTransformation(pts2, pts1, matches)
- tps_pts.estimateTransformation(pts1, pts2, matches)
- # Outputs
-
- p = ptm.reshape(1, -1, 2)
- if ptm is not None:
- p_iter_tps = tps_pts.applyTransformation(p)
- else:
- p_iter_tps = None
- if img is not None:
- result_tps = tps_img.warpImage(img)
- else:
- result_tps = None
- return result_tps, p_iter_tps
注意事项:
1. 创建对象一般用 cv2.createThinPlateSplineShapeTransformer(),用到的函数为estimateTransformation(),但我这里对浮动图像(img)做变换和对浮动图像上的点(pts)做变换,使用了两个transformer对象: tps_img 和 tps_pts 分别算了一次。
原因是opencv封装的ThinPlateSpline模块从2017年就有一个没修的bug,estimatetransformation的说明文档的输入顺序如下:source_points,target_points,matches. 但开发者搞反了输入顺序,如果对图像变换,source 和 target 点应该互换,但对浮动图像选的点做变换又是正确的(崩溃)参考这个opencv的issue: 点此查看 https://github.com/opencv/opencv/issues/7084
简而言之
- # 对图像变换用这个
- tps_img = cv2.createThinPlateSplineShapeTransformer()
- tps_img.estimateTransformation(target_points, source_points, matches)
- pts = tps_img.warpImage(img)
-
- # 对点变换用这个
- tps_pts = cv2.createThinPlateSplineShapeTransformer()
- tps_pts.estimateTransformation(source_points, target_points, matches)
- pts = tps_pts.applyTransformation(p)
-
- """两个target和source的顺序是相反的"""
2. 如果输入的pts1 pts2为(m,2)的ndarray,下面两句是必要的,因为opencv的ThinPlateSpline模块estimateTransformation只接受输入为(1,m,2)的tuple貌似,不然就会报错
- pts1 = pts1.reshape(1, -1, 2)
- pts2 = pts2.reshape(1, -1, 2)
3. 最后补充一个注意事项,输入的坐标点必须转为np.float32 np.float32 np.float32 重要的事情说三遍,不然真的被坑惨了。。。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。