python提取图片中的多个二维码,返回坐标

 

import cv2
import numpy as np
from pyzbar.pyzbar import decode
import sys


def is_overlap(rect1, rect2):
    """
    判断两个矩形区域是否重叠
    :param rect1: 第一个矩形区域,格式为 (x1, y1, x2, y2)
    :param rect2: 第二个矩形区域,格式为 (x1, y1, x2, y2)
    :return: 如果重叠返回 True,否则返回 False
    """
    x1_1, y1_1, x2_1, y2_1 = rect1
    x1_2, y1_2, x2_2, y2_2 = rect2
    return not (x2_1 < x1_2 or x2_2 < x1_1 or y2_1 < y1_2 or y2_2 < y1_1)


def remove_overlaps(rectangles):
    """
    去除重叠的矩形区域
    :param rectangles: 矩形区域列表,每个元素格式为 (x1, y1, x2, y2)
    :return: 去除重叠后的矩形区域列表
    """
    non_overlapping = []
    for rect in rectangles:
        is_valid = True
        for existing_rect in non_overlapping:
            if is_overlap(rect, existing_rect):
                is_valid = False
                break
        if is_valid:
            non_overlapping.append(rect)
    return non_overlapping


def find_qr_codes(image_path):
    # 尝试使用 pyzbar 识别二维码
    image = cv2.imread(image_path)
    if image is None:
        print(f"无法打开或读取文件: {image_path},请检查文件路径和文件完整性。")
        return []
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    decoded_objects = decode(gray)
    qr_coordinates = []
    for obj in decoded_objects:
        if obj.type == 'QRCODE':
            points = obj.polygon
            if len(points) == 4:
                x_coords = [point.x for point in points]
                y_coords = [point.y for point in points]
                x_min = min(x_coords)
                x_max = max(x_coords)
                y_min = min(y_coords)
                y_max = max(y_coords)
                qr_coordinates.append((x_min, y_min, x_max, y_max))
                # 将识别到的区域设为白色(遮挡)
                gray[y_min:y_max, x_min:x_max] = 255

    templates = [
        '/www/pythoncmd/qrcode/template_dy.png',
        '/www/pythoncmd/qrcode/template_wx.png'
    ]
    for template_path in templates:
        template = cv2.imread(template_path, 0)
        if template is None:
            print(f"无法打开或读取模板文件: {template_path},请检查文件路径和文件完整性。")
            continue
        # 创建 SIFT 对象
        sift = cv2.SIFT_create()
        # 检测关键点和描述符
        kp1, des1 = sift.detectAndCompute(template, None)
        kp2, des2 = sift.detectAndCompute(gray, None)
        # 使用 FLANN 进行特征匹配
        FLANN_INDEX_KDTREE = 1
        index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
        search_params = dict(checks=50)
        flann = cv2.FlannBasedMatcher(index_params, search_params)
        matches = flann.knnMatch(des1, des2, k=2)
        # 筛选好的匹配点
        good_matches = []
        for m, n in matches:
            if m.distance < 0.7 * n.distance:
                good_matches.append(m)
        if len(good_matches) > 10:
            src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
            dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)
            M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
            if M is not None:  # 检查 M 是否有效
                h, w = template.shape
                pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)
                dst = cv2.perspectiveTransform(pts, M)
                x_coords = [point[0][0] for point in dst]
                y_coords = [point[0][1] for point in dst]
                x_min = int(min(x_coords))
                x_max = int(max(x_coords))
                y_min = int(min(y_coords))
                y_max = int(max(y_coords))

                # 获取图像的宽度和高度
                height, width = image.shape[:2]
                if (x_max < width and y_max < height and x_max - x_min > 100 and y_max - y_min > 100):
                    qr_coordinates.append((x_min, y_min, x_max, y_max))
                    gray[y_min:y_max, x_min:x_max] = 255
#             else:
#                 print("单应性矩阵 M 无效,跳过当前模板匹配")

    # 去除重叠区域
    qr_coordinates = remove_overlaps(qr_coordinates)
    return qr_coordinates


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("用法: python detect_qrcodes.py <图片路径>")
        print(len(sys.argv))
        sys.exit(1)
    image_path = sys.argv[1]
    coordinates = find_qr_codes(image_path)
    print(coordinates)

 

posted @ 2025-04-27 10:04  露娜喵喵  阅读(60)  评论(0)    收藏  举报