当图像具有不同因素时确定图像相似性。图像分析

Determining Image similarity when images have varying factors. Image Analysis

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

场景:

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

一个用例场景可能是纸币。专家会select一张好的钞票图片上的一个区域是真钞,然后用户将需要检查的钞票图像提供给软件。所以照明和捕获设备可能会有所不同。
我不想让你们深入研究比较钞票的本质,这是另一个需要解决的问题,我已经解决了大部分问题。

我的问题:

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

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

我尝试了什么:

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

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

RGB 图像上的 SSIM。

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

使用索贝尔滤波器后的SSIM。

再次相似度低。 我使用了 Scikit in python and SSIM from OpenCV

中的 SSIM

特征匹配 Flann.

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

基本上我猜想我需要使用各种方法和算法来达到最好的结果。我的直觉告诉我,我需要将 RGB 比较结果与一种方法结合起来:

我是一个图像分析新手,我也试图找到一种方法来比较所提供图像的 sobel 乘积,使用 mean and std calculations from openCV, however I either did it wrong, or the results I got were useless anyway. I calculated the eucledian distance 在均值和标准差计算产生的向量之间,但是我可以不使用结果主要是因为我看不到它们在图像之间的关系。

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

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

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

我觉得你可以试试特征匹配,比如SURF算法,FLANNEL 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; }

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

#!/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 函数没有给我想要的结果。 所以我使用来自轮廓的信息创建了两个图像,然后我应用了中值模糊滤镜。

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