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. img1
dan img2
adalah 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, imread
mengembalikan 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]. arr
adalah 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 main
fungsinya:
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 cv2
modul 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:
di mana p dan q adalah histogram dari frame yang digunakan. Ambang ditetapkan pada 0,2.