Di bawah ini adalah tiga pendekatan untuk menyelesaikan masalah ini (dan ada banyak lainnya).
Yang pertama adalah pendekatan standar dalam visi komputer, pencocokan titik kunci. Ini mungkin memerlukan beberapa latar belakang pengetahuan untuk diimplementasikan, dan bisa lambat.
Metode kedua hanya menggunakan pemrosesan gambar dasar, dan berpotensi lebih cepat daripada pendekatan pertama, dan mudah untuk diterapkan. Namun, apa yang diperolehnya dalam pemahaman, tidak memiliki ketahanan - pencocokan gagal pada gambar yang diskalakan, diputar, atau berubah warna.
Metode ketiga cepat dan kuat, tetapi berpotensi yang paling sulit untuk diterapkan.
Pencocokan Keypoint
Lebih baik daripada memilih 100 poin acak adalah memilih 100 poin penting . Bagian-bagian tertentu dari suatu gambar memiliki lebih banyak informasi daripada yang lain (terutama di bagian tepi dan sudut), dan ini adalah yang Anda ingin gunakan untuk pencocokan gambar yang cerdas. Google " ekstraksi keypoint " dan " pencocokan keypoint " dan Anda akan menemukan beberapa makalah akademis tentang subjek ini. Saat ini, titik kunci SIFT bisa dibilang yang paling populer, karena mereka dapat mencocokkan gambar di bawah skala, rotasi, dan pencahayaan yang berbeda. Beberapa implementasi SIFT dapat ditemukan di sini .
Satu kelemahan untuk pencocokan titik kunci adalah waktu berjalan dari implementasi naif: O (n ^ 2m), di mana n adalah jumlah titik kunci dalam setiap gambar, dan m adalah jumlah gambar dalam database. Beberapa algoritma pintar mungkin menemukan kecocokan terdekat lebih cepat, seperti quadtrees atau partisi ruang biner.
Solusi alternatif: Metode histogram
Solusi lain yang kurang kuat tetapi berpotensi lebih cepat adalah membangun histogram fitur untuk setiap gambar, dan memilih gambar dengan histogram yang paling dekat dengan histogram gambar input. Saya menerapkan ini sebagai undergrad, dan kami menggunakan 3 histogram warna (merah, hijau, dan biru), dan dua histogram tekstur, arah dan skala. Saya akan memberikan detail di bawah ini, tetapi saya harus perhatikan bahwa ini hanya bekerja dengan baik untuk mencocokkan gambar yang SANGAT mirip dengan gambar basis data. Gambar skala ulang, diputar, atau berubah warna bisa gagal dengan metode ini, tetapi perubahan kecil seperti memotong tidak akan merusak algoritme
Menghitung histogram warna sangatlah mudah - cukup pilih rentang untuk kotak histogram Anda, dan untuk setiap rentang, hitung jumlah piksel dengan warna dalam rentang itu. Sebagai contoh, perhatikan histogram "hijau", dan anggaplah kita memilih 4 ember untuk histogram kami: 0-63, 64-127, 128-191, dan 192-255. Kemudian untuk setiap piksel, kita melihat nilai hijau, dan menambahkan penghitungan ke ember yang sesuai. Setelah selesai menghitung, kami membagi setiap ember dengan jumlah piksel di seluruh gambar untuk mendapatkan histogram yang dinormalisasi untuk saluran hijau.
Untuk histogram arah tekstur, kami mulai dengan melakukan deteksi tepi pada gambar. Setiap titik tepi memiliki vektor normal yang menunjuk ke arah tegak lurus terhadap tepi. Kami menghitung sudut vektor normal menjadi salah satu dari 6 ember antara 0 dan PI (karena tepi memiliki simetri 180 derajat, kami mengonversi sudut antara -PI dan 0 menjadi antara 0 dan PI). Setelah menghitung jumlah titik tepi di setiap arah, kami memiliki histogram yang tidak dinormalisasi yang mewakili arah tekstur, yang kami normalkan dengan membagi setiap ember dengan jumlah total titik tepi pada gambar.
Untuk menghitung histogram skala tekstur, untuk setiap titik tepi, kami mengukur jarak ke titik tepi terdekat berikutnya dengan arah yang sama. Misalnya, jika titik tepi A memiliki arah 45 derajat, algoritma berjalan ke arah itu sampai menemukan titik tepi lain dengan arah 45 derajat (atau dalam deviasi yang masuk akal). Setelah menghitung jarak ini untuk setiap titik tepi, kami membuang nilai-nilai tersebut ke dalam histogram dan menormalkannya dengan membaginya dengan jumlah total titik tepi.
Sekarang Anda memiliki 5 histogram untuk setiap gambar. Untuk membandingkan dua gambar, Anda mengambil nilai absolut dari perbedaan antara setiap kotak histogram, dan kemudian menjumlahkan nilai-nilai ini. Misalnya, untuk membandingkan gambar A dan B, kami akan menghitung
|A.green_histogram.bucket_1 - B.green_histogram.bucket_1|
untuk setiap ember dalam histogram hijau, dan ulangi untuk histogram lainnya, lalu jumlahkan semua hasilnya. Semakin kecil hasilnya, semakin baik pertandingan. Ulangi untuk semua gambar dalam basis data, dan kecocokan dengan hasil terkecil menang. Anda mungkin ingin memiliki ambang, di atas mana algoritma menyimpulkan bahwa tidak ada kecocokan yang ditemukan.
Pilihan Ketiga - Titik Puncak + Pohon Keputusan
Pendekatan ketiga yang mungkin jauh lebih cepat daripada dua lainnya adalah menggunakan hutan semantik texton (PDF). Ini melibatkan penggalian titik kunci sederhana dan menggunakan pohon keputusan koleksi untuk mengklasifikasikan gambar. Ini lebih cepat daripada pencocokan keypoint SIFT sederhana, karena menghindari proses pencocokan yang mahal, dan keypoint jauh lebih sederhana daripada SIFT, jadi ekstraksi keypoint jauh lebih cepat. Namun, ini mempertahankan invariansi metode SIFT untuk rotasi, skala, dan pencahayaan, fitur penting yang tidak dimiliki metode histogram.
Perbarui :
Kesalahan saya - makalah Semantic Texton Forests tidak secara khusus tentang pencocokan gambar, melainkan pelabelan wilayah. Makalah asli yang cocok adalah yang ini: Pengenalan Titik Puncak menggunakan Pohon Acak . Juga, makalah di bawah ini terus mengembangkan ide-ide dan mewakili keadaan seni (c. 2010):
Metode terbaik yang saya tahu adalah menggunakan Perceptual Hash. Tampaknya ada implementasi open source yang baik dari hash yang tersedia di:
http://phash.org/
Gagasan utamanya adalah bahwa setiap gambar direduksi menjadi kode hash kecil atau 'sidik jari' dengan mengidentifikasi fitur-fitur penting dalam file gambar asli dan membuat representasi yang ringkas dari fitur-fitur tersebut (daripada membuat data gambar secara langsung). Ini berarti bahwa tingkat positif palsu jauh berkurang melalui pendekatan sederhana seperti mengurangi gambar ke gambar berukuran sidik jari kecil dan membandingkan sidik jari.
phash menawarkan beberapa jenis hash dan dapat digunakan untuk gambar, audio atau video.
sumber
Posting ini adalah titik awal dari solusi saya, banyak ide bagus di sini jadi saya pikir saya akan membagikan hasil saya. Wawasan utama adalah bahwa saya telah menemukan cara untuk mengatasi lambatnya pencocokan gambar berbasis-titik kunci dengan memanfaatkan kecepatan phash.
Untuk solusi umum, sebaiknya gunakan beberapa strategi. Setiap algoritma paling cocok untuk jenis transformasi gambar tertentu dan Anda dapat memanfaatkannya.
Di atas, algoritma tercepat; di bagian bawah paling lambat (meski lebih akurat). Anda mungkin melewatkan yang lambat jika kecocokan yang baik ditemukan di tingkat yang lebih cepat.
Saya memiliki hasil yang sangat baik dengan phash. Akurasi bagus untuk gambar yang diperbesar ulang. Ini tidak baik untuk gambar yang dimodifikasi (secara persepsi) (dipotong, diputar, dicerminkan, dll). Untuk menangani kecepatan hashing, kita harus menggunakan cache disk / database untuk menjaga hash untuk tumpukan jerami.
Hal yang sangat baik tentang phash adalah bahwa begitu Anda membangun basis data hash Anda (yang bagi saya adalah sekitar 1000 gambar / detik), pencarian bisa sangat, sangat cepat, khususnya ketika Anda dapat menyimpan seluruh basis data hash di dalam memori. Ini cukup praktis karena hash hanya 8 byte.
Misalnya, jika Anda memiliki 1 juta gambar, itu akan memerlukan array 1 juta nilai hash 64-bit (8 MB). Pada beberapa CPU ini cocok dengan cache L2 / L3! Dalam penggunaan praktis saya telah melihat corei7 membandingkan lebih dari 1 Giga-hamm / detik, itu hanya masalah bandwidth memori ke CPU. Basis data 1 Miliar-gambar praktis pada CPU 64-bit (RAM 8 GB diperlukan) dan pencarian tidak akan melebihi 1 detik!
Untuk gambar yang dimodifikasi / dipangkas akan tampak fitur fitur-invarian / detektor kunci seperti SIFT adalah cara yang harus dilakukan. SIFT akan menghasilkan titik kunci yang baik yang akan mendeteksi crop / rotate / mirror dll. Namun perbandingan deskriptor sangat lambat dibandingkan dengan jarak tempuh yang digunakan oleh phash. Ini adalah batasan utama. Ada banyak perbandingan yang harus dilakukan, karena ada maksimum IxJxK deskriptor membandingkan untuk mencari satu gambar (I = num gambar tumpukan jerami, J = titik kunci target per gambar tumpukan jerami, K = titik kunci target per gambar jarum).
Untuk mengatasi masalah kecepatan, saya mencoba menggunakan phash di setiap titik kunci yang ditemukan, menggunakan ukuran fitur / radius untuk menentukan sub-persegi panjang. Trik untuk membuat ini bekerja dengan baik, adalah menumbuhkan / mengecilkan jari-jari untuk menghasilkan level sub-rect yang berbeda (pada gambar jarum). Biasanya level pertama (tidak berskala) akan cocok namun seringkali dibutuhkan beberapa kali lagi. Saya tidak 100% yakin mengapa ini bekerja, tapi saya bisa membayangkan itu mengaktifkan fitur yang terlalu kecil untuk phash untuk bekerja (phash skala gambar ke 32x32).
Masalah lainnya adalah SIFT tidak akan mendistribusikan keypoint secara optimal. Jika ada bagian gambar dengan banyak tepi, titik kunci akan mengelompok di sana dan Anda tidak akan mendapatkannya di area lain. Saya menggunakan GridAdaptedFeatureDetector di OpenCV untuk meningkatkan distribusi. Tidak yakin ukuran kisi apa yang terbaik, saya menggunakan kisi kecil (1x3 atau 3x1 tergantung pada orientasi gambar).
Anda mungkin ingin mengatur skala semua gambar tumpukan jerami (dan jarum) ke ukuran yang lebih kecil sebelum deteksi fitur (saya menggunakan 210px sepanjang dimensi maksimum). Ini akan mengurangi noise pada gambar (selalu menjadi masalah untuk algoritma visi komputer), juga akan memfokuskan detektor pada fitur yang lebih menonjol.
Untuk gambar orang, Anda dapat mencoba deteksi wajah dan menggunakannya untuk menentukan ukuran gambar yang akan diukur dan ukuran kisi (misalnya wajah dengan skala terbesar hingga 100px). Detektor fitur menyumbang berbagai tingkat skala (menggunakan piramida) tetapi ada batasan berapa banyak tingkat yang akan digunakan (ini tentu saja bisa disesuaikan).
Detektor keypoint mungkin bekerja paling baik ketika mengembalikan kurang dari jumlah fitur yang Anda inginkan. Misalnya, jika Anda meminta 400 dan mendapatkan 300 kembali, itu bagus. Jika Anda mendapatkan 400 kembali setiap kali, mungkin beberapa fitur bagus harus ditinggalkan.
Gambar jarum dapat memiliki titik kunci yang lebih sedikit daripada gambar tumpukan jerami dan masih mendapatkan hasil yang baik. Menambahkan lebih banyak tidak selalu memberi Anda keuntungan besar, misalnya dengan J = 400 dan K = 40 hit rate saya adalah sekitar 92%. Dengan J = 400 dan K = 400 hit rate hanya naik hingga 96%.
Kita dapat memanfaatkan kecepatan ekstrem fungsi hamming untuk menyelesaikan penskalaan, rotasi, mirroring dll. Teknik multi-pass dapat digunakan. Pada setiap iterasi, ubah sub-persegi panjang, ulang hash, dan jalankan fungsi pencarian lagi.
sumber
Seperti yang ditunjukkan oleh cartman, Anda dapat menggunakan segala jenis nilai hash untuk menemukan duplikat yang tepat.
Satu titik awal untuk menemukan gambar yang dekat bisa ada di sini . Ini adalah alat yang digunakan oleh perusahaan CG untuk memeriksa apakah gambar yang dirubah masih menunjukkan adegan yang sama.
sumber
Saya punya ide, yang dapat bekerja dan kemungkinan besar sangat cepat. Anda dapat melakukan sub-sampel gambar untuk mengatakan resolusi 80x60 atau sebanding, dan mengonversinya menjadi skala abu-abu (setelah subsampling akan lebih cepat). Memproses kedua gambar yang ingin Anda bandingkan. Kemudian jalankan jumlah normal dari perbedaan kuadrat antara dua gambar (gambar permintaan dan masing-masing dari db), atau yang lebih baik, Normalized Cross Correlation, yang memberikan respons lebih dekat ke 1, jika kedua gambar tersebut sama. Kemudian jika gambar serupa Anda dapat melanjutkan ke teknik yang lebih canggih untuk memverifikasi bahwa itu adalah gambar yang sama. Jelas algoritma ini linier dalam hal jumlah gambar dalam database Anda sehingga meskipun akan sangat cepat hingga 10.000 gambar per detik pada perangkat keras modern. Jika Anda memerlukan invarian untuk rotasi, maka gradien dominan dapat dihitung untuk gambar kecil ini, dan kemudian seluruh sistem koordinat dapat diputar ke orientasi kanonik, meskipun ini, akan lebih lambat. Dan tidak, tidak ada invariansi untuk skala di sini.
Jika Anda menginginkan sesuatu yang lebih umum atau menggunakan basis data besar (jutaan gambar), maka Anda perlu melihat ke dalam teori pengambilan gambar (banyak makalah yang muncul dalam 5 tahun terakhir). Ada beberapa petunjuk dalam jawaban lain. Tapi itu mungkin berlebihan, dan pendekatan histogram menyarankan akan melakukan pekerjaan. Meskipun saya akan berpikir kombinasi dari berbagai pendekatan cepat akan lebih baik.
sumber
Perusahaan saya memiliki sekitar 24 juta gambar yang masuk dari produsen setiap bulan. Saya mencari solusi cepat untuk memastikan bahwa gambar yang kami unggah ke katalog kami adalah gambar baru .
Saya ingin mengatakan bahwa saya telah mencari di internet jauh dan luas untuk mencoba menemukan solusi yang ideal. Saya bahkan mengembangkan algoritma deteksi tepi saya sendiri.
Saya telah mengevaluasi kecepatan dan akurasi beberapa model. Gambar saya, yang memiliki latar belakang putih, bekerja sangat baik dengan phashing. Seperti kata redcalx , saya merekomendasikan phash atau ahash. JANGAN gunakan Hashing MD5 atau hash kriptografis lainnya. Kecuali, Anda hanya menginginkan pencocokan gambar EXACT. Setiap pengubahan ukuran atau manipulasi yang terjadi di antara gambar akan menghasilkan hash yang berbeda.
Untuk phash / ahash, Lihat ini: imagehash
Saya ingin memperpanjang posting * redcalx dengan memposting kode dan keakuratan saya.
Apa yang saya lakukan:
Inilah beberapa hasil saya:
Semoga ini membantu!
sumber
Saya percaya bahwa menurunkan ukuran gambar ke ukuran hampir ikon, katakanlah 48x48, lalu mengonversi ke skala abu-abu, lalu mengambil perbedaan antara piksel, atau Delta, harus bekerja dengan baik. Karena kami membandingkan perubahan warna piksel, daripada warna piksel sebenarnya, tidak masalah jika gambarnya sedikit lebih terang atau lebih gelap. Perubahan besar akan berpengaruh karena piksel yang terlalu terang / gelap akan hilang. Anda dapat menerapkan ini di satu baris, atau sebanyak yang Anda inginkan untuk meningkatkan akurasi. Paling banyak Anda akan memiliki 47x47 = 2.209 pengurangan untuk membuat untuk membentuk Kunci yang sebanding.
sumber
Memilih 100 poin acak bisa berarti bahwa gambar yang serupa (atau kadang-kadang bahkan berbeda) akan ditandai sebagai sama, yang saya anggap bukan yang Anda inginkan. Hash MD5 tidak akan berfungsi jika gambar format yang berbeda (png, jpeg, dll), memiliki ukuran yang berbeda, atau memiliki metadata yang berbeda. Mengurangi semua gambar ke ukuran yang lebih kecil adalah taruhan yang baik, melakukan perbandingan piksel-untuk-piksel tidak boleh terlalu lama selama Anda menggunakan pustaka gambar / bahasa cepat yang baik, dan ukurannya cukup kecil.
Anda dapat mencoba membuatnya kecil, kemudian jika mereka melakukan perbandingan yang sama pada ukuran yang lebih besar - bisa menjadi kombinasi yang baik antara kecepatan dan akurasi ...
sumber
Jika Anda memiliki banyak gambar, lihat ke filter Bloom , yang menggunakan banyak hash untuk hasil yang probablistik namun efisien. Jika jumlah gambar tidak besar, maka hash kriptografis seperti md5 harus memadai.
sumber