def 图片查找_特征匹配_全部(big_img, small_img, threshold=0.7, min_match_count=4, maxcnt=0):
    '''
    使用sift算法进行多个相同元素的查找
    Args:
        big_img (numpy.ndarray): 大图
        small_img (numpy.ndarray): 需要查找的图片
        threshold (float): 阈值,当相识度小于该阈值的时候,就忽略掉
        min_match_count (int): 最小匹配数量
        maxcnt (int): 限制匹配的数量

    Returns:
        list: 包含匹配结果的列表,每个元素为字典,包含中心点坐标、矩形框以及置信度
        例如:
        [{'result': (100, 200), 'rectangle': [(10, 10), (10, 210), (210, 210), (210, 10)], 'confidence': 0.8}]
    '''
    sift = cv2.SIFT_create(nfeatures=0, nOctaveLayers=10)
    flann = cv2.FlannBasedMatcher({'algorithm': 1, 'trees': 5}, dict(checks=50))
    g1 = cv2.cvtColor(small_img, cv2.COLOR_BGR2GRAY)
    g2 = cv2.cvtColor(big_img, cv2.COLOR_BGR2GRAY)
    kp_sch, des_sch = sift.detectAndCompute(g1, None)
    if len(kp_sch) < min_match_count:
        return None
    kp_src, des_src = sift.detectAndCompute(g2, None)
    if len(kp_src) < min_match_count:
        return None

    result = []
    while True:
        # 匹配两个图片中的特征点,k=2表示每个特征点取2个最匹配的点
        matches = flann.knnMatch(des_sch, des_src, k=2)
        good = []
        for m, n in matches:
            # 剔除掉跟第二匹配太接近的特征点
            if m.distance < threshold * n.distance:
                good.append(m)

        if len(good) < min_match_count:
            break

        sch_pts = np.float32([kp_sch[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
        img_pts = np.float32([kp_src[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)

        # M是转化矩阵
        M, mask = cv2.findHomography(sch_pts, img_pts, cv2.RANSAC, 5.0)
        matches_mask = mask.ravel().tolist()

        # 计算四个角矩阵变换后的坐标,也就是在大图中的坐标
        h, w = small_img.shape[:2]
        pts = np.float32([[0, 0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
        dst = cv2.perspectiveTransform(pts, M)

        # trans numpy arrary to python list
        # [(a, b), (a1, b1), ...] 
        pypts = []
        for npt in dst.astype(int).tolist():
            pypts.append(tuple(npt[0]))

        lt, br = pypts[0], pypts[2]
        middle_point = (lt[0] + br[0]) / 2, (lt[1] + br[1]) / 2  # 计算中心点

        result.append(dict(
            result=middle_point,
            rectangle=pypts,
            confidence=min(1.0 * matches_mask.count(1) / 10, 1.0)  # min(1.0 * matches_mask.count(1) / 10, 1.0)
        ))

        if maxcnt and len(result) >= maxcnt:
            break

        # 从特征点中删掉那些已经匹配过的, 用于寻找多个目标
        qindexes, tindexes = [], []
        for m in good:
            # 将已经找到的先存起来 后面方便删除
            qindexes.append(m.queryIdx)  # need to remove from kp_sch
            tindexes.append(m.trainIdx)  # need to remove from kp_img

        def filter_index(tt, arr):
            r = np.ndarray(0, np.float32)
            for i, item in enumerate(arr):
                if tt == 1:
                    if i not in qindexes:
                        r = np.append(r, item)
                else:
                    if i not in tindexes:
                        r = np.append(r, item)

            return r

        # 更新数组
        kp_src = filter_index(1, kp_src)
        des_src = filter_index(0, des_src)

    return result


if __name__ == '__main__':
    big_img = cv2.imdecode(np.fromfile(file=r'C:\Users\Administrator\Desktop\result_11.jpg', dtype=np.uint8), cv2.IMREAD_COLOR)  # 加载大图

    small_img = cv2.imdecode(np.fromfile(file=r'C:\Users\Administrator\Desktop\zhuye1.bmp', dtype=np.uint8), cv2.IMREAD_COLOR)

    ret = 图片查找_特征匹配_全部(big_img, small_img)
    print(ret)

关于“cv2.error: OpenCV(4.5.2) c:\users\runneradmin\appdata\local\temp\pip-req-build-vi271kac\opencv\modules\flann\include\opencv2\flann\nn_index.h:71: error: (-215:Assertion failed) queries.cols == veclen() in function 'cvflann::NNIndex<struct cvflann::L2 >::knnSearch'”的解决方法:

该错误表示 des_schdes_src 的维度不匹配。可能的原因是:

  1. 图像大小不一致: small_imgbig_img 的大小可能不一致,导致特征描述符的维度不同。请确保两张图片的大小一致。
  2. SIFT 参数: sift.detectAndCompute() 的参数可能导致特征描述符的维度不同。请检查参数,确保参数设置一致。
  3. 特征点数量: 如果其中一张图片的特征点数量过少,会导致维度不匹配。可以调整 sift.detectAndCompute()nfeatures 参数,或增加 min_match_count 的值。

建议

  1. 调试: 使用 print(des_sch.shape, des_src.shape) 打印 des_schdes_src 的维度,检查是否一致。
  2. 更换算法: 尝试使用其他的特征匹配算法,比如基于 ORB 特征的匹配算法,来替代 FLANN 进行特征匹配。
  3. 更新 OpenCV: 尝试更新 OpenCV 库,可能可以解决问题。

如果以上方法都无法解决问题,请提供更多错误信息和代码片段,以便更准确地定位问题。

注意: 代码中使用了 cv2.imdecode(np.fromfile(...), cv2.IMREAD_COLOR) 加载图片,这是一种比较高效的读取图片的方式,建议使用。

Python OpenCV SIFT 特征匹配查找多个相同元素

原文地址: https://www.cveoy.top/t/topic/hLNz 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录