当图像具有不同因素时确定图像相似性。图像分析
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。
- 根据形状匹配或类似的东西比较结果。
我是一个图像分析新手,我也试图找到一种方法来比较所提供图像的 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 函数没有给我想要的结果。
所以我使用来自轮廓的信息创建了两个图像,然后我应用了中值模糊滤镜。
目前,我正在对像素进行简单的布尔检查。然而,我计划在未来改变这一点,让它变得更聪明。可能有一些数组数学。
如果有人有任何建议,欢迎提出。
过去一周(或更长时间)的问候我一直在努力解决一个问题。
场景:
我正在开发一个应用程序,它允许专家使用提供的某物图像作为基础来创建食谱。该食谱由感兴趣的领域组成。该程序的目的是允许非专家使用它,提供与原始图像相似的图像,并且该软件会交叉检查从配方图像到提供图像的这些不同兴趣区域。
一个用例场景可能是纸币。专家会select一张好的钞票图片上的一个区域是真钞,然后用户将需要检查的钞票图像提供给软件。所以照明和捕获设备可能会有所不同。
我不想让你们深入研究比较钞票的本质,这是另一个需要解决的问题,我已经解决了大部分问题。
我的问题:
最初我
我尝试并使用了不同的方法来比较这些部分,但由于图像的性质,每个方法都有其局限性。照明可能会有所不同,前提是图像可能有某种污染等。
我尝试了什么:
使用RGB差异的简单图像相似度比较。
问题是图像可能完全不同,但颜色可能相似。所以我会在“完全”不同的纸币上获得高百分比。
RGB 图像上的 SSIM。
所有渠道的相似度百分比都非常低。
使用索贝尔滤波器后的SSIM。
再次相似度低。 我使用了 Scikit in python and SSIM from OpenCV
中的 SSIM特征匹配 Flann.
找不到使用检测到的匹配项来提取相似性的好方法。
基本上我猜想我需要使用各种方法和算法来达到最好的结果。我的直觉告诉我,我需要将 RGB 比较结果与一种方法结合起来:
- 执行某种形式的边缘检测,如 sobel。
- 根据形状匹配或类似的东西比较结果。
我是一个图像分析新手,我也试图找到一种方法来比较所提供图像的 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 函数没有给我想要的结果。 所以我使用来自轮廓的信息创建了两个图像,然后我应用了中值模糊滤镜。
目前,我正在对像素进行简单的布尔检查。然而,我计划在未来改变这一点,让它变得更聪明。可能有一些数组数学。 如果有人有任何建议,欢迎提出。