刘虾 2025-08-06 10:30 采纳率: 49.4%
浏览 13
已结题

视觉检测中怎么将两张图片判断是同一张图片

使用python语言,视觉检测中怎么将两张图片判断是同一张图片,两张图片存在光照变化,位置变化(上下左右移动几十个像素),其实是同一张图片

  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2025-08-06 10:31
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    在视觉检测中,判断两张图片是否为同一张图片(即使存在光照变化、**位置变化(上下左右移动几十个像素)**等),可以采用以下几种方法。以下是详细的解决方案:


    一、使用图像相似度算法

    1. SSIM(结构相似性指数)

    • 原理:SSIM 是一种衡量两幅图像在亮度、对比度和结构上相似性的指标。
    • 优点:对光照变化和轻微位移有较好的鲁棒性。
    • 缺点:对于大范围的位移或旋转不敏感。
    from skimage.metrics import structural_similarity as ssim
    import cv2
    
    def compare_images_ssim(img1_path, img2_path):
        # 读取图像并转换为灰度图
        img1 = cv2.imread(img1_path, 0)
        img2 = cv2.imread(img2_path, 0)
    
        # 计算 SSIM
        score, _ = ssim(img1, img2, full=True)
        return score
    

    重点ssim 函数返回的是一个介于 -1 到 1 的值,越接近 1 表示越相似。


    二、使用特征点匹配(如 SIFT、SURF、ORB)

    2. SIFT / SURF / ORB 特征提取与匹配

    • 原理:通过提取图像中的关键点和描述符,然后进行匹配。
    • 优点:对光照变化、平移、旋转都有一定鲁棒性。
    • 缺点:计算量较大,但适用于大多数情况。
    import cv2
    
    def match_features(img1_path, img2_path):
        # 读取图像
        img1 = cv2.imread(img1_path)
        img2 = cv2.imread(img2_path)
    
        # 转换为灰度图
        gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
        gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    
        # 使用 ORB 特征提取器
        orb = cv2.ORB_create()
    
        # 找到关键点和描述符
        kp1, des1 = orb.detectAndCompute(gray1, None)
        kp2, des2 = orb.detectAndCompute(gray2, None)
    
        # 使用 BFMatcher 进行匹配
        bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
        matches = bf.match(des1, des2)
    
        # 按距离排序
        matches = sorted(matches, key=lambda x: x.distance)
    
        # 绘制匹配结果
        matched_img = cv2.drawMatches(img1, kp1, img2, kp2, matches[:50], None, flags=2)
        cv2.imshow("Matches", matched_img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
        # 返回匹配数量
        return len(matches)
    

    重点len(matches) 越多,说明图像越相似。


    三、使用深度学习模型(如 CNN 或 Siamese Network)

    3. 使用预训练的 CNN 提取特征

    • 原理:使用预训练的卷积神经网络(如 VGG、ResNet)提取图像特征,再比较特征向量之间的相似度。
    • 优点:对光照变化、位置偏移具有较强鲁棒性。
    • 缺点:需要一定的 GPU 算力支持。
    import torch
    import torchvision.models as models
    import torchvision.transforms as transforms
    from PIL import Image
    
    # 加载预训练的 ResNet18 模型
    model = models.resnet18(pretrained=True)
    model.eval()
    model = torch.nn.Sequential(*list(model.children())[:-1])  # 去掉最后的全连接层
    
    # 图像预处理
    transform = transforms.Compose([
        transforms.Resize((224, 224)),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
    ])
    
    def extract_features(image_path):
        image = Image.open(image_path)
        image = transform(image).unsqueeze(0)  # 添加 batch 维度
        with torch.no_grad():
            features = model(image)
        return features.squeeze().numpy()
    
    def compare_images_cnn(img1_path, img2_path):
        feat1 = extract_features(img1_path)
        feat2 = extract_features(img2_path)
    
        # 使用余弦相似度
        similarity = 1 - (feat1 @ feat2.T) / (np.linalg.norm(feat1) * np.linalg.norm(feat2))
        return similarity
    

    重点cosine similarity 越接近 1,表示两张图片越相似。


    四、结合上述方法(推荐方案)

    4. 综合方案:使用特征匹配 + 相似度评分

    def is_same_image(img1_path, img2_path, threshold=0.9):
        # 使用 SSIM
        ssim_score = compare_images_ssim(img1_path, img2_path)
        
        # 使用特征匹配
        match_count = match_features(img1_path, img2_path)
        
        # 使用 CNN 特征相似度
        cnn_score = compare_images_cnn(img1_path, img2_path)
    
        # 综合判断
        if ssim_score > threshold and match_count > 50 and cnn_score > 0.9:
            return True
        else:
            return False
    

    重点:设置合理的阈值(如 threshold=0.9)来判断是否为同一张图片。


    五、总结(有序列表)

    1. 使用 SSIM:评估图像结构相似性,适合光照变化和轻微位移。
    2. 使用特征点匹配(如 ORB):通过关键点匹配判断图像是否为同一张。
    3. 使用深度学习模型(CNN):提取高维特征,增强鲁棒性。
    4. 综合方案:结合多种方法,提高判断准确率。
    5. 设置合理阈值:根据实际应用场景调整判断标准。

    如果你有具体图片或场景,我可以进一步优化代码或建议更合适的算法。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 8月17日
  • 已采纳回答 8月9日
  • 创建了问题 8月6日