मैं कैसे पता लगा सकता हूं कि दो छवियां "समान" हैं, भले ही किसी में थोड़ी अलग फसल / अनुपात हो?


11

मेरी दो अलग-अलग छवियां हैं:

100px में यहां छवि विवरण दर्ज करेंया 400px के साथयहां छवि विवरण दर्ज करें

तथा

100px चौड़ाई यहां छवि विवरण दर्ज करेंया 400px मेंयहां छवि विवरण दर्ज करें

जैसा कि आप देख सकते हैं कि दोनों स्पष्ट रूप से मानवीय दृष्टिकोण से "समान" हैं। अब मैं प्रोग्रामिक रूप से पता लगाना चाहता हूं कि वे समान हैं। मैं रूबी रत्न के माध्यम से इमेज मैजिक का उपयोग कर रहा हूं, rmagickजैसे कि:

img1 = Magick::Image.from_blob(File.read("image_1.jpeg")).first
img2 = Magick::Image.from_blob(File.read("image_2.jpeg")).first

if img1.difference(img2).first < 4000.0 # I have found this to be a good threshold, but does not work for cropped images
  puts "they are the same!!!"
end

हालांकि यह उन छवियों के लिए अच्छी तरह से काम करता है जिनके पास समान अनुपात / फसल है, यह आदर्श नहीं है जब उनके पास थोड़ी अलग फसल होती है और एक ही चौड़ाई में आकार दिया गया है।

वहाँ विभिन्न फसल के साथ छवियों के लिए यह करने के लिए एक रास्ता है? मुझे एक ऐसे समाधान में दिलचस्पी है जहां मैं कुछ कह सकता हूं: एक छवि दूसरे के अंदर समाहित है और इसमें लगभग 90% उदाहरण शामिल हैं।

पुनश्च। मैं उच्च रिज़ॉल्यूशन में चित्र प्राप्त कर सकता हूं यदि वह मदद करता है (जैसे कि डबल)


2
RMagick के बारे में निश्चित नहीं है, लेकिन ImageMagick के compareकमांड लाइन टूल में एक -subimage-searchस्विच है।
स्टीफन

यह दिलचस्प है, उस लुक को एक कमांड कैसे करेगा?
नील्स क्रिस्टियन

2
कभी खुद इसका इस्तेमाल नहीं किया, शायद इससे मदद मिलती है: stackoverflow.com/q/29062811/477037
स्टीफन

धन्यवाद, यह जानकारी का एक बड़ा टुकड़ा है। मैं यह पता नहीं लगा सकता कि रूबी से यह कैसे
करवाया जाए

1
क्या छवियां कम गुणवत्ता वाली हैं? यदि नहीं, तो कृपया अधिक गुणवत्ता के साथ छवियों का बड़ा संस्करण साझा करें।
MH304

जवाबों:


6

आप सुविधा मिलान पर एक नज़र रखना चाहते हैं। विचार दो छवियों में सुविधाओं को खोजने और उनसे मेल खाने का है। इस पद्धति का उपयोग आमतौर पर किसी अन्य छवि में टेम्पलेट (लोगो कहने) के लिए किया जाता है। एक विशेषता, संक्षेप में, उन चीजों के रूप में वर्णित किया जा सकता है जो मनुष्य को एक छवि में दिलचस्प मिलेंगे, जैसे कि कोने या खुली जगह। कई तरह की फीचर डिटेक्शन तकनीकें हैं, हालांकि मेरी सिफारिश है कि एक स्केल-इनवायरमेंट फीचर ट्रांसफॉर्मेशन (SIFT) का इस्तेमाल फीचर डिटेक्शन एल्गोरिदम के रूप में किया जाए। SIFT छवि अनुवाद, स्केलिंग, रोटेशन, रोशनी परिवर्तन के लिए आंशिक रूप से अपरिवर्तनीय, और स्थानीय ज्यामितीय विरूपण के लिए मजबूत है। यह आपके विनिर्देश से मेल खाता है जहां छवियों में थोड़ा भिन्न अनुपात हो सकता है।

आपकी दो प्रदान की गई छवियों को देखते हुए, यहां FLANN सुविधा मिलानकर्ता का उपयोग करके सुविधाओं से मेल खाने का प्रयास किया गया है । यह निर्धारित करने के लिए कि दो छवियां समान हैं, हम इसे कुछ पूर्व निर्धारित दहलीज से आधार बना सकते हैं जो डेविड जी लोव द्वारा स्केल-इनवेरिएंट कीप्वाइंट्स से डिस्टिंक्टिव इमेज फीचर्स में वर्णित अनुपात परीक्षण पास करने वाले मैचों की संख्या को ट्रैक करता है । परीक्षण की एक सरल व्याख्या यह है कि यदि परीक्षण अस्पष्ट हैं और उन्हें हटा दिया जाना चाहिए, तो अनुपात परीक्षण जांच करता है, आप इसे एक आउटस्टैंडिंग हटाने की तकनीक के रूप में मान सकते हैं। हम यह निर्धारित करने के लिए कि इस परीक्षण को पास कर सकते हैं कि दोनों चित्र समान हैं या नहीं। यहाँ सुविधा मिलान परिणाम हैं:

Matches: 42

डॉट्स का पता लगाए गए सभी मैचों का प्रतिनिधित्व करते हैं जबकि हरी रेखा "अच्छे मैचों" का प्रतिनिधित्व करते हैं जो अनुपात परीक्षण पास करते हैं। यदि आप अनुपात परीक्षण का उपयोग नहीं करते हैं, तो सभी बिंदु खींचे जाएंगे। इस तरह, आप इस फ़िल्टर का उपयोग केवल सर्वश्रेष्ठ मिलान सुविधाओं को रखने के लिए एक सीमा के रूप में कर सकते हैं।


मैंने इसे पायथन में लागू किया, मैं रेल से बहुत परिचित नहीं हूं। उम्मीद है कि इससे मदद करेगी, सुसंयोग!

कोड

import numpy as np
import cv2

# Load images
image1 = cv2.imread('1.jpg', 0)
image2 = cv2.imread('2.jpg', 0)

# Create the sift object
sift = cv2.xfeatures2d.SIFT_create(700)

# Find keypoints and descriptors directly
kp1, des1 = sift.detectAndCompute(image2, None)
kp2, des2 = sift.detectAndCompute(image1, None)

# FLANN parameters
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)   # or pass empty dictionary
flann = cv2.FlannBasedMatcher(index_params,search_params)
matches = flann.knnMatch(des1,des2,k=2)

# Need to draw only good matches, so create a mask
matchesMask = [[0,0] for i in range(len(matches))]

count = 0
# Ratio test as per Lowe's paper (0.7)
# Modify to change threshold 
for i,(m,n) in enumerate(matches):
    if m.distance < 0.15*n.distance:
        count += 1
        matchesMask[i]=[1,0]

# Draw lines
draw_params = dict(matchColor = (0,255,0),
                   # singlePointColor = (255,0,0),
                   matchesMask = matchesMask,
                   flags = 0)

# Display the matches
result = cv2.drawMatchesKnn(image2,kp1,image1,kp2,matches,None,**draw_params)
print('Matches:', count)
cv2.imshow('result', result)
cv2.waitKey()

2
सुपर दिलचस्प दृष्टिकोण, मैं इसे एक स्पिन दूंगा और वापस आऊंगा ...
नील्स क्रिस्टियन

पुनश्च। मैंने छवियों को बड़े पैमाने पर अपडेट किया
नील्स क्रिस्टियन

1
@nathancy ऐसा है कि आपके उदाहरण पर, हरे रंग के बिंदु मेल खाते हैं, लेकिन नीले रंग के नहीं हैं? लगता है कि बहुत सारे बेजोड़ डॉट्स हैं?
ड्रेको एटर

2
@DracoAter अच्छा सवाल है, नीले डॉट्स सभी मैचों का प्रतिनिधित्व करते हैं, जबकि हम केवल "अच्छे मैच" आकर्षित करते हैं जो हरे रंग में अनुपात परीक्षण पास करते हैं। यदि आप अनुपात परीक्षण का उपयोग नहीं करते हैं, तो सभी बिंदुओं को खींचा जाएगा, लेकिन हम "बेहतर" मैचों को खींचने के लिए अनुपात परीक्षण का उपयोग करके फ़िल्टर करते हैं। इस तरह से, ओपी इस परीक्षण का उपयोग एक सीमा के रूप में कर सकता है कि केवल सबसे अच्छी मिलान वाली विशेषताओं को रखा जाए। इसलिए सभी नीले डॉट्स वे विशेषताएं हैं जिन्हें SIFT ने पाया है लेकिन हम अच्छे लोगों को रखने के लिए फ़िल्टर करते हैं जो हरे रंग में खींचे जाते हैं
नथनसी

धन्यवाद। प्रतियोगिता कठिन थी, जवाब में कई महान लोग :-)
नील्स क्रिस्टियन

4

क्योंकि ImageMagick बहुत पुराना, उन्नत और कई विशेषताओं वाला उपकरण है, इसलिए ऐसा इंटरफ़ेस बनाना मुश्किल होगा जो अधिकांश विशेषताओं को कवर करता हो। यह जितना महान है, राग्मिक सभी विशेषताओं को कवर करने के लिए (और न ही कई प्रयास अजगर ने किया है) करीब नहीं आते हैं।

मैं कई उपयोग के मामलों की कल्पना करता हूं, यह सिर्फ एक कमांड लाइन विधि को निष्पादित करने और उस से पढ़ने के लिए सुरक्षित-पर्याप्त और बहुत आसान होगा। रूबी में जो इस तरह दिखेगा;

require 'open3'

def check_subimage(large, small)
    stdin, stdout, stderr, wait_thr = Open3.popen3("magick compare -subimage-search -metric RMSE #{large} #{small} temp.jpg")
    result = stderr.gets
    stderr.close
    stdout.close
    return result.split[1][1..-2].to_f < 0.2
end

if check_subimage('a.jpg', 'b.jpg')
    puts "b is a crop of a"
else
    puts "b is not a crop of a"
end

मैं महत्वपूर्ण चीजें कवर करूंगा और फिर अतिरिक्त नोटों के बारे में बात करूंगा।

यदि दूसरी छवि ( small) पहले का एक उप-भाग है (तो ) की जांच करने के लिए कमांड मैजिक तुलना का उपयोग करता है large। यह फ़ंक्शन यह नहीं जांचता है कि छोटा सख्ती से बड़े (ऊंचाई और चौड़ाई दोनों) से छोटा है। समानता के लिए मैंने जो संख्या डाली है वह 0.2 (20% त्रुटि) है, और आपके द्वारा प्रदान की गई छवियों का मूल्य लगभग 0.15 है। आप इसे ठीक करना चाह सकते हैं! मुझे लगता है कि एक सख्त उपसमुच्चय वाले चित्र 0.01 से कम मिलते हैं।

  • यदि आप उन मामलों में कम त्रुटि (छोटी संख्या) चाहते हैं, जहां आपके पास 90% ओवरलैप है, लेकिन दूसरी छवि में कुछ अतिरिक्त सामान हैं, जो पहले नहीं है, तो आप इसे एक बार चला सकते हैं, फिर पहली बड़ी छवि को उस स्थान पर क्रॉप करें जहां सबमेज समाहित है , तो इसे फिर से "छोटी" एक और मूल "छोटी" छवि के रूप में बड़े के रूप में फसली छवि के साथ फिर से चलाएं।
  • यदि आप वास्तव में रूबी में एक अच्छी वस्तु उन्मुख इंटरफ़ेस चाहते थे, तो rmagick मैजिककोर एपीआई का उपयोग करता है। यह (डॉक्स से लिंक) कमांड संभवतः वह है जिसे आप इसे लागू करने के लिए उपयोग करना चाहते हैं, और आप अपने आप को सीईएक्स को rmagick या पैकेज करने के लिए एक पीआर खोल सकते हैं।
  • ओपन 3 के उपयोग से एक धागा शुरू होगा ( डॉक्स देखें )। बंद करना stderrऔर stdout"आवश्यक" नहीं है, लेकिन आपको माना जाता है।
  • "Arp" छवि जो कि तीसरी arg है, एक विश्लेषण पर आउटपुट के लिए एक फ़ाइल निर्दिष्ट करती है। एक त्वरित नज़र के साथ, मुझे इसकी आवश्यकता नहीं होने का एक तरीका नहीं मिला, लेकिन यह बस स्वचालित रूप से ओवरराइट करता है और डिबगिंग के लिए बचाने के लिए अच्छा हो सकता है। आपके उदाहरण के लिए, यह इस तरह दिखेगा;

यहां छवि विवरण दर्ज करें

  • पूर्ण आउटपुट 10092.6 (0.154003) @ 0,31 के प्रारूप में है। पहली संख्या 655535 में से rmse मान है, दूसरा (जो मैं उपयोग करता हूं) सामान्यीकृत प्रतिशत है। अंतिम दो संख्याएं मूल छवि के स्थान का प्रतिनिधित्व करती हैं, जहां से छोटी छवि शुरू होती है।
  • के बाद से वहाँ कैसे "समान" चित्र हैं के लिए सच का एक उद्देश्य स्रोत नहीं है, मैं RMSE उठाया (अधिक मीट्रिक विकल्पों को देखने के लिए यहाँ )। यह मूल्यों के बीच मतभेदों का एक काफी सामान्य उपाय है। एक एब्सोल्यूट एरर काउंट (AE) एक अच्छे विचार की तरह लग सकता है, हालाँकि ऐसा लगता है कि कुछ क्रॉपिंग सॉफ्टवेयर पिक्सल को पूरी तरह से संरक्षित नहीं करते हैं, इसलिए आपको फ़ज़ी को समायोजित करना पड़ सकता है और यह एक सामान्यीकृत मूल्य नहीं है, इसलिए तब आपको त्रुटि गणना की तुलना करनी होगी छवि और whatnot के आकार के साथ।

1
कुछ वास्तव में महान जानकारी वहाँ कैरोल। साभार
नील्स क्रिस्टियन

यह जानने के लिए उत्सुक हैं कि यह आपके अन्य मामलों के लिए कैसे काम करता है!
कैरोल चेन

1
सुपर शानदार जवाब के लिए धन्यवाद। अगर मैं कर सकता था, तो मैंने आपको इसके लिए 100p इनाम भी दिया था :-)
नील्स क्रिस्टियन

3

दोनों छवियों का हिस्टोग्राम प्राप्त करें और उनकी तुलना करें। यह फसल और ज़ूम के लिए बहुत अच्छा काम करेगा जब तक कि इनकी वजह से बहुत अधिक परिवर्तन न हो।

यह वर्तमान दृष्टिकोण से बेहतर है जहां आप छवियों को सीधे घटा रहे हैं। लेकिन यह दृष्टिकोण अभी भी कम है।


सलाह के लिए धन्यवाद मैं इस पर एक नज़र डालूंगा।
नील्स क्रिस्टियन

यह बहुत उपयोगी उत्तर नहीं है क्योंकि यह प्रदर्शित नहीं करता है कि लक्ष्य को कैसे पूरा किया जाए। यह "Google इस शब्द के बराबर है और इसे स्वयं समझ लें।"
एक और

हिस्टोग्राम उन चीजों में से एक है जो लोग इमेज प्रोसेसिंग में सीखते हैं। अगर कुछ को इसे गूगल करना है, तो मैं गहराई से माफी मांगता हूं।
रवितजा नर्रा

3

आमतौर पर टेम्पलेट मिलान का इन स्थितियों में अच्छा परिणाम होता है। टेम्पलेट मिलान एक छवि के क्षेत्रों को खोजने के लिए एक तकनीक है जो टेम्पलेट छवि (दूसरी छवि) से मेल खाती है (समान हैं)। यह एल्गोरिथ्म स्रोत छवि (दूसरा वाला) में सबसे अच्छा मैक्टेड स्थिति के लिए एक अंक देता है।

TM_CCOEFF_NORMED पद्धति का उपयोग करते हुए opencv में , 0 और 1. के बीच स्कोर देता है। यदि स्कोर 1 है, तो इसका मतलब है कि टेम्पलेट छवि स्रोत छवि का एक हिस्सा (रीक्ट) है, लेकिन अगर आपके पास लाइटनिंग या परिप्रेक्ष्य में थोड़ा बदलाव है दो छवि, स्कोर 1 से कम होगा।

अब समानता स्कोर के लिए एक सीमा पर विचार करके, आप पता लगा सकते हैं कि वे समान हैं या नहीं। उस दहलीज को कुछ नमूना छवियों पर कुछ परीक्षण और त्रुटि द्वारा प्राप्त किया जा सकता है। मैंने आपके चित्र आज़माए और स्कोर 0.823863 हो गया । यहाँ कोड (opencv C ++) और मेल द्वारा प्राप्त दो छवियों के बीच का सामान्य क्षेत्र है:

यहां छवि विवरण दर्ज करें

Mat im2 = imread("E:/1/1.jpg", 1);
//Mat im2;// = imread("E:/1/1.jpg", 1);
Mat im1 = imread("E:/1/2.jpg", 1);

//im1(Rect(0, 0, im1.cols - 5, im1.rows - 5)).copyTo(im2);

int result_cols = im1.cols - im2.cols + 1;
int result_rows = im1.rows - im2.rows + 1;

Mat result = Mat::zeros(result_rows, result_cols, CV_32FC1);

matchTemplate(im1, im2, result, TM_CCOEFF_NORMED);

double minVal; double maxVal;
Point minLoc; Point maxLoc;
Point matchLoc;

minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());

cout << minVal << " " << maxVal << " " << minLoc << " " << maxLoc << "\n";
matchLoc = maxLoc;

rectangle(im1, matchLoc, Point(matchLoc.x + im2.cols, matchLoc.y + im2.rows), Scalar::all(0), 2, 8, 0);
rectangle(result, matchLoc, Point(matchLoc.x + im2.cols, matchLoc.y + im2.rows), Scalar::all(0), 2, 8, 0);

imshow("1", im1);
imshow("2", result);
waitKey(0);

सुपर शानदार जवाब के लिए धन्यवाद। अगर मैं कर सकता था, तो मैंने आपको इसके लिए 100p इनाम भी दिया था :-)
नील्स क्रिस्टियन

2

Find_similar_region विधि पर विचार करें । लक्ष्य चित्र के रूप में दो छवियों में से छोटे का उपयोग करें। छवि और लक्ष्य छवि पर फ़ज़ी विशेषताओं के लिए विभिन्न मान आज़माएं।


धन्यवाद, हालांकि मैं इसे काम नहीं कर सकता - क्या आप कर सकते हैं?
नील्स क्रिस्टियन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.