【问题标题】:Determining Image similarity when images have varying factors. Image Analysis当图像具有不同的因素时确定图像相似性。图像分析
【发布时间】:2019-05-11 23:00:25
【问题描述】:

过去一周(或更长时间)的问候我一直在努力解决一个问题。

场景:

我正在开发一个应用程序,它允许专家使用提供的某物图像作为基础创建食谱。配方由感兴趣的领域组成。该程序的目的是允许非专家使用它,提供与原始图像相似的图像,并且软件会交叉检查这些不同的兴趣区域,从配方图像到提供的图像。

一个用例场景可能是纸币。专家会在一张好的钞票图片上选择一个真正的区域,然后用户会向软件提供需要检查的钞票图像。因此,照明以及捕获设备可能会有所不同。
我不想让你们深入研究比较钞票的本质,那是另一个需要解决的问题,我大部分时间都涵盖了它。

我的问题:

最初我将两张图片中的一张shrink 调整为较小的一张。 所以现在我们正在处理具有相同大小的图片。 (我实际上是对感兴趣的区域而不是整个图片进行缩小,但这不重要。)

我尝试并使用了不同的方法来比较这些部分,但由于图像的性质,每个部分都有其局限性。照明可能会有所不同,前提是图像可能存在某种污染等。

我尝试了什么:

使用RGB差异的简单图像相似度比较。

问题是图片可能完全不同,但颜色可能相似。所以我会在“完全”不同的钞票上获得很高的百分比。

RGB 图像上的 SSIM。

在所有渠道上的相似度百分比非常低。

使用 sobel 过滤器后的 SSIM。

再次低百分比的相似性。 我在 python 中使用了来自ScikitSSIM from OpenCV 的 SSIM

特征匹配Flann

找不到使用检测到的匹配项来提取相似性的好方法。

基本上我猜我需要使用各种方法和算法来达到最佳效果。我的直觉告诉我,我需要将 RGB 比较结果与以下方法相结合:

  • 执行某种形式的边缘检测,例如 sobel。
  • 根据形状匹配或类似的东西比较结果。

我是一个图像分析新手,我也试图找到一种方法来比较所提供图像的索贝尔产品,使用来自openCV的mean and std calculations,但是我要么做错了,要么我得到的结果无论如何都没用.我计算了均值和标准差计算得出的向量之间的eucledian distance,但我无法使用这些结果,主要是因为我看不到它们在图像之间的关系。

我没有提供我使用的代码,首先是因为我废弃了其中的一些代码,其次是因为我不是在寻找代码解决方案,而是寻找方法或学习材料的方向。 (我已经阅读了大量的论文)。 最后,我不是试图检测相似的图像,而是给定两张图像,提取它们之间的相似性,试图绕过由照明或纸张失真等造成的微小差异。

最后我想说的是,我通过提供相同的图像两次测试了所有方法,我会得到 100% 的相似度,所以我并没有完全搞砸。

如果没有某种训练集来教软件什么是可接受的图像变体,我正在尝试的事情是否可行? (我也不知道这是否有意义:D)

【问题讨论】:

    标签: opencv image-processing similarity scikit-image


    【解决方案1】:

    我觉得你可以试试 Feature Matching,比如 SURF 算法、FLANN https://docs.opencv.org/3.3.0/dc/dc3/tutorial_py_matcher.html

    http://www.coldvision.io/2016/06/27/object-detection-surf-knn-flann-opencv-3-x-cuda/

    使用 SURF 进行特征检测的示例:https://docs.opencv.org/3.0-beta/doc/tutorials/features2d/feature_detection/feature_detection.html

    #include <stdio.h>
    #include <iostream>
    #include "opencv2/core.hpp"
    #include "opencv2/features2d.hpp"
    #include "opencv2/xfeatures2d.hpp"
    #include "opencv2/highgui.hpp"
    
    using namespace cv;
    using namespace cv::xfeatures2d;
    
    void readme();
    
    /** @function main */
    int main( int argc, char** argv )
    {
      if( argc != 3 )
      { readme(); return -1; }
    
      Mat img_1 = imread( argv[1], IMREAD_GRAYSCALE );
      Mat img_2 = imread( argv[2], IMREAD_GRAYSCALE );
    
      if( !img_1.data || !img_2.data )
      { std::cout<< " --(!) Error reading images " << std::endl; return -1; }
    
      //-- Step 1: Detect the keypoints using SURF Detector
      int minHessian = 400;
    
      Ptr<SURF> detector = SURF::create( minHessian );
    
      std::vector<KeyPoint> keypoints_1, keypoints_2;
    
      detector->detect( img_1, keypoints_1 );
      detector->detect( img_2, keypoints_2 );
    
      //-- Draw keypoints
      Mat img_keypoints_1; Mat img_keypoints_2;
    
      drawKeypoints( img_1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
      drawKeypoints( img_2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
    
      //-- Show detected (drawn) keypoints
      imshow("Keypoints 1", img_keypoints_1 );
      imshow("Keypoints 2", img_keypoints_2 );
    
      waitKey(0);
    
      return 0;
      }
    
      /** @function readme */
      void readme()
      { std::cout << " Usage: ./SURF_detector <img1> <img2>" << std::endl; }
    

    【讨论】:

    • 问候并感谢您的遮阳篷,正如我在问题中所说,我已经尝试过使用 FLANN,但是我无法从中提取相似性百分比。如果您对此有任何想法,那将有所帮助。
    【解决方案2】:

    好吧,经过一番挖掘,这就是我带来的:

    #!/usr/bin/env
    import numpy as np
    import cv2
    import sys
    import matplotlib.image as mpimg
    from skimage import io
    from skimage import measure
    import time
    
    s = 0
    imgA = cv2.imread(sys.argv[1])
    imgB = cv2.imread(sys.argv[2])
    #imgA = cv2.imread('imageA.bmp')
    #imgB = cv2.imread('imageB.bmp')
    
    imgA = cv2.cvtColor(imgA, cv2.COLOR_BGR2GRAY)
    imgB = cv2.cvtColor(imgB, cv2.COLOR_BGR2GRAY)
    
    ret,imgA = cv2.threshold(imgA,127,255,0)
    ret,imgB = cv2.threshold(imgB,127,255,0)
    
    imgAContours, contoursA, hierarchyA = cv2.findContours(imgA, cv2.RETR_TREE , cv2.CHAIN_APPROX_NONE)
    imgBContours, contoursB, hierarchyB = cv2.findContours(imgB, cv2.RETR_TREE , cv2.CHAIN_APPROX_NONE)
    
    imgAContours = cv2.drawContours(imgAContours,contoursA,-1,(0,0,0),1)
    imgBContours = cv2.drawContours(imgBContours,contoursB,-1,(0,0,0),1)
    imgAContours = cv2.medianBlur(imgAContours,5)
    imgBContours = cv2.medianBlur(imgBContours,5)
    
    
    
    #s = 100 * 1/(1+cv2.matchShapes(imgAContours,imgBContours,cv2.CONTOURS_MATCH_I2,0.0))
    #s = measure.compare_ssim(imgAContours,imgBContours)
    #equality = np.equal(imgAContours,imgBContours)
    total = 0.0
    sum = 0.0
    
    for x in range(len(imgAContours)):
        for y in range(len(imgAContours[x])):
            total +=1
            t = imgAContours[x,y] == imgBContours[x,y]
            if t:
                sum+=1
    
    s = (sum/total) * 100
    
    print(s)
    

    基本上,我尽可能简单地对这两个图像进行预处理,然后找到轮廓。现在 openCV 的 matchShapes 函数没有给我想要的结果。 所以我使用来自轮廓的信息创建了两个图像,然后我应用了中值模糊过滤器。

    目前,我正在对像素进行简单的布尔检查。但是我计划在未来改变这一点,让它更聪明。可能有一些数组数学。 如果有人有任何建议,欢迎提出。

    【讨论】:

      猜你喜欢
      • 2019-03-15
      • 2021-04-12
      • 1970-01-01
      • 2017-12-14
      • 1970-01-01
      • 2021-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多