python - मैं दो छवियों के बीच अंतर कैसे माप सकता हूं?




image-processing background-subtraction (12)

सामान्य विचार

विकल्प 1: दोनों छवियों को सरणी ( scipy.misc.imread ) के रूप में लोड करें और तत्व-वार (पिक्सेल-बाय-पिक्सेल) अंतर की गणना करें। अंतर के मानदंड की गणना करें।

विकल्प 2: दोनों छवियों को लोड करें। उनमें से प्रत्येक के लिए कुछ फीचर वेक्टर की गणना करें (जैसे हिस्टोग्राम)। छवियों के बजाय फीचर वैक्टर के बीच दूरी की गणना करें।

हालांकि, पहले बनाने के कुछ निर्णय हैं।

प्रशन

आपको पहले इन सवालों का जवाब देना चाहिए:

  • एक ही आकार और आयाम की छवियां हैं?

    यदि नहीं, तो आपको उन्हें आकार बदलने या फसल करने की आवश्यकता हो सकती है। पीआईएल पुस्तकालय इसे पायथन में करने में मदद करेगा।

    अगर उन्हें एक ही सेटिंग्स और एक ही डिवाइस के साथ लिया जाता है, तो वे शायद वही हैं।

  • क्या छवियां अच्छी तरह से गठबंधन हैं?

    यदि नहीं, तो पहले सबसे अच्छा संरेखण खोजने के लिए, आप पहले क्रॉस-सहसंबंध चला सकते हैं। SciPy करने के लिए काम करता है।

    अगर कैमरा और दृश्य अभी भी हैं, तो छवियों को अच्छी तरह से गठबंधन होने की संभावना है।

  • छवियों का संपर्क हमेशा एक ही है? (क्या हल्कापन / इसके विपरीत है?)

    यदि नहीं, तो आप छवियों को सामान्य बनाना चाहते हैं।

    लेकिन सावधान रहें, कुछ स्थितियों में यह अच्छा से ज्यादा गलत हो सकता है। उदाहरण के लिए, एक अंधेरे पृष्ठभूमि पर एक चमकदार पिक्सेल सामान्यीकृत छवि को बहुत अलग बना देगा।

  • क्या रंग की जानकारी महत्वपूर्ण है?

    यदि आप रंग परिवर्तनों को नोटिस करना चाहते हैं, तो आपके पास ग्रे-स्केल छवि के रूप में स्केलर मान की बजाय प्रति बिंदु रंग मानों का वेक्टर होगा। इस तरह के कोड लिखते समय आपको अधिक ध्यान देने की जरूरत है।

  • क्या छवि में अलग किनारे हैं? क्या वे आगे बढ़ने की संभावना रखते हैं?

    यदि हां, तो आप पहले किनारे का पता लगाने एल्गोरिदम लागू कर सकते हैं (उदाहरण के लिए सोबेल या प्रीविट ट्रांसफॉर्म के साथ ग्रेडियेंट की गणना करें, कुछ थ्रेसहोल्ड लागू करें), फिर दूसरी छवि पर किनारों पर किनारों की तुलना करें।

  • क्या छवि में शोर है?

    सभी सेंसर छवि को कुछ मात्रा में शोर के साथ प्रदूषित करते हैं। कम लागत वाले सेंसर में अधिक शोर है। छवियों की तुलना करने से पहले आप कुछ शोर में कमी लागू कर सकते हैं। ब्लर यहां सबसे सरल (लेकिन सबसे अच्छा नहीं) दृष्टिकोण है।

  • आप किस प्रकार के बदलावों को नोटिस करना चाहते हैं?

    यह छवियों के बीच अंतर के लिए उपयोग करने के लिए मानक की पसंद को प्रभावित कर सकता है।

    मैनहट्टन मानदंड (पूर्ण मूल्यों का योग) या शून्य मानदंड (शून्य के बराबर तत्वों की संख्या) का उपयोग करने पर विचार करें ताकि यह माप सके कि छवि कितनी बदल गई है। पूर्व आपको बताएगा कि छवि कितनी दूर है, बाद वाला केवल बताएगा कि कितने पिक्सेल अलग हैं।

उदाहरण

मुझे लगता है कि आपकी छवियों को अलग-अलग एक्सपोजर के साथ, समान आकार और आकार, अच्छी तरह से गठबंधन किया गया है। सादगी के लिए, मैं उन्हें ग्रेस्केल में परिवर्तित करता हूं भले ही वे रंग (आरजीबी) छवियां हों।

आपको इन आयातों की आवश्यकता होगी:

import sys

from scipy.misc import imread
from scipy.linalg import norm
from scipy import sum, average

मुख्य समारोह, दो छवियों को पढ़ें, ग्रेस्केल में कनवर्ट करें, परिणामों की तुलना करें और प्रिंट करें:

def main():
    file1, file2 = sys.argv[1:1+2]
    # read images as 2D arrays (convert to grayscale for simplicity)
    img1 = to_grayscale(imread(file1).astype(float))
    img2 = to_grayscale(imread(file2).astype(float))
    # compare
    n_m, n_0 = compare_images(img1, img2)
    print "Manhattan norm:", n_m, "/ per pixel:", n_m/img1.size
    print "Zero norm:", n_0, "/ per pixel:", n_0*1.0/img1.size

तुलना कैसे करें। img1 और img2 यहां 2 डी SciPy arrays हैं:

def compare_images(img1, img2):
    # normalize to compensate for exposure difference, this may be unnecessary
    # consider disabling it
    img1 = normalize(img1)
    img2 = normalize(img2)
    # calculate the difference and its norms
    diff = img1 - img2  # elementwise for scipy arrays
    m_norm = sum(abs(diff))  # Manhattan norm
    z_norm = norm(diff.ravel(), 0)  # Zero norm
    return (m_norm, z_norm)

अगर फ़ाइल एक रंगीन छवि है, तो imread तीव्रता प्राप्त करने के लिए एक 3 डी सरणी, औसत आरजीबी चैनल (अंतिम सरणी अक्ष) देता है। ग्रेस्केल छवियों के लिए ऐसा करने की आवश्यकता नहीं है (उदाहरण के लिए .pgm ):

def to_grayscale(arr):
    "If arr is a color image (3D array), convert it to grayscale (2D array)."
    if len(arr.shape) == 3:
        return average(arr, -1)  # average over the last axis (color channels)
    else:
        return arr

सामान्यीकरण छोटा है, आप [0,255] के बजाय [0,1] को सामान्यीकृत करना चुन सकते हैं। arr यहां एक SciPy सरणी है, इसलिए सभी परिचालन तत्व-वार हैं:

def normalize(arr):
    rng = arr.max()-arr.min()
    amin = arr.min()
    return (arr-amin)*255/rng

main समारोह चलाएं:

if __name__ == "__main__":
    main()

अब आप इसे सब एक स्क्रिप्ट में रख सकते हैं और दो छवियों के खिलाफ चला सकते हैं। अगर हम छवि की तुलना स्वयं करते हैं, तो कोई फर्क नहीं पड़ता:

$ python compare.py one.jpg one.jpg
Manhattan norm: 0.0 / per pixel: 0.0
Zero norm: 0 / per pixel: 0.0

अगर हम छवि को धुंधला करते हैं और मूल की तुलना करते हैं, तो कुछ अंतर होता है:

$ python compare.py one.jpg one-blurred.jpg 
Manhattan norm: 92605183.67 / per pixel: 13.4210411116
Zero norm: 6900000 / per pixel: 1.0

पीएस संपूर्ण compare.py स्क्रिप्ट।

अद्यतन: प्रासंगिक तकनीकें

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

  • पृष्ठभूमि घटाव और विभाजन (अग्रभूमि वस्तुओं का पता लगाने के लिए)
  • स्पैस ऑप्टिकल प्रवाह (गति का पता लगाने के लिए)
  • छवियों के बजाय हिस्टोग्राम या कुछ अन्य आंकड़ों की तुलना करना

मैं दृढ़ता से "लर्निंग ओपनसीवी" पुस्तक, अध्याय 9 (छवि भागों और विभाजन) और 10 (ट्रैकिंग और गति) पर एक नज़र डालने की सलाह देता हूं। पूर्व पृष्ठभूमि घटाव विधि का उपयोग करने के लिए सिखाता है, उत्तरार्द्ध ऑप्टिकल प्रवाह विधियों पर कुछ जानकारी देता है। ओपनसीवी लाइब्रेरी में सभी विधियां लागू की गई हैं। यदि आप पायथन का उपयोग करते हैं, तो मैं cv2 ≥ 2.3, और इसके cv2 पायथन मॉड्यूल का उपयोग करने का सुझाव देता हूं।

पृष्ठभूमि घटाव का सबसे सरल संस्करण:

  • पृष्ठभूमि के प्रत्येक पिक्सेल के लिए औसत मान μ और मानक विचलन σ सीखें
  • वर्तमान पिक्सेल मानों की तुलना (μ-2σ, μ + 2σ) या (μ-σ, μ + σ) की सीमा से करें

अधिक उन्नत संस्करण प्रत्येक पिक्सेल के लिए खाता समय श्रृंखला में लेते हैं और गैर स्थैतिक दृश्यों को नियंत्रित करते हैं (जैसे पेड़ या घास चलाना)।

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

हिस्टोग्राम की तुलना लगातार फ्रेम के बीच अचानक परिवर्तनों का पता लगाने में मदद कर सकती है। इस दृष्टिकोण का इस्तेमाल कॉरबन एट अल, 2010 में किया गया था:

लगातार फ्रेम की समानता। लगातार दो फ्रेम के बीच की दूरी मापा जाता है। यदि यह बहुत अधिक है, तो इसका मतलब है कि दूसरा फ्रेम दूषित हो गया है और इस प्रकार छवि समाप्त हो गई है। कुल्बैक-लीबलर दूरी , या पारस्परिक एन्ट्रॉपी, दो फ्रेम के हिस्टोग्राम पर:

जहां पी और क्यू फ्रेम के हिस्टोग्राम का उपयोग किया जाता है। थ्रेसहोल्ड 0.2 पर तय किया गया है।

यहां मैं क्या करना चाहता हूं:

मैं नियमित अंतराल पर वेबकैम के साथ चित्र ले रहा हूं। एक समय चूक की तरह की तरह क्रमबद्ध करें। हालांकि, अगर कुछ भी वास्तव में नहीं बदला है, यानी, तस्वीर काफी समान दिखती है, तो मैं नवीनतम स्नैपशॉट स्टोर नहीं करना चाहता हूं।

मुझे लगता है कि अंतर को मापने का कोई तरीका है, और मुझे अनुभवी रूप से सीमा तय करना होगा।

मैं पूर्णता के बजाय सादगी की तलाश में हूं। मैं अजगर का उपयोग कर रहा हूँ।


आप PIL से कार्यों का उपयोग कर दो छवियों की तुलना कर सकते हैं।

import Image
import ImageChops

im1 = Image.open("splash.png")
im2 = Image.open("splash2.png")

diff = ImageChops.difference(im2, im1)

Diff ऑब्जेक्ट एक ऐसी छवि है जिसमें प्रत्येक पिक्सेल पहली छवि से दूसरी छवि में उस पिक्सेल के रंग मानों के घटाव का परिणाम होता है। Diff छवि का उपयोग करके आप कई चीजें कर सकते हैं। सबसे सरल एक diff.getbbox() फ़ंक्शन है। यह आपको न्यूनतम आयताकार बताएगा जिसमें आपकी दो छवियों के बीच सभी बदलाव शामिल हैं।

आप शायद पीआईएल के कार्यों का उपयोग करके यहां उल्लिखित अन्य सामानों के अनुमानों को लागू कर सकते हैं।


कुछ हद तक अधिक सिद्धांत दृष्टिकोण जीआईएसटी या सेंट्रिस्ट जैसे छवियों की तुलना करने के लिए वैश्विक वर्णनकर्ता का उपयोग करना है। जैसा कि here वर्णित हैश फ़ंक्शन भी एक समान समाधान प्रदान करता है।


कोशिश करने के लिए एक छोटी सी चीज:

दोनों छवियों को छोटे थंबनेल (उदाहरण के लिए 64 x 64) में दोहराएं और थंबनेल पिक्सेल-बाय-पिक्सेल की तुलना एक निश्चित थ्रेसहोल्ड से करें। यदि मूल छवियां लगभग समान हैं, तो resampled थंबनेल बहुत समान या यहां तक ​​कि वही होगा। यह विधि शोर का ख्याल रखती है जो विशेष रूप से निम्न-प्रकाश दृश्यों में हो सकती है। यदि आप ग्रेस्केल जाते हैं तो यह बेहतर भी हो सकता है।


दिए गए अधिकांश जवाब प्रकाश के स्तर से निपटेंगे नहीं।

मैं तुलना करने से पहले छवि को मानक प्रकाश स्तर पर सामान्यीकृत कर दूंगा।


दो छवियों के बीच समानता को मापने का एक और अच्छा, सरल तरीका:

import sys
from skimage.measure import compare_ssim
from skimage.transform import resize
from scipy.ndimage import imread

# get two images - resize both to 1024 x 1024
img_a = resize(imread(sys.argv[1]), (2**10, 2**10))
img_b = resize(imread(sys.argv[2]), (2**10, 2**10))

# score: {-1:1} measure of the structural similarity between the images
score, diff = compare_ssim(img_a, img_b, full=True)
print(score)

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


मुझे एक ही कैमरे के साथ एक तिपाई पर एक ही कैमरे से ली गई जेपीजी छवियों के साथ बहुत भाग्य मिला है (1) बहुत सरलीकृत (जैसे 3000 पिक्सेल चौड़े से 100 पिक्सेल चौड़े या उससे भी कम तक) (2) प्रत्येक जेपीजी सरणी को एकल में फ़्लैट करना वेक्टर (3) जोड़ों के साथ एक सरल सहसंबंधित एल्गोरिदम के साथ अनुक्रमिक छवियों को सहसंबंधित करना, सह-गुण प्राप्त करने के लिए सहसंबंध गुणांक (4) स्क्वायरिंग सहसंबंध गुणांक प्राप्त करने के लिए (यानी एक छवि में परिवर्तनशीलता का अंश अगले में भिन्नता द्वारा समझाया गया है) (5) आम तौर पर मेरे आवेदन में यदि आर-वर्ग <0.9, मैं कहता हूं कि दो छवियां अलग हैं और कुछ बीच में हुआ है।

यह मेरे कार्यान्वयन में मजबूत और तेज़ है (गणित 7)

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

मुझे नहीं पता कि पायथन का उपयोग कैसे करें, लेकिन मुझे यकीन है कि यह सहसंबंध भी करता है, नहीं?


मुझे एक ही समस्या थी और एक साधारण पायथन मॉड्यूल लिखा जो एक काले / सफेद diff छवि बनाने के लिए तकिया की छवि चॉप का उपयोग करके दो समान आकार की छवियों की तुलना करता है और हिस्टोग्राम मानों को जोड़ता है।

आप या तो यह स्कोर सीधे प्राप्त कर सकते हैं, या एक पूर्ण काला बनाम सफेद diff की तुलना में प्रतिशत मूल्य प्राप्त कर सकते हैं।

इसमें एक साधारण is_equal फ़ंक्शन भी शामिल है, जिसमें छवि के बराबर (और सहित) के तहत एक अस्पष्ट-थ्रेसहोल्ड की आपूर्ति करने की संभावना है।

दृष्टिकोण बहुत विस्तृत नहीं है, लेकिन शायद उसी मुद्दे के साथ संघर्ष करने के लिए अन्य लोगों के लिए उपयोग किया जा सकता है।

https://pypi.python.org/pypi/imgcompare/


मैं विशेष रूप से सवाल पूछ रहा हूं कि अगर वे "अलग-अलग" हैं तो गणना कैसे करें। मुझे लगता है कि आप पिक्सल को एक-एक करके घटा सकते हैं।

सबसे पहले, मैं कुछ भी बदलने के साथ छवियों का एक गुच्छा लेता हूं, और कैप्चर में भिन्नता, इमेजिंग सिस्टम में शोर, जेपीईजी संपीड़न कलाकृतियों, और प्रकाश में क्षण-प्रति-परिवर्तन में बदलाव के कारण अधिकतम पिक्सेल बदलता है । शायद आप पाएंगे कि कुछ भी नहीं होने पर भी 1 या 2 बिट मतभेदों की अपेक्षा की जा सकती है।

फिर "वास्तविक" परीक्षण के लिए, आप इस तरह एक मानदंड चाहते हैं:

  • वही अगर पी पिक्सल तक ई से अधिक नहीं है।

तो, शायद, यदि ई = 0.02, पी = 1000, जिसका अर्थ है (लगभग) कि यह "अलग" होगा यदि कोई भी पिक्सेल ~ 5 इकाइयों (8-बिट छवियों को मानते हुए) से बदलता है, या 1000 से अधिक पिक्सल में कोई त्रुटि थी।

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

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


यह देखें कि कैसे हायर वेवलेट्स isk-daemon द्वारा कार्यान्वित किए जाते हैं। आप फ्लाई पर छवियों के बीच अंतर की गणना करने के लिए इसके आईएमजीडीबी सी ++ कोड का उपयोग कर सकते हैं:

isk-daemon एक ओपन सोर्स डेटाबेस सर्वर है जो सामग्री-आधारित (दृश्य) छवि को किसी भी छवि से संबंधित वेबसाइट या सॉफ़्टवेयर में खोजने में सक्षम है।

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


धरती मूवर्स दूरी बिल्कुल वही हो सकती है जो आपको चाहिए। वास्तविक समय में लागू करने के लिए यह बहुत भारी हो सकता है।


एक साधारण समाधान:

छवि को जेपीईजी के रूप में एन्कोड करें और फाइलसाइज में पर्याप्त बदलाव की तलाश करें।

मैंने वीडियो थंबनेल के साथ कुछ ऐसा ही कार्यान्वित किया है, और इसमें बहुत सफलता और स्केलेबिलिटी थी।





timelapse