当图像具有变化因素时确定图像相似度。图像分析

时间:2018-12-11 01:01:15

标签: opencv image-processing similarity scikit-image

过去一周(或更多)的问候,我一直在努力解决问题。

场景:

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

一个用例场景可能是钞票。专家将在钞票的真实图片上选择一个真实的区域,然后用户将向软件提供需要检查的钞票图像。因此照明和捕获设备可能会有所不同。
我不想让你们去研究比较钞票的本质,这是另一个需要解决的怪兽,而我在很大程度上得到了解决。

我的问题:

最初,我将两张图片之一shrink缩小为较小的一张。 因此,现在我们要处理具有相同大小的图片。 (我实际上是缩小到感兴趣的区域而不是整个区域,但这没关系。)

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

我尝试过什么:

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

提供的问题是图像可能完全不同,但颜色可能相似。因此,我将在“完全”不同的钞票上获得很高的百分比。

在RGB图像上的

SSIM。

在所有渠道上的相似度会非常低。

使用sobel滤波器后的

SSIM。

相似度百分比较低。 我在python和Scikit中都使用了SSIM from OpenCV的SSIM

Flann 匹配的功能。

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

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

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

我是图像分析新手,我还尝试使用openCV的mean and std calculations比较提供的图像的sobel产品,但是我做错了,或者得到的结果是反正没用。我在平均值和标准差计算得出的向量之间计算了eucledian distance,但是我无法使用结果主要是因为我看不到它们在图像之间的关系。

我没有提供我以前使用的代码,因为我废弃了一些代码,所以过于草率,其次是因为我不是在寻找代码解决方案,而是在寻找学习材料的方法或方向。 (我已经读了很多论文)。 最终,我不是要检测相似的图像,而是给定两个图像,提取它们之间的相似性,尝试绕过照明或纸张变形等造成的细微差别。

最后我想说我通过两次提供相同的图像测试了所有方法,并且我将获得100%的相似性,所以我并没有完全搞定它。

在没有某种训练集的情况下,即使没有教我什么软件,我还能尝试什么呢? (再次我不知道那是否有意义:D)

2 个答案:

答案 0 :(得分:0)

我认为您可以尝试功能匹配,例如SURF alogrithm,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; }

答案 1 :(得分:0)

好好摸索一下,这就是我带来的:

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

当前,我正在对每个像素进行布尔检查。但是,我计划在将来进行更改,以使其更智能。可能与一些数组数学。 如果有人有任何建议,欢迎他们。