سؤال

أحاول مقارنة الصور إلى بعضها البعض لمعرفة ما إذا كانت مختلفة.الأولى حاولت أن تجعل بيرسون correleation RGB القيم ، الذي يعمل أيضا جيدة جدا إلا إذا كانت الصور قليلا ليت تحول.حتى إذا كان لديك 100% من الصور متطابقة ولكن واحد هو تحركت قليلا, أنا سيئة قيمة الارتباط.

أي اقتراحات لتحسين الخوارزمية ؟

راجع للشغل, أنا أتحدث عن مقارنة ألف من imgages...

تحرير:هنا هو مثال على الصور (المجهرية):

im1:

enter image description here

im2:

enter image description here

im3:

enter image description here

im1 و im2 هي نفسها ولكن قليلا تحول/cutted, im3 ينبغي اعتبار كلي مختلفة...

تحرير: يتم حل المشكلة مع اقتراحات بيتر هانسن!يعمل بشكل جيد جدا!شكرا لجميع الإجابات!بعض النتائج التي يمكن العثور عليها هنا http://labtools.ipk-gatersleben.de/image%20comparison/image%20comparision.pdf

هل كانت مفيدة؟

المحلول

A مثل هذا السؤال وطلب من العام الماضي و لديه العديد من الردود ، بما في ذلك أحد فيما يتعلق pixelizing الصور التي كنت سأقترح على الأقل التأهيل المسبق الخطوة (كما يستبعد جدا غير صور مماثلة جدا بسرعة).

هناك أيضا وصلات إلى هناك لا تزال في وقت سابق من الأسئلة التي لها أكثر المراجع إجابات جيدة.

وهنا التنفيذ باستخدام بعض الأفكار مع Scipy باستخدام يدك فوق ثلاث صور (حفظ im1.jpg, im2.jpg, im3.jpg ، على التوالي).الناتج النهائي يظهر im1 مقارنة مع نفسها كخط أساس ، ثم كل صورة مقارنة مع الآخرين.

>>> import scipy as sp
>>> from scipy.misc import imread
>>> from scipy.signal.signaltools import correlate2d as c2d
>>>
>>> def get(i):
...     # get JPG image as Scipy array, RGB (3 layer)
...     data = imread('im%s.jpg' % i)
...     # convert to grey-scale using W3C luminance calc
...     data = sp.inner(data, [299, 587, 114]) / 1000.0
...     # normalize per http://en.wikipedia.org/wiki/Cross-correlation
...     return (data - data.mean()) / data.std()
...
>>> im1 = get(1)
>>> im2 = get(2)
>>> im3 = get(3)
>>> im1.shape
(105, 401)
>>> im2.shape
(109, 373)
>>> im3.shape
(121, 457)
>>> c11 = c2d(im1, im1, mode='same')  # baseline
>>> c12 = c2d(im1, im2, mode='same')
>>> c13 = c2d(im1, im3, mode='same')
>>> c23 = c2d(im2, im3, mode='same')
>>> c11.max(), c12.max(), c13.max(), c23.max()
(42105.00000000259, 39898.103896795357, 16482.883608327804, 15873.465425120798)

لذلك نلاحظ أن im1 مقارنة مع ذاته يعطي درجة من 42105, im2 مقارنة مع im1 ليس بعيدا ، ولكن im3 مقارنة مع الآخرين يعطي تحت نصف تلك القيمة.سيكون لديك تجربة مع صور أخرى لمعرفة مدى هذه قد تؤدي وكيف يمكن تحسينه.

وقت تشغيل طويل...عدة دقائق على الجهاز الخاص بي.وأود أن محاولة بعض ما قبل الترشيح لتجنب إضاعة الوقت مقارنة جدا صور متباينة ، ربما مع "مقارنة jpg حجم الملف" خدعة المذكورة في الردود على مسألة أخرى ، أو مع pixelization.حقيقة أن لديك صور مختلفة الأحجام يعقد الأمور ، ولكن لم تعطي معلومات كافية حول مدى ذبح قد يتوقع المرء ، لذلك فإنه من الصعب إعطاء إجابة محددة أن يأخذ ذلك في الاعتبار.

نصائح أخرى

لدي واحدة فعلت هذا مع صورة الرسم البياني مقارنة.بلدي الخوارزمية الأساسية هو هذا:

  1. تقسيم الصورة إلى الأحمر والأخضر والأزرق
  2. إنشاء تطبيع رسوم بيانية الأحمر والأخضر والأزرق قناة لسلسلة لهم في ناقلات (r0...rn, g0...gn, b0...bn) حيث n هو عدد "دلاء", 256 ينبغي أن يكون كافيا
  3. طرح هذا الرسم البياني من الرسم البياني من صورة أخرى وحساب المسافة

هنا بعض التعليمات البرمجية مع numpy و pil

r = numpy.asarray(im.convert( "RGB", (1,0,0,0, 1,0,0,0, 1,0,0,0) ))
g = numpy.asarray(im.convert( "RGB", (0,1,0,0, 0,1,0,0, 0,1,0,0) ))
b = numpy.asarray(im.convert( "RGB", (0,0,1,0, 0,0,1,0, 0,0,1,0) ))
hr, h_bins = numpy.histogram(r, bins=256, new=True, normed=True)
hg, h_bins = numpy.histogram(g, bins=256, new=True, normed=True)
hb, h_bins = numpy.histogram(b, bins=256, new=True, normed=True)
hist = numpy.array([hr, hg, hb]).ravel()

إذا كان لديك اثنين من رسوم بيانية ، يمكنك الحصول على المسافة مثل هذا:

diff = hist1 - hist2
distance = numpy.sqrt(numpy.dot(diff, diff))

إذا اثنين من الصور متطابقة ، المسافة هو 0 ، بقدر ما تتباعد كلما بعدت المسافة.

انها عملت بشكل جيد جدا على الصور بالنسبة لي لكنه فشل في الرسومات مثل النصوص و الشعارات.

كنت حقا بحاجة إلى تحديد السؤال بشكل أفضل ، ولكن ينظر إلى تلك الصور 5, الكائنات الحية جميعا يبدو أن تكون موجهة بنفس الطريقة.إذا كان هذا هو الحال دائما, يمكنك محاولة القيام تطبيع عبر الارتباط بين الصورتين وأخذ قيمة الذروة مثل درجة من التشابه.أنا لا أعرف من تطبيع عبر ارتباط وظيفة في بيثون ، ولكن هناك مماثلة fftconvolve() وظيفة يمكنك القيام به التعميم عبر ارتباط نفسك:

a = asarray(Image.open('c603225337.jpg').convert('L'))
b = asarray(Image.open('9b78f22f42.jpg').convert('L'))
f1 = rfftn(a)
f2 = rfftn(b)
g =  f1 * f2
c = irfftn(g)

هذا لن يعمل كما هو مكتوب منذ الصور مختلفة الأحجام و الإخراج لا مرجح أو تطبيع على الإطلاق.

موقع قيمة الذروة من الإخراج إلى الإزاحة بين الصورتين ، وحجم الذروة يشير إلى التشابه.يجب أن يكون هناك طريقة الوزن/تطبيع بحيث يمكنك معرفة الفرق بين مباراة جيدة و الفقراء المباراة.

هذه ليست جيدة من إجابة كما أريد ، حيث لم ترد على كيفية تطبيع بعد ولكن سوف أقوم بتحديث الموضوع إن معرفة ذلك ، وسوف تعطيك فكرة أن ننظر إلى.

إذا كانت المشكلة هي حول تحول بكسل ، ربما يجب أن تقارن ضد تحويل التردد.

الاتحاد الفرنسي للتنس أن تكون على ما يرام (numpy له تنفيذ 2D المصفوفات), ولكن أنا دائما أسمع هذا المويجات أفضل لهذا النوع من المهام ^_^

عن الأداء ، إذا كانت جميع الصور هي من نفس الحجم ، إذا كنت أتذكر جيدا ، FFTW حزمة خلق المتخصصة وظيفة لكل الاتحاد الفرنسي للتنس حجم المدخلات ، حتى تتمكن من الحصول على لطيفة تعزيز الأداء إعادة استخدام نفس رمز...أنا لا أعرف إذا كان numpy على أساس FFTW, ولكن إذا لم يكن ربما قد تتمكن من محاولة للتحقيق قليلا هناك.

هنا لديك النموذج...يمكنك أن تلعب قليلا مع ذلك لمعرفة أي عتبة تناسبها مع الصور الخاصة بك.

import Image
import numpy
import sys

def main():
    img1 = Image.open(sys.argv[1])
    img2 = Image.open(sys.argv[2])

    if img1.size != img2.size or img1.getbands() != img2.getbands():
        return -1

    s = 0
    for band_index, band in enumerate(img1.getbands()):
        m1 = numpy.fft.fft2(numpy.array([p[band_index] for p in img1.getdata()]).reshape(*img1.size))
        m2 = numpy.fft.fft2(numpy.array([p[band_index] for p in img2.getdata()]).reshape(*img2.size))
        s += numpy.sum(numpy.abs(m1-m2))
    print s

if __name__ == "__main__":
    sys.exit(main())

آخر طريقة للمضي قدما قد يكون عدم وضوح الصور ، ثم طرح قيم البكسل من الصورتين.إذا كان الفرق غير النيل, ثم يمكنك تحويل واحدة من الصور 1 بكسل في كل اتجاه و قارن مرة أخرى ، إذا كان الفرق أقل مما هو عليه في الخطوة السابقة, يمكنك تكرار التحول في اتجاه التدرج و طرح حتى الفرق أقل من عتبة معينة أو يزيد مرة أخرى.التي يجب أن تعمل إذا كان نصف قطر وضوح نواة أكبر من التحول من الصور.

أيضا, يمكنك أن تجرب مع بعض الأدوات التي تستخدم عادة في تصوير العمل على مزج عدة معارض أو القيام الإستعراضات ، مثل بانو أدوات.

وقد فعلت بعض الصور المعالجة الحال منذ فترة طويلة, و تذكر أن مطابقة عادة بدأت مع جعل الصورة الرمادي ، ثم شحذ حواف الصورة حتى ترى فقط الحواف.أنت (البرنامج) ثم تحول طرح الصور حتى الفرق هو الحد الأدنى.

إذا كان هذا الفرق هو أكبر من treshold يمكنك تعيين الصور ليست متساوية ثم يمكنك الانتقال إلى المرحلة التالية.الصور مع أصغر treshold ثم يمكن تحليل المقبل.

أنا لا أعتقد أنه في أفضل يمكنك جذريا رقيقة من الممكن المباريات, ولكن سوف تحتاج إلى شخصيا مقارنة مباريات ممكنة لتحديد انهم حقا على قدم المساواة.

أنا لا يمكن أن تظهر حقا رمز كما كان منذ زمن طويل ، واعتدت Khoros/الأنشودة على هذا الحال.

أولا: الارتباط هو وحدة المعالجة المركزية مكثفة جدا دقيق لقياس التشابه.لماذا لا تذهب فقط من مجموع المربعات لو الاختلافات بين الأفراد بكسل ؟

الحل بسيط, إذا كان الحد الأقصى التحول محدودة:تولد كل ممكن تحول الصور والعثور على واحد الذي هو أفضل مباراة.تأكد من حساب الخاص بك المباراة متغير (أيcorrellation) فقط على مجموعة فرعية من وحدات البكسل التي يمكن أن تكون مطابقة في كل تحول الصور.يوفر أقصى قدر من التحول يجب أن يكون أصغر بكثير من حجم الصور الخاصة بك.

إذا كنت ترغب في استخدام بعض السلف تقنيات معالجة الصور أقترح عليك البحث في نخل هذا هو قوية جدا طريقة (نظريا على أي حال) يمكن أن تتطابق بشكل صحيح البنود في الصور المستقلة الترجمة, دوران واسع.

أعتقد أنك يمكن أن تفعل شيئا مثل هذا:

  • تقدير عمودي / أفقي النزوح من الإشارة صورة مقابل صورة مقارنة.a بسيطة حزين (مجموع المطلق الفرق) مع نواقل الحركة أن تفعل ذلك.

  • تحويل صورة مقارنة وفقا لذلك

  • حساب الارتباط بيرسون كنت تحاول فعله

التحول القياس ليس من الصعب.

  • تأخذ المنطقة (قوله عن 32 × 32) في صورة مقارنة.
  • تحول ذلك بواسطة x بكسل أفقي و y بكسل في الاتجاه الرأسي.
  • حساب حزين (مجموع المطلق الفرق) ث.r.t.الصورة الأصلية
  • هل هذا لعدة قيم x و y في مجموعة صغيرة (-10, +10)
  • العثور على مكان حيث الفرق هو الحد الأدنى
  • اختيار تلك القيمة كما تحول ناقلات الحركة

ملاحظة:

إذا كان حزينا قادم عالية جدا لجميع قيم x و y ثم يمكنك على أية حال نفترض أن الصور عالية متباينة و التحول القياس ليس من الضروري.

للحصول على واردات للعمل بشكل صحيح على أوبونتو 16.04 (اعتبارا من نيسان / أبريل 2017), تثبيت بايثون 2.7 و هذه:

sudo apt-get install python-dev
sudo apt-get install libtiff5-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python-tk
sudo apt-get install python-scipy
sudo pip install pillow

ثم غيرت ندفة الثلج واردات هذه:

import scipy as sp
from scipy.ndimage import imread
from scipy.signal.signaltools import correlate2d as c2d

كيف رهيبة هذا ندفة الثلج كتابتها عملت لي 8 سنوات!

أقترح حل يقوم على Jaccard مؤشر التشابه في صورة رسوم بيانية.انظر: https://en.wikipedia.org/wiki/Jaccard_index#Weighted_Jaccard_similarity_and_distance

يمكنك حساب الفرق في توزيع بكسل الألوان.هذا هو في الواقع جميلة ثابتة إلى ترجمة.

from PIL.Image import Image
from typing import List

def jaccard_similarity(im1: Image, im2: Image) -> float:
    """Compute the similarity between two images.
    First, for each image an histogram of the pixels distribution is extracted.
    Then, the similarity between the histograms is compared using the weighted Jaccard index of similarity, defined as:
    Jsimilarity = sum(min(b1_i, b2_i)) / sum(max(b1_i, b2_i)
    where b1_i, and b2_i are the ith histogram bin of images 1 and 2, respectively.

    The two images must have same resolution and number of channels (depth).

    See: https://en.wikipedia.org/wiki/Jaccard_index
    Where it is also called Ruzicka similarity."""

    if im1.size != im2.size:
        raise Exception("Images must have the same size. Found {} and {}".format(im1.size, im2.size))

    n_channels_1 = len(im1.getbands())
    n_channels_2 = len(im2.getbands())
    if n_channels_1 != n_channels_2:
        raise Exception("Images must have the same number of channels. Found {} and {}".format(n_channels_1, n_channels_2))

    assert n_channels_1 == n_channels_2

    sum_mins = 0
    sum_maxs = 0

    hi1 = im1.histogram()  # type: List[int]
    hi2 = im2.histogram()  # type: List[int]

    # Since the two images have the same amount of channels, they must have the same amount of bins in the histogram.
    assert len(hi1) == len(hi2)

    for b1, b2 in zip(hi1, hi2):
        min_b = min(b1, b2)
        sum_mins += min_b
        max_b = max(b1, b2)
        sum_maxs += max_b

    jaccard_index = sum_mins / sum_maxs

    return jaccard_index

فيما يتعلق الخطأ التربيعي ، Jaccard مؤشر يكمن دائما في نطاق [0,1] ، مما يتيح إجراء مقارنات بين أحجام الصور المختلفة.

ثم يمكنك مقارنة الصورتين ، ولكن بعد إعادة قياس إلى نفس الحجم!أو بكسل التهم سوف يكون بطريقة أو بأخرى طبيعية.أنا استخدم هذا:

import sys

from skincare.common.utils import jaccard_similarity

import PIL.Image
from PIL.Image import Image

file1 = sys.argv[1]
file2 = sys.argv[2]

im1 = PIL.Image.open(file1)  # type: Image
im2 = PIL.Image.open(file2)  # type: Image

print("Image 1: mode={}, size={}".format(im1.mode, im1.size))
print("Image 2: mode={}, size={}".format(im2.mode, im2.size))

if im1.size != im2.size:
    print("Resizing image 2 to {}".format(im1.size))
    im2 = im2.resize(im1.size, resample=PIL.Image.BILINEAR)

j = jaccard_similarity(im1, im2)
print("Jaccard similarity index = {}".format(j))

اختبار على الصور الخاصة بك:

$ python CompareTwoImages.py im1.jpg im2.jpg
Image 1: mode=RGB, size=(401, 105)
Image 2: mode=RGB, size=(373, 109)
Resizing image 2 to (401, 105)
Jaccard similarity index = 0.7238955686269157
$ python CompareTwoImages.py im1.jpg im3.jpg 
Image 1: mode=RGB, size=(401, 105)
Image 2: mode=RGB, size=(457, 121)
Resizing image 2 to (401, 105)
Jaccard similarity index = 0.22785529941822316
$ python CompareTwoImages.py im2.jpg im3.jpg 
Image 1: mode=RGB, size=(373, 109)
Image 2: mode=RGB, size=(457, 121)
Resizing image 2 to (373, 109)
Jaccard similarity index = 0.29066426814105445

كنت قد تنظر أيضا في تجريب مختلف اختزال المرشحات (مثل أقرب أو LANCZOS) ، كما أنها بالطبع تغير لون التوزيع عند تغيير حجم.

بالإضافة إلى ذلك, تعتبر أن مبادلة الصور تغيير النتائج ، كما الصورة الثانية قد تكون downsampled بدلا من upsampled (بعد كل شيء ، الاقتصاص قد تناسب حالتك بدلا من إعادة قياس.)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top