使用opencv-python的薄板样条插值(ThinPlateSpline)实现图像和坐标变换

使用opencv-python的薄板样条插值(tps)实现图像和坐标变换

自己用opencv-python做基于薄板样条图像配准时踩了不少坑。网上现有关于thinplatetransformer的内容太少,这里跟大家分享下错误经验。

opencv安装

需要注意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)

如果想自己下可以点击这里:
在这里插入图片描述
在这里插入图片描述

tps模块使用方法

类说明文档: 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 重要的事情说三遍,不然真的被坑惨了。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值