OpenCV调用warpPerspective报(-215)单应矩阵断言失败问题
问题背景
对两张尺寸为128×128的RGB肺部掩码图像执行图像配准操作,相同处理逻辑在其他普通图像上可正常运行,本次运行抛出异常。参考公开教程编写的registerImage配准函数、完整运行代码与报错信息如下:
import cv2 import numpy as np def registerImage(img1,img2): # 待对齐图像 img1_color = img1 # 参考图像 img2_color = img2 # 转灰度图 img1 = cv2.cvtColor(img1_color, cv2.COLOR_BGR2GRAY) img2 = cv2.cvtColor(img2_color, cv2.COLOR_BGR2GRAY) height, width = img2.shape # 初始化ORB检测器,最多提取5000个特征 orb_detector = cv2.ORB_create(5000) # 检测关键点与计算描述子 kp1, d1 = orb_detector.detectAndCompute(img1, None) kp2, d2 = orb_detector.detectAndCompute(img2, None) # 初始化汉明距离的暴力匹配器,开启交叉校验 matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True) # 匹配描述子 matches = matcher.match(d1, d2) # 按汉明距离排序匹配对 matches.sort(key = lambda x: x.distance) # 取前90%匹配质量较好的点对 matches = matches[:int(len(matches)*0.9)] no_of_matches = len(matches) # 存储匹配点坐标 p1 = np.zeros((no_of_matches, 2)) p2 = np.zeros((no_of_matches, 2)) for i in range(len(matches)): p1[i, :] = kp1[matches[i].queryIdx].pt p2[i, :] = kp2[matches[i].trainIdx].pt # 计算单应性矩阵 homography, mask = cv2.findHomography(p1, p2, cv2.RANSAC) # 用单应性矩阵做透视变换对齐图像 transformed_img = cv2.warpPerspective(img1_color, homography, (width, height)) # 拼接展示结果 img1_show = cv2.resize(img1_color,(320,320)) img2_show = cv2.resize(img2_color,(320,320)) img3_show = cv2.resize(transformed_img,(320,320)) img = np.concatenate((img1_show,img2_show,img3_show), axis=1) cv2_imshow(img) ref_path = path + "/mask_0.png" test_path = path + "/mask_8.png" from google.colab.patches import cv2_imshow ref_mask = cv2.imread(ref_path) cv2_imshow(ref_mask) test_mask = cv2.imread(test_path) cv2_imshow(test_mask) registerImage(ref_mask,test_mask)
报错信息:
error: OpenCV(4.1.2) /io/opencv/modules/imgproc/src/imgwarp.cpp:3167: error: (-215:Assertion failed) (M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 3 && M0.cols == 3 in function 'warpPerspective'
报错根因
这个断言错误的直接原因是传入cv2.warpPerspective的homography单应性矩阵是None,不符合函数要求的3×3浮点矩阵的入参规范。
单应性矩阵返回空的核心原因:
- 处理对象是肺部二值掩码图像,图像本身纹理极少,128×128的小尺寸下ORB检测器默认参数能提取到的有效特征点、匹配对数量不足,RANSAC算法无法求解出合法的单应性矩阵,就会直接返回
None。 - 代码没有做入参合法性校验,拿到空值直接传入透视变换函数就触发了报错。之前在普通自然图像上能正常运行,是因为自然图像纹理丰富,很容易提取到足够的有效特征匹配点,不会出现单应性矩阵为空的情况。
修复方法
- 调整ORB检测器参数,降低特征检测阈值,适配低纹理的小尺寸掩码图像
- 增加匹配点数量校验:单应性矩阵求解最少需要4对有效匹配点,数量不足时直接抛出提示,避免后续计算异常
- 对求解得到的单应性矩阵做非空校验,确认矩阵合法后再调用透视变换函数
修改后的核心代码片段:
def registerImage(img1,img2): img1_color = img1 img2_color = img2 img1 = cv2.cvtColor(img1_color, cv2.COLOR_BGR2GRAY) img2 = cv2.cvtColor(img2_color, cv2.COLOR_BGR2GRAY) height, width = img2.shape # 调低ORB检测阈值,适配低纹理小尺寸图像 orb_detector = cv2.ORB_create(5000, edgeThreshold=5, patchSize=15, fastThreshold=5) kp1, d1 = orb_detector.detectAndCompute(img1, None) kp2, d2 = orb_detector.detectAndCompute(img2, None) # 增加空描述子校验,避免特征点为0时匹配报错 if d1 is None or d2 is None or len(kp1) <4 or len(kp2)<4: print("有效特征点数量不足,无法完成配准") return matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True) matches = matcher.match(d1, d2) matches.sort(key = lambda x: x.distance) matches = matches[:int(len(matches)*0.9)] no_of_matches = len(matches) # 匹配点不足4对时无法求解单应性矩阵,直接返回 if no_of_matches <4: print("有效匹配点对不足4对,无法计算单应性矩阵") return p1 = np.zeros((no_of_matches, 2)) p2 = np.zeros((no_of_matches, 2)) for i in range(len(matches)): p1[i, :] = kp1[matches[i].queryIdx].pt p2[i, :] = kp2[matches[i].trainIdx].pt homography, mask = cv2.findHomography(p1, p2, cv2.RANSAC) # 校验单应性矩阵是否合法 if homography is None or homography.shape != (3,3): print("单应性矩阵求解失败") return transformed_img = cv2.warpPerspective(img1_color, homography, (width, height)) # 后续展示逻辑不变 img1_show = cv2.resize(img1_color,(320,320)) img2_show = cv2.resize(img2_color,(320,320)) img3_show = cv2.resize(transformed_img,(320,320)) img = np.concatenate((img1_show,img2_show,img3_show), axis=1) cv2_imshow(img)
补充说明:如果调整ORB参数后依然无法得到足够匹配点,说明基于特征点的配准方法不适合当前掩码场景,可以换用基于灰度互相关、掩码轮廓对齐的配准方案,效果会更稳定。
内容的提问来源于stack exchange,提问作者Nisarg Doshi
相关产品推荐
相关产品推荐

