Bagaimana saya bisa mengukur perbedaan antara dua gambar?


179

Inilah yang ingin saya lakukan:

Saya mengambil foto dengan webcam secara berkala. Semacam hal selang waktu. Namun, jika tidak ada yang benar-benar berubah, yaitu, gambar cukup banyak terlihat sama, saya tidak ingin menyimpan snapshot terbaru.

Saya membayangkan ada beberapa cara untuk mengukur perbedaan, dan saya harus menentukan ambang batas secara empiris.

Saya mencari kesederhanaan daripada kesempurnaan. Saya menggunakan python.


Jawaban:


269

Ide umum

Opsi 1: Muat kedua gambar sebagai array ( scipy.misc.imread) dan hitung perbedaan elemen-bijaksana (pixel-by-pixel). Hitung norma perbedaannya.

Opsi 2: Muat kedua gambar. Hitung beberapa vektor fitur untuk masing-masing (seperti histogram). Hitung jarak antara vektor fitur daripada gambar.

Namun, ada beberapa keputusan yang harus diambil terlebih dahulu.

Pertanyaan

Anda harus menjawab pertanyaan-pertanyaan ini terlebih dahulu:

  • Apakah gambar dengan bentuk dan dimensi yang sama?

    Jika tidak, Anda mungkin perlu mengubah ukuran atau memangkasnya. PIL library akan membantu melakukannya dengan Python.

    Jika mereka diambil dengan pengaturan yang sama dan perangkat yang sama, mereka mungkin sama.

  • Apakah gambar sejajar dengan baik?

    Jika tidak, Anda mungkin ingin menjalankan korelasi silang terlebih dahulu, untuk menemukan keselarasan terbaik terlebih dahulu. SciPy memiliki fungsi untuk melakukannya.

    Jika kamera dan pemandangan diam, gambar-gambar tersebut kemungkinan akan sejajar dengan baik.

  • Apakah paparan gambar selalu sama? (Apakah terang / kontras sama?)

    Jika tidak, Anda mungkin ingin menormalkan gambar.

    Tapi hati-hati, dalam beberapa situasi ini mungkin melakukan lebih banyak kesalahan daripada kebaikan. Misalnya, satu piksel terang pada latar belakang gelap akan membuat gambar yang dinormalisasi menjadi sangat berbeda.

  • Apakah informasi warna penting?

    Jika Anda ingin melihat perubahan warna, Anda akan memiliki vektor nilai warna per titik, bukan nilai skalar seperti pada gambar skala abu-abu. Anda perlu lebih banyak perhatian saat menulis kode seperti itu.

  • Apakah ada tepi yang berbeda pada gambar? Apakah mereka cenderung bergerak?

    Jika ya, Anda dapat menerapkan algoritme deteksi tepi terlebih dahulu (mis. Menghitung gradien dengan transformasi Sobel atau Prewitt, menerapkan beberapa ambang batas), lalu membandingkan tepi pada gambar pertama dengan tepi pada yang kedua.

  • Apakah ada noise pada gambar?

    Semua sensor mencemari gambar dengan sejumlah noise. Sensor berbiaya rendah memiliki lebih banyak noise. Anda mungkin ingin menerapkan sedikit pengurangan noise sebelum membandingkan gambar. Blur adalah pendekatan yang paling sederhana (tapi bukan yang terbaik) di sini.

  • Perubahan apa yang ingin Anda perhatikan?

    Ini dapat memengaruhi pilihan norma yang digunakan untuk perbedaan antar gambar.

    Pertimbangkan untuk menggunakan norma Manhattan (jumlah nilai absolut) atau norma nol (jumlah elemen yang tidak sama dengan nol) untuk mengukur seberapa banyak gambar telah berubah. Yang pertama akan memberi tahu Anda berapa banyak gambar dimatikan, yang terakhir hanya akan memberitahu berapa banyak piksel berbeda.

Contoh

Saya berasumsi gambar Anda selaras, ukuran dan bentuk yang sama, mungkin dengan pencahayaan berbeda. Untuk kesederhanaan, saya mengonversinya menjadi skala abu-abu walaupun itu adalah gambar berwarna (RGB).

Anda akan membutuhkan impor ini:

import sys

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

Fungsi utama, membaca dua gambar, mengkonversi ke skala abu-abu, membandingkan dan mencetak hasil:

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

Bagaimana cara membandingkan. img1dan img2adalah array 2D SciPy di ​​sini:

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)

Jika file tersebut adalah gambar berwarna, imreadmengembalikan array 3D, saluran RGB rata-rata (sumbu array terakhir) untuk mendapatkan intensitas. Tidak perlu melakukannya untuk gambar skala abu-abu (mis. .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

Normalisasi itu sepele, Anda dapat memilih untuk menormalkan ke [0,1] daripada [0,255]. arradalah array SciPy di ​​sini, jadi semua operasi adalah elemen-bijaksana:

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

Jalankan mainfungsinya:

if __name__ == "__main__":
    main()

Sekarang Anda bisa meletakkan ini semua dalam skrip dan menjalankan dua gambar. Jika kita membandingkan gambar dengan dirinya sendiri, tidak ada perbedaan:

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

Jika kita mengaburkan gambar dan dibandingkan dengan aslinya, ada beberapa perbedaan:

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

PS Seluruh skrip compare.py .

Pembaruan: teknik yang relevan

Karena pertanyaannya adalah tentang urutan video, di mana frame cenderung hampir sama, dan Anda mencari sesuatu yang tidak biasa, saya ingin menyebutkan beberapa pendekatan alternatif yang mungkin relevan:

  • pengurangan dan segmentasi latar belakang (untuk mendeteksi objek latar depan)
  • aliran optik jarang (untuk mendeteksi gerakan)
  • membandingkan histogram atau statistik lain alih-alih gambar

Saya sangat merekomendasikan untuk melihat buku "Belajar OpenCV", Bab 9 (Bagian gambar dan segmentasi) dan 10 (Pelacakan dan gerakan). Yang pertama mengajarkan untuk menggunakan metode pengurangan Background, yang terakhir memberikan beberapa info tentang metode aliran optik. Semua metode diimplementasikan dalam pustaka OpenCV. Jika Anda menggunakan Python, saya sarankan untuk menggunakan OpenCV ≥ 2.3, dan cv2modul Python -nya .

Versi pengurangan latar belakang yang paling sederhana:

  • pelajari nilai rata-rata μ dan standar deviasi σ untuk setiap piksel latar belakang
  • bandingkan nilai piksel saat ini dengan kisaran (μ-2σ, μ + 2σ) atau (μ-σ, μ + σ)

Versi yang lebih canggih mempertimbangkan seri waktu akun untuk setiap piksel dan menangani adegan non-statis (seperti memindahkan pohon atau rumput).

Gagasan aliran optik adalah untuk mengambil dua atau lebih bingkai, dan menetapkan vektor kecepatan ke setiap piksel (aliran optik padat) atau beberapa di antaranya (aliran optik jarang). Untuk memperkirakan aliran optik yang jarang, Anda dapat menggunakan metode Lucas-Kanade (ini juga diterapkan di OpenCV). Jelas, jika ada banyak aliran (rata-rata tinggi di atas nilai maks dari bidang kecepatan), maka ada sesuatu yang bergerak dalam bingkai, dan gambar berikutnya lebih berbeda.

Membandingkan histogram dapat membantu mendeteksi perubahan mendadak antara frame yang berurutan. Pendekatan ini digunakan dalam Courbon et al, 2010 :

Kesamaan frame berturut-turut. Jarak antara dua frame berturut-turut diukur. Jika terlalu tinggi, berarti frame kedua rusak dan dengan demikian gambarnya dihilangkan. Jarak Kullback – Leibler , atau entropi timbal balik, pada histogram kedua frame:

$$ d (p, q) = \ sum_i p (i) \ log (p (i) / q (i)) $$

di mana p dan q adalah histogram dari frame yang digunakan. Ambang ditetapkan pada 0,2.


Saya mendapatkan RuntimeWarning: invalid value encountered in double_scalarson line 44 ( return (arr-amin)*255/rng) dan ValueError: array must not contain infs or NaNson line 30 ( z_norm = norm(diff.ravel(), 0))
BioGeek

@BioGeek yaitu jika rngsama dengan nol. Tambahkan saja cek dan aturrng = 1
haisi

76

Solusi sederhana:

Encode gambar sebagai jpeg dan cari perubahan substansial dalam ukuran file .

Saya telah mengimplementasikan sesuatu yang mirip dengan gambar mini video, dan memiliki banyak kesuksesan dan skalabilitas.


3
Ini adalah solusi yang sangat mudah, sederhana dan jauh lebih baik daripada perbandingan piksel-bijaksana. Jika ada sedikit noise pada gambar webcam Anda atau jika gambar digeser bahkan oleh satu pixel, maka perbandingan langsung akan mengambil semua perubahan yang tidak berarti ini. Pendekatan yang lebih kuat akan menghitung transformasi cosinus diskrit dan kemudian membandingkan gambar dalam domain frekuensi. Menggunakan kompresi JPEG seperti ini memberi Anda sebagian besar manfaat tanpa masuk ke teori Fourier.
AndrewF

Suka itu. Meskipun solusi lain juga berfungsi, ini memiliki keuntungan besar untuk situasi umum: bagaimana jika Anda tidak ingin menyimpan gambar "basis"? cukup simpan ukuran file sebagai hash dan kemudian bandingkan angka hanya dengan substraksi. Dalam kasus saya, saya memiliki 4 gambar, salah satunya sangat mirip dan 3 lainnya sangat berbeda. Hanya skala ke dimensi yang sama, untuk jpg dan kurangi. Benar-benar bagus.
Diego Andrés Díaz Espinoza

60

Anda dapat membandingkan dua gambar menggunakan fungsi dari PIL .

import Image
import ImageChops

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

diff = ImageChops.difference(im2, im1)

Objek diff adalah gambar di mana setiap piksel adalah hasil dari pengurangan nilai warna dari piksel tersebut di gambar kedua dari gambar pertama. Menggunakan gambar diff Anda dapat melakukan beberapa hal. Yang paling sederhana adalah diff.getbbox()fungsinya. Ini akan memberi tahu Anda persegi panjang minimal yang berisi semua perubahan antara dua gambar Anda.

Anda mungkin dapat mengimplementasikan perkiraan hal-hal lain yang disebutkan di sini menggunakan fungsi dari PIL juga.


2
Saya ingin menyimpan perbedaan gambar. berarti objek diff yang menyimpan perbedaan gambar. bagaimana saya menyimpannya?
Sagar

2
@Anthony Anda dapat memanggil save () pada objek berbeda yang menentukan nama gambar. seperti ini: diff.save ("diff.png") itu akan menyimpan perbedaan gambar untuk Anda.
Sagar

20

Dua metode populer dan relatif sederhana adalah: (a) jarak Euclidean sudah disarankan, atau (b) normalisasi lintas-korelasi. Korelasi silang yang dinormalisasi cenderung lebih kuat pada perubahan pencahayaan daripada korelasi silang sederhana. Wikipedia memberikan rumus untuk korelasi silang yang dinormalisasi . Ada metode yang lebih canggih juga, tetapi mereka membutuhkan sedikit lebih banyak pekerjaan.

Menggunakan sintaks seperti numpy,

dist_euclidean = sqrt (jumlah ((i1 - i2) ^ 2)) / i1.size

dist_manhattan = jumlah (abs (i1 - i2)) / i1.size

dist_ncc = jumlah ((i1 - mean (i1)) * (i2 - mean (i2))) / (
  (i1.size - 1) * stdev (i1) * stdev (i2))

dengan asumsi itu i1dan i2adalah array gambar grayscale 2D.


3
Fungsi korelasi silang gambar dibangun ke dalam SciPy ( docs.scipy.org/doc/scipy/reference/generated/… ), dan versi cepat menggunakan FFT tersedia dalam stsci python ( stsci.edu/resources/software_hardware/pyraf/ stsci_python )
endolith

14

Suatu hal yang sepele untuk dicoba:

Ubah sampel kedua gambar menjadi thumbnail kecil (mis. 64 x 64) dan bandingkan thumbnail piksel-demi-piksel dengan ambang batas tertentu. Jika gambar aslinya hampir sama, thumbnail yang di-resampled akan sangat mirip atau bahkan sama persis. Metode ini menangani kebisingan yang dapat terjadi terutama dalam adegan cahaya rendah. Bahkan mungkin lebih baik jika Anda menggunakan skala abu-abu.


tetapi bagaimana Anda membandingkan piksel?
operator

Setelah memiliki thumbnail, Anda dapat membandingkan piksel satu per satu. Anda akan menghitung "jarak" dari nilai-nilai RGB, jika Anda bekerja dalam warna atau hanya perbedaan antara nada abu-abu jika Anda dalam skala abu-abu.
Ates Goral

1
+ msgstr "bandingkan piksel satu per satu". Apa artinya? Haruskah tes gagal jika SATU dari 64 ^ 2 pixel per pixel tes gagal?
Federico A. Ramponi

Apa yang saya maksud dengan "bandingkan thumbnail pixel-by-pixel dengan ambang tertentu" adalah untuk datang dengan algoritma fuzzy untuk membandingkan piksel. Jika perbedaan yang dihitung (tergantung pada algoritma fuzzy Anda) melebihi ambang tertentu, gambarnya "tidak sama".
Ates Goral

1
Contoh yang sangat sederhana, tanpa "algoritma fuzzy": loop paralel melalui setiap piksel (bandingkan piksel # n gambar # 1 dengan piksel # n gambar # 2), dan tambahkan perbedaan nilainya ke variabel
mk12

7

Saya membahas secara khusus pertanyaan tentang bagaimana menghitung jika mereka "cukup berbeda". Saya berasumsi Anda dapat mengetahui cara mengurangi piksel satu per satu.

Pertama, saya akan mengambil banyak gambar tanpa perubahan apa pun , dan mencari tahu jumlah maksimum yang diubah oleh piksel apa pun hanya karena variasi tangkapan, derau dalam sistem pencitraan, artefak kompresi JPEG, dan perubahan pencahayaan dari waktu ke waktu dalam pencahayaan. . Mungkin Anda akan menemukan bahwa perbedaan 1 atau 2 bit diharapkan bahkan ketika tidak ada yang bergerak.

Kemudian untuk tes "nyata", Anda ingin kriteria seperti ini:

  • sama jika hingga P pixel berbeda tidak lebih dari E.

Jadi, mungkin, jika E = 0,02, P = 1000, itu akan berarti (kurang-lebih) bahwa itu akan "berbeda" jika ada satu piksel yang berubah lebih dari ~ 5 unit (dengan asumsi gambar 8-bit), atau jika lebih dari 1000 piksel memiliki kesalahan sama sekali.

Ini dimaksudkan terutama sebagai teknik "triase" yang baik untuk dengan cepat mengidentifikasi gambar yang cukup dekat sehingga tidak perlu pemeriksaan lebih lanjut. Gambar-gambar yang "gagal" mungkin lebih ke teknik yang lebih rumit / mahal yang tidak akan memiliki positif palsu jika kamera bergetar sedikit, misalnya, atau lebih kuat untuk perubahan pencahayaan.

Saya menjalankan proyek open source, OpenImageIO , yang berisi utilitas bernama "idiff" yang membandingkan perbedaan dengan ambang batas seperti ini (bahkan lebih rumit, sebenarnya). Bahkan jika Anda tidak ingin menggunakan perangkat lunak ini, Anda mungkin ingin melihat sumbernya untuk melihat bagaimana kami melakukannya. Ini digunakan secara komersial sedikit dan teknik thresholding ini dikembangkan sehingga kami bisa memiliki test suite untuk rendering dan perangkat lunak pemrosesan gambar, dengan "gambar referensi" yang mungkin memiliki perbedaan kecil dari platform ke platform atau saat kami membuat perubahan kecil untuk algoritma, jadi kami ingin operasi "cocok dalam toleransi".


6

Saya memiliki masalah yang sama di tempat kerja, saya sedang menulis ulang titik akhir transformasi gambar kami dan saya ingin memeriksa bahwa versi baru menghasilkan keluaran yang sama atau hampir sama dengan versi lama. Jadi saya menulis ini:

https://github.com/nicolashahn/diffimg

Yang beroperasi pada gambar dengan ukuran yang sama, dan pada level per-pixel, mengukur perbedaan nilai di setiap saluran: R, G, B (, A), mengambil perbedaan rata-rata dari saluran tersebut, dan kemudian rata-rata selisih lebih dari semua piksel, dan mengembalikan rasio.

Misalnya, dengan gambar 10x10 piksel putih, dan gambar yang sama tetapi satu piksel telah berubah menjadi merah, perbedaan pada piksel tersebut adalah 1/3 atau 0,33 ... (RGB 0,0,0 vs 255,0,0 ) dan semua piksel lainnya adalah 0. Dengan total 100 piksel, 0,33 ... / 100 = perbedaan ~ 0,33% pada gambar.

Saya percaya ini akan bekerja dengan sempurna untuk proyek OP (saya menyadari ini adalah posting yang sangat lama sekarang, tetapi memposting untuk StackOverflowers masa depan yang juga ingin membandingkan gambar dengan python).


5

Sebagian besar jawaban yang diberikan tidak akan berurusan dengan tingkat pencahayaan.

Pertama-tama saya akan menormalkan gambar ke tingkat cahaya standar sebelum melakukan perbandingan.


Jika Anda mengambil gambar periodik dan membedakan pasangan yang berdekatan, Anda mungkin dapat menyimpan yang pertama setelah seseorang menyalakan lampu.
walkytalky

5

Cara lain yang bagus dan sederhana untuk mengukur kesamaan antara dua gambar:

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)

Jika orang lain tertarik dengan cara yang lebih kuat untuk membandingkan gambar kesamaan, saya mengumpulkan tutorial dan web app untuk mengukur dan memvisualisasikan gambar yang sama menggunakan Tensorflow.


3
Ya, skimagesangat bagus digunakan untuk aplikasi ini. Saya menggunakan from skimage.measure import compare_ssim, compare_msebanyak. skimage.measure docs .
ximiki

3

Pernahkah Anda melihat Algoritma untuk menemukan pertanyaan gambar yang serupa ? Lihat untuk melihat saran.

Saya akan menyarankan transformasi wavelet dari frame Anda (Saya telah menulis ekstensi C untuk itu menggunakan transformasi Haar); kemudian, dengan membandingkan indeks faktor-faktor wavelet terbesar (proporsional) antara kedua gambar, Anda harus mendapatkan perkiraan kemiripan numerik.


2

Saya minta maaf jika sudah terlambat untuk menjawab, tetapi karena saya sudah melakukan hal yang serupa, saya pikir saya bisa berkontribusi.

Mungkin dengan OpenCV Anda bisa menggunakan pencocokan templat. Dengan asumsi Anda menggunakan webcam seperti yang Anda katakan:

  1. Sederhanakan gambar (mungkin ambang batas?)
  2. Terapkan pencocokan templat dan periksa max_val dengan minMaxLoc

Tip: max_val (atau min_val tergantung pada metode yang digunakan) akan memberi Anda angka, angka besar. Untuk mendapatkan perbedaan dalam persentase, gunakan pencocokan templat dengan gambar yang sama - hasilnya adalah 100% Anda.

Kode palsu untuk dicontohkan:

previous_screenshot = ...
current_screenshot = ...

# simplify both images somehow

# get the 100% corresponding value
res = matchTemplate(previous_screenshot, previous_screenshot, TM_CCOEFF)
_, hundred_p_val, _, _ = minMaxLoc(res)

# hundred_p_val is now the 100%

res = matchTemplate(previous_screenshot, current_screenshot, TM_CCOEFF)
_, max_val, _, _ = minMaxLoc(res)

difference_percentage = max_val / hundred_p_val

# the tolerance is now up to you

Semoga ini bisa membantu.


1

Jarak penggerak bumi mungkin persis seperti yang Anda butuhkan. Mungkin abit berat untuk melaksanakan secara real time sekalipun.


Saya tidak benar-benar merasakan jawaban ini cocok dengan baik: "Saya mencari kesederhanaan daripada kesempurnaan. Saya menggunakan python."
PilouPili

Saya pikir karena utas pertanyaan ini mendapat banyak lalu lintas dan judul yang menarik sebagian besar pemirsa adalah tentang bagaimana mengukur perbedaan antara dua gambar, ia memiliki nilai di sini.
Danoram

1

Bagaimana dengan menghitung Jarak Manhattan dari dua gambar. Itu memberi Anda nilai n * n. Kemudian Anda bisa melakukan sesuatu seperti rata-rata baris untuk mengurangi ke nilai n dan fungsi lebih dari itu untuk mendapatkan satu nilai tunggal.


1

Saya telah memiliki banyak keberuntungan dengan gambar jpg yang diambil dengan kamera yang sama pada tripod dengan (1) sangat menyederhanakan (seperti pergi dari lebar 3000 piksel ke lebar 100 piksel atau bahkan lebih sedikit) (2) meratakan setiap jpg array menjadi satu vektor (3) gambar sekuensial berkorelasi berpasangan dengan algoritma korelasi sederhana untuk mendapatkan koefisien korelasi (4) kuadrat koefisien korelasi untuk mendapatkan r-square (yaitu fraksi variabilitas dalam satu gambar dijelaskan oleh variasi di gambar berikutnya) (5) umumnya dalam aplikasi saya jika r-square <0,9, saya katakan dua gambar berbeda dan sesuatu terjadi di antaranya.

Ini kuat dan cepat dalam implementasi saya (Mathematica 7)

Sebaiknya Anda bermain-main dengan bagian gambar yang Anda minati dan memusatkan perhatian pada hal itu dengan memangkas semua gambar ke area kecil itu, jika tidak, jauh dari kamera tetapi perubahan penting akan terlewatkan.

Saya tidak tahu cara menggunakan Python, tetapi saya yakin itu berkorelasi juga, bukan?


1

Anda dapat menghitung histogram dari kedua gambar dan kemudian menghitung Koefisien Bhattacharyya , ini adalah algoritma yang sangat cepat dan saya telah menggunakannya untuk mendeteksi perubahan bidikan dalam video kriket (dalam C menggunakan openCV)


Bisakah Anda menghitung koefisien pada gambar itu sendiri?
endolith

Anda harus menghitung histogram untuk gambar (dengan ukuran nampan histogram sesuai persyaratan).
vishalv2050

1

Lihatlah bagaimana Haar Wavelets diimplementasikan oleh isk-daemon . Anda dapat menggunakannya dengan kode imgdb C ++ untuk menghitung perbedaan antara gambar secara langsung:

isk-daemon adalah server database sumber terbuka yang mampu menambahkan pencarian gambar berbasis konten (visual) ke situs web atau perangkat lunak terkait gambar.

Teknologi ini memungkinkan pengguna situs web atau perangkat lunak terkait gambar untuk membuat sketsa di widget gambar mana yang ingin mereka temukan dan membuat situs web membalas gambar yang paling mirip atau meminta lebih banyak foto serupa di setiap halaman detail gambar.


1

Saya memiliki masalah yang sama dan menulis modul python sederhana yang membandingkan dua gambar berukuran sama menggunakan ImageChops bantal untuk membuat gambar diff hitam / putih dan merangkum nilai histogram.

Anda bisa mendapatkan skor ini secara langsung, atau nilai persentase dibandingkan dengan perbedaan hitam penuh vs putih.

Ini juga berisi fungsi is_equal sederhana, dengan kemungkinan untuk memasok ambang fuzzy di bawah (dan termasuk) gambar melewati sama.

Pendekatannya tidak terlalu rumit, tetapi mungkin berguna bagi orang lain di luar sana yang berjuang dengan masalah yang sama.

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


1

Pendekatan yang agak lebih berprinsip adalah menggunakan deskriptor global untuk membandingkan gambar, seperti GIST atau CENTRIST. Fungsi hash, seperti dijelaskan di sini , juga menyediakan solusi serupa.


1
import os
from PIL import Image
from PIL import ImageFile
import imagehash
  
#just use to the size diferent picture
def compare_image(img_file1, img_file2):
    if img_file1 == img_file2:
        return True
    fp1 = open(img_file1, 'rb')
    fp2 = open(img_file2, 'rb')

    img1 = Image.open(fp1)
    img2 = Image.open(fp2)

    ImageFile.LOAD_TRUNCATED_IMAGES = True
    b = img1 == img2

    fp1.close()
    fp2.close()

    return b





#through picturu hash to compare
def get_hash_dict(dir):
    hash_dict = {}
    image_quantity = 0
    for _, _, files in os.walk(dir):
        for i, fileName in enumerate(files):
            with open(dir + fileName, 'rb') as fp:
                hash_dict[dir + fileName] = imagehash.average_hash(Image.open(fp))
                image_quantity += 1

    return hash_dict, image_quantity

def compare_image_with_hash(image_file_name_1, image_file_name_2, max_dif=0):
    """
    max_dif: The maximum hash difference is allowed, the smaller and more accurate, the minimum is 0.
    recommend to use
    """
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    hash_1 = None
    hash_2 = None
    with open(image_file_name_1, 'rb') as fp:
        hash_1 = imagehash.average_hash(Image.open(fp))
    with open(image_file_name_2, 'rb') as fp:
        hash_2 = imagehash.average_hash(Image.open(fp))
    dif = hash_1 - hash_2
    if dif < 0:
        dif = -dif
    if dif <= max_dif:
        return True
    else:
        return False


def compare_image_dir_with_hash(dir_1, dir_2, max_dif=0):
    """
    max_dif: The maximum hash difference is allowed, the smaller and more accurate, the minimum is 0.

    """
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    hash_dict_1, image_quantity_1 = get_hash_dict(dir_1)
    hash_dict_2, image_quantity_2 = get_hash_dict(dir_2)

    if image_quantity_1 > image_quantity_2:
        tmp = image_quantity_1
        image_quantity_1 = image_quantity_2
        image_quantity_2 = tmp

        tmp = hash_dict_1
        hash_dict_1 = hash_dict_2
        hash_dict_2 = tmp

    result_dict = {}

    for k in hash_dict_1.keys():
        result_dict[k] = None

    for dif_i in range(0, max_dif + 1):
        have_none = False

        for k_1 in result_dict.keys():
            if result_dict.get(k_1) is None:
                have_none = True

        if not have_none:
            return result_dict

        for k_1, v_1 in hash_dict_1.items():
            for k_2, v_2 in hash_dict_2.items():
                sub = (v_1 - v_2)
                if sub < 0:
                    sub = -sub
                if sub == dif_i and result_dict.get(k_1) is None:
                    result_dict[k_1] = k_2
                    break
    return result_dict


def main():
    print(compare_image('image1\\815.jpg', 'image2\\5.jpg'))
    print(compare_image_with_hash('image1\\815.jpg', 'image2\\5.jpg', 7))
    r = compare_image_dir_with_hash('image1\\', 'image2\\', 10)
    for k in r.keys():
        print(k, r.get(k))


if __name__ == '__main__':
    main()
  • keluaran:

    Salah
    Benar
    image2 \ 5.jpg image1 \ 815.jpg
    image2 \ 6.jpg image1 \ 819.jpg
    image2 \ 7.jpg image1 \ 900.jpg
    image2 \ 8.jpg image1 \ 998.jpg
    image2 \ 9.jpg image1 \ 1012 .jpg

  • contoh gambar:

    • 815.jpg
      815.jpg

    • 5.jpg
      5.jpg


0

Saya pikir Anda bisa menghitung jarak euclidean (yaitu sqrt (jumlah kuadrat perbedaan, piksel demi piksel)) antara luminansi dua gambar, dan menganggapnya sama jika ini berada di bawah ambang empiris. Dan Anda lebih baik melakukannya dengan membungkus fungsi C.


0

Ada banyak metrik di luar sana untuk mengevaluasi apakah dua gambar terlihat seperti / seberapa mirip.

Saya tidak akan membahas kode apa pun di sini, karena saya pikir itu harus menjadi masalah ilmiah, selain masalah teknis.

Secara umum, pertanyaan tersebut terkait dengan persepsi manusia tentang gambar, sehingga masing-masing algoritma memiliki dukungan pada ciri-ciri sistem visual manusia.

Pendekatan klasik adalah:

Prediktor perbedaan yang terlihat: algoritme untuk penilaian kesetiaan gambar ( https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1666/0000/Visible-differences-predictor--an-algorithm-for-the- penilaian-of / 10.1117 / 12.135952.short? SSO = 1 )

Penilaian Kualitas Gambar: Dari Visibilitas Kesalahan hingga Kesamaan Struktural ( http://www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf )

FSIM: Indeks Kesamaan Fitur untuk Penilaian Kualitas Gambar ( https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf )

Di antara mereka, SSIM (Penilaian Kualitas Gambar: Dari Visibilitas Kesalahan ke Kesamaan Struktural) adalah yang termudah untuk dihitung dan biaya overhead juga kecil, seperti yang dilaporkan dalam makalah lain "Penilaian Kualitas Gambar Berdasarkan Kemiripan Gradien" ( https: //www.semanticscholar .org / kertas / Gambar-Penilaian-Kualitas-Berbasis-Gradien-Liu-Lin / 2b819bef80c02d5d4cb56f27b202535e119df988 ).

Ada banyak lagi pendekatan lain. Lihatlah Google Cendekia dan cari sesuatu seperti "perbedaan visual", "penilaian kualitas gambar", dll, jika Anda tertarik / benar-benar peduli pada seni.


0

Ada solusi sederhana dan cepat menggunakan numpy dengan menghitung mean squared error:

before = np.array(get_picture())
while True:
    now = np.array(get_picture())
    MSE = np.mean((now - before)**2)

    if  MSE > threshold:
        break

    before = now
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.