Contoh penggunaan ImageMagick -- perbandingan gambar
- Kata pengantar dan indeks contoh penggunaan ImageMagick
- Metode membandingkan gambar -- apa yang berbeda?
- Program compare
- Gambar selisih
- Perbandingan flicker
-
Statistik perbandingan -- seberapa berbeda? Pencocokan dan pelacakan sub-gambar Menemukan gambar kecil di dalam gambar yang lebih besar. Menemukan gambar duplikat -- menemukan dua gambar yang sama Mengelompokkan gambar berdasarkan tipe -- klasifikasi gambar untuk perbandingan
- Warna linear
- Hitam putih murni
- Gambar berwarna
- Berwarna midtone
- Teks vs gambar garis
-
Menangani tipe gambar tertentu Metrik gambar -- membuat sidik jari gambar untuk perbandingan Kamera web -- menemukan apa yang berubah pada kamera tetap Kemampuan membandingkan dua gambar atau lebih, atau menemukan gambar duplikat di dalam koleksi yang besar, adalah perkara yang sangat rumit. Pada contoh-contoh ini kita melihat cara membandingkan gambar untuk menentukan seberapa mirip gambar-gambar itu, dan di bagian mana bedanya. Ini bisa melibatkan pengklasifikasian atau pengelompokan gambar ke dalam berbagai tipe agar lebih mudah ditangani. Menemukan semacam metrik untuk menyederhanakan dan mengelompokkan gambar yang mirip. Lalu melakukan clustering terhadap gambar-gambar serupa berdasarkan metrik semacam itu. Namun perbandingan, dan atau kajian semacam ini, meski sulit bisa berbuah manis, karena membuka kemampuan menemukan duplikat dan salinan gambar, bahkan menghapus 'spam' atau teks dan pemberitahuan lain dari gambar.
Metode membandingkan gambar
Program compare
Program "magick compare" disediakan sebagai cara mudah membandingkan dua gambar yang mirip, untuk menentukan seberapa 'berbeda' kedua gambar itu. Sebagai contoh, di sini saya punya dua frame dari animasi 'bag', yang lalu saya berikan ke "magick compare' untuk menyorot area yang berubah.
magick compare bag_frame1.gif bag_frame2.gif compare.gif
Seperti terlihat, hasilnya adalah gambar putih dan merah yang di dalamnya ada 'bayangan' gambar kedua. Terlihat jelas ada tiga area yang berubah di antara kedua gambar. Alih-alih menyimpan gambar 'compare' itu, tentu saja gambarnya bisa langsung dilihat, cara yang menurut saya lebih praktis, dengan mengeluarkannya ke format keluaran khusus "x:", atau dengan program "display". Sebagai contoh..
magick compare bag_frame1.gif bag_frame2.gif x:
magick compare bag_frame1.gif bag_frame2.gif miff:- | display
Sejak IM v6.4 warna selisih bisa diubah dari merah ke warna lain yang lebih menarik... |
magick compare bag_frame1.gif bag_frame2.gif \
-highlight-color SeaGreen compare_color.gif
![[IM Output]](../static/img/compare/compare_color.gif)
Sejak IM v6.4.2-8 warna satunya juga bisa ditentukan. |
magick compare bag_frame1.gif bag_frame2.gif \
-highlight-color SeaGreen -lowlight-color PaleGreen \
compare_colors.gif
![[IM Output]](../static/img/compare/compare_colors.gif)
Kalau 'bayangan' gambar kedua itu tidak dikehendaki, sejak IM v6.4.2-8 tambahkan saja "-compose src" pada opsinya untuk membuangnya. |
magick compare bag_frame1.gif bag_frame2.gif \
-compose Src compare_src.gif
![[IM Output]](../static/img/compare/compare_src.gif)
Dengan memakai ketiga pengaturan (setting) tambahan itu kita bisa menghasilkan mask grayscale dari piksel-piksel yang berubah... |
magick compare bag_frame1.gif bag_frame2.gif \
-compose Src -highlight-color White -lowlight-color Black \
compare_mask.gif
![[IM Output]](../static/img/compare/compare_mask.gif)
Perhatikan bahwa mask ini mencakup SEMUA selisih, sekecil apa pun. Sebagai contoh, semua selisih kecil yang timbul karena menyimpan gambar ke format file JPEG yang lossy pun terlihat...
magick bag_frame1.gif bag_frame1.jpg
magick compare bag_frame1.gif bag_frame1.jpg compare_lossy_jpeg.gif
Seperti terlihat, walau selisih antara versi GIF dan versi JPEG gambar itu praktis tidak kasat mata, "magick compare" melaporkan banyak sekali selisih. Dengan faktor fuzz yang kecil, IM bisa diminta mengabaikan selisih-selisih kecil antara kedua gambar itu. |
magick compare -metric AE -fuzz 5% \
bag_frame1.gif bag_frame1.jpg compare_fuzz.gif
![[IM Text]](../static/img/compare/compare_fuzz.txt.gif)
![[IM Output]](../static/img/compare/compare_fuzz.gif)
Hasilnya menunjukkan bahwa sebagian besar selisih yang ada memang hanya kecil. Pengaturan (setting) khusus "-metric" bernilai 'AE' (singkatan dari "Absolute Error", cacah error mutlak) akan melaporkan (ke standard error) cacah piksel yang benar-benar di-mask pada faktor fuzz saat itu.
Gambar selisih
Untuk mendapat gambaran yang lebih baik tentang seberapa jauh kedua gambar berbeda, biasanya lebih baik membuat gambar komposisi 'difference' yang lebih tepat.... |
magick composite bag_frame1.gif bag_frame1.jpg \
-compose difference difference_jpeg.gif
![[IM Output]](../static/img/compare/difference_jpeg.gif)
Seperti terlihat, meski "magick compare" menunjukkan bahwa JPEG menimbulkan banyak selisih antara kedua gambar, komposisi 'difference' hasilnya cukup gelap, yang menandakan bahwa semua selisih itu relatif kecil. Kalau gambar hasilnya terlalu hitam sehingga selisihnya sulit dilihat, gambar itu bisa dinormalisasi (dengan "-auto-level" yang secara matematis lebih benar) supaya hasilnya lebih menonjol. |
magick difference_jpeg.gif -auto-level difference_norm.gif
![[IM Output]](../static/img/compare/difference_norm.gif)
Ini masih menunjukkan bahwa sebagian besar selisihnya sangat kecil, dengan selisih terbesar muncul di sepanjang tepi tajam gambar, bagian yang memang tidak ditangani dengan baik oleh format file gambar JPEG. Sebaliknya, gambar selisih antara kedua frame asli animasi tadi memperlihatkan perbedaan yang sangat mencolok di antara keduanya, bahkan tanpa penguatan apa pun. |
magick composite bag_frame1.gif bag_frame2.gif \
-compose difference difference_frames.gif
![[IM Output]](../static/img/compare/difference_frames.gif)
Perhatikan bahwa karena metode compose 'difference' bersifat asosiatif, urutan kedua gambar pada contoh-contoh di atas tidak jadi soal, meskipun berbeda dengan "magick compare", di sini gambar berukuran berbeda pun bisa dibandingkan, dan gambar tujuanlah yang menentukan ukuran akhir gambar selisihnya. Metode difference ini bahkan lebih berguna lagi bila dipakai bersama program "magick", karena gambar hasilnya masih bisa diproses lebih lanjut sebelum disimpan atau ditampilkan. Sebagai contoh, tiap kanal warna bisa di-threshold lalu digabungkan untuk menghasilkan mask dari setiap piksel yang berubah warna di antara kedua gambar. |
magick bag_frame1.gif bag_frame2.gif -compose difference -composite \
-threhold 0 -separate -evaluate-sequence Add \
difference_mask.gif
![[IM Output]](../static/img/compare/difference_mask.gif)
Pada dasarnya inilah yang dikerjakan program "magick compare", hanya saja dengan kendali lebih banyak atas warna dan gaya keluarannya. Namun seperti terlihat, cara ini cenderung menemukan perubahan sekecil apa pun di antara dua gambar. Kalau gambarnya berasal dari format file gambar yang lossy seperti JPEG, atau gambar GIF yang perlu pengurangan warna dan dithering (kuantisasi warna), hampir seluruh isi gambar kemungkinan akan tertandai. Karena itu cara ini biasanya kurang berguna. Untuk hasil yang lebih baik, coba cari tahu seberapa jauh sebenarnya warna pikselnya berbeda. Sebagai contoh, hasilnya bisa kita jadikan grayscale supaya diperoleh gambar perbandingan yang lebih terbaca ketimbang yang penuh warna. |
magick bag_frame1.gif bag_frame2.gif -compose difference -composite \
-colorspace Gray difference_gray.gif
![[IM Output]](../static/img/compare/difference_gray.gif)
Berbeda dengan "magick compare", gambar selisih memperlihatkan campuran kedua gambar yang menyatu dalam hasil akhirnya. Lihat misalnya 'jimat' aneh yang seolah muncul di dahi kucing itu. Aslinya itu adalah pegangan tas dari gambar pertama. Percampuran semacam ini bisa membingungkan, karena selisih mana persisnya yang sedang dilihat menjadi kabur: yang tampak adalah gabungan dari yang ditambahkan sekaligus yang dihilangkan dari gambar. Karena kekaburan detail inilah "magick compare" biasanya lebih enak dilihat oleh mata manusia, sedangkan gambar 'difference' lebih cocok untuk pemrosesan gambar lebih lanjut. Namun meng-grayscale-kan gambar selisih hanya akan merata-ratakan (sebenarnya rata-rata berbobot) jarak RGB-nya. Akibatnya selisih warna sebesar satu bit bisa hilang karena Efek kuantum, non-HDRI vs HDRI. Kalau selisih sekecil apa pun antara gambar itu penting, cara yang lebih baik adalah menjumlahkan kanal-kanal warna terpisah dari gambar selisih, supaya SEMUA selisih tertangkap, termasuk yang paling kecil. |
magick bag_frame1.gif bag_frame2.gif -compose difference -composite \
-separate -evaluate-sequence add difference_add.gif
![[IM Output]](../static/img/compare/difference_add.gif)
Nilai selisih yang dihasilkan di atas dikenal sebagai metrik 'manhattan distance'. Yaitu jarak antara kedua warna dari masing-masing gambar bila gerakannya dibatasi pada arah ortogonal (atau aksial) saja. Namun hati-hati, selisih yang besar bisa terpotong (atau 'terbakar') karena nilainya dapat melampaui 'Quantum Range' data piksel, atau batas bilangan bulat, kecuali bila memakai IM versi HDRI. Lebih jauh lagi, jarak vektor warna bisa diperoleh dengan memakai kuadrat dan akar kuadrat untuk mewujudkan jarak Pythagoras atau Euclid. |
magick bag_frame1.gif bag_frame2.gif -compose difference -composite \
-evaluate Pow 2 -separate -evaluate-sequence Add -evaluate Pow 0.5 \
difference_vector.gif
![[IM Output]](../static/img/compare/difference_vector.gif)
Ini sebenarnya mirip dengan apa yang diukur faktor 'fuzz' sebagai bagian dari proses thresholding-nya (bila transparansi tidak terlibat). Namun 'fuzz' juga membagi nilai kuadratnya dengan 3 sebelum dijumlahkan, supaya hasilnya tidak melampaui batas rentang warna gambar. Dengan begitu piksel 'putih' murni hanya muncul pada hasil untuk selisih antara warna primer dan sekunder yang berlawanan, misalnya antara piksel biru dan kuning. Jadi mari kita lakukan penskalaan itu juga... |
magick bag_frame1.gif bag_frame2.gif -compose difference -composite \
-evaluate Pow 2 -evaluate divide 3 -separate \
-evaluate-sequence Add -evaluate Pow 0.5 \
difference_vector_scaled.gif
![[IM Output]](../static/img/compare/difference_vector_scaled.gif)
Hasilnya sebenarnya sangat mirip dengan gambar selisih "-colorspace Gray' (seperti di atas), tetapi merupakan representasi selisih warna yang jauh lebih akurat. Modifikasi 'Pow 0.5' yang kedua boleh saja dihilangkan, dan hasilnya adalah gambar selisih kuadrat. Ada metrik jarak warna lain, yang bisa dibaca di halaman Color Difference, Wikipedia. Sebagian besar di antaranya juga menghasilkan selisih vektor (seperti yang terakhir tadi) tetapi memakai ruang warna lain, seperti LAB atau LUV. Hal ini lebih penting untuk membandingkan selisih warna di dunia nyata (misalnya ukuran selisih menurut penglihatan manusia). Lihat juga Penghapusan latar belakang, yang memakai gambar selisih seperti di atas untuk menghapus latar belakang. Anda mungkin juga tertarik melihat halaman luar tentang Change Detection sebagai contoh penerapan praktisnya.
Perbandingan flicker
Alternatif lain selain program "magick compare" untuk melihat selisih antar gambar adalah melakukan perbandingan flicker antara gambar-gambar yang mirip pada laju yang cukup cepat. |
magick -delay 50 bag_frame1.gif bag_frame2.gif -loop 0 flicker_cmp.gif
![[IM Output]](../static/img/compare/flicker_cmp.gif)
Supaya lebih mudah, saya menulis skrip bernama "**flicker_cmp**" untuk menampilkan animasi dari dua gambar yang diberikan, yang berganti-ganti di antara keduanya persis seperti contoh di atas. Skrip itu juga menambahkan label di bagian bawah gambar yang ditampilkan supaya jelas gambar mana yang sedang Anda lihat pada saat itu.
Membandingkan animasi
Selisih antara dua animasi yang sudah di-coalesce juga bisa dibandingkan dengan teknik 'film strip' khusus. Lihat teknik 'append' serupa di Penyambungan berdampingan. Pada dasarnya kita menyambung semua frame animasi menjadi satu gambar yang besar dan panjang. Kedua gambar itu lalu dibandingkan, dan animasi baru dibuat dengan memecah kembali hasilnya menjadi frame-frame terpisah. Sebagai contoh...
magick \( anim1.gif -coalesce -append \) \
\( anim2.gif -coalesce -append \) miff:- | \
magick compare - miff:- |\
magick - -crop 160x120 +repage anim_compare.gif
Hasilnya adalah animasi dari gambar-gambar 'compare', yaitu versi 'redup' dari animasi kedua yang ditimpa sorotan yang menunjukkan bagian-bagian yang berbeda. Perhatikan bahwa agar ini berhasil, ukuran "-crop" harus sama dengan ukuran asli animasinya. Animasi itu juga akan kehilangan jeda (delay) waktu yang bervariasi bila sebelumnya ada, dan menggantinya dengan jeda waktu tetap berdasarkan frame pertama animasi aslinya. Teknik perbandingan gambar lain yang berguna untuk animasi dipakai untuk menemukan semua area tempat animasi berubah, sehingga bagian-bagian animasi yang tidak saling terhubung bisa dipisahkan. Dengan cara ini animasi besar bisa dipecah menjadi beberapa animasi yang lebih kecil. Lihat Memecah sebuah animasi.
Statistik perbandingan Seberapa berbeda sebenarnya dua gambar?
Sedang dikerjakan
Statistik dari gambar selisih...
Perintah berikut mengeluarkan informasi verbose dan mengambil hanya
bagian yang berisi statistik kanal dari gambar tersebut....
magick image1 image2 -compose Difference -composite \
-colorspace gray -verbose info: |\
sed -n '/statistics:/,/^ [^ ]/ p'
Angka dalam tanda kurung (bila ada) adalah nilai ternormalisasi antara
nol dan satu, sehingga tidak bergantung pada level Q dari IM Anda.
Kalau angka-angka ini tidak muncul, sebaiknya pertimbangkan memutakhirkan IM Anda.
Untuk mendapatkan level abu-abu rata-rata (mean) sebagai persentase, pakai
perintah ini...
magick image1 image2 -compose Difference -composite \
-colorspace gray -format '%[fx:mean*100]' info:
Kalau tidak perlu persentase, ada yang lebih sederhana lagi..
magick image1 image2 -compose Difference -composite \
-colorspace gray -format '%[mean]' info:
Statistik program compare...
Nilai selisih rata-rata yang sebenarnya bisa diperoleh dengan -metric
magick compare -metric MAE image1 image2 null: 2>&1
Menambahkan -verbose akan memberikan informasi lebih rinci tentang setiap
kanal secara terpisah.
magick compare -verbose -metric MAE rose.jpg reconstruct.jpg null: 2>&1
Image: rose.jpg
Channel distortion: MAE
red: 1884 (0.028748)
green: 1532.34 (0.023382)
blue: 1691.25 (0.0258068)
all: 1702.53 (0.025979)
Ada sejumlah metrik berbeda yang bisa dipilih.
Dengan set gambar uji yang sama (kurang lebih sama)
Jumlah piksel
AE ...... Absolute Error, cacah piksel yang berbeda (0=sama)
Nilai ini bisa di-threshold dengan pengaturan -fuzz supaya
hanya piksel yang selisihnya melebihi ambang batas yang dihitung.
Sejak IM v6.4.3 cacah -metric AE dipengaruhi -fuzz,
sehingga selisih 'kecil' bisa dikeluarkan dari cacah ini.
magick -metric AE -fuzz 10% image1.png image2.png null:
Piksel mana saja yang berbeda bisa dilihat lewat gambar
keluarannya (diabaikan pada perintah di atas).
Ini SATU-SATUNYA metrik yang dipengaruhi 'fuzz'.
Error maksimum (dari satu piksel mana pun)
PAE ..... Peak Absolute Error (dalam satu kanal, untuk ruang warna 3D)
PSNR .... Peak Signal to noise ratio (dipakai dalam paper kompresi gambar)
Rasio antara selisih kuadrat rata-rata dan kuadrat rata-rata maksimum
yang mungkin ada di antara dua gambar mana pun, dinyatakan sebagai
nilai desibel.
Makin tinggi PSNR, makin mirip kedua gambar itu, dengan
selisih maksimum terjadi pada nilai 1. PSNR 20 berarti
selisihnya 1/100 dari maksimum.
Error rata-rata (atas seluruh piksel)
MAE ..... Mean absolute error (rata-rata jarak error kanal)
MSE ..... Mean squared error (rata-rata jarak error kuadrat)
RMSE .... (sq)root mean squared error -- yaitu: sqrt(MSE)
Metrik khusus
MEPP .... Normalized Mean Error DAN Normalized Maximum Error
Keduanya semestinya berkaitan langsung dengan faktor '-fuzz',
untuk gambar tanpa transparansi.
Dengan transparansi hal ini jadi sulit, sebab mask semestinya
mempengaruhi jumlah piksel yang dibandingkan, dan karenanya 'mean'-nya,
tetapi saat ini hal itu belum dikerjakan.
FUZZ selisih faktor fuzz dengan memperhitungkan transparansi
NCC normalized cross correlation (1 = mirip)
Saya memperoleh hasil berikut pada gambar-gambar uji saya...
_metric_|__low_Q_jpeg__|__black_vs_white__
PSNR | 29.6504 | 0
PAE | 63479 | 65535
MAE | 137.478 | 65535
MSE | 4.65489e+06 | 4.29484e+09
RMSE | 2157.52 | 65535
Kolom angka pertama adalah perbandingan gambar dengan selisih akibat JPEG
berkualitas rendah: gambar uji dibaca lalu disimpan kembali dengan pengaturan
-quality yang sangat rendah.
Yang kedua, "black vs white", adalah perbandingan gambar hitam polos dengan
gambar putih polos. Kalau 'warna rata-rata' gambar diabaikan oleh
perbandingan itu, nilai hasilnya akan sangat kecil. Tampaknya ini
hanya terjadi pada metrik PSNR, sebab semua metrik lain menghasilkan
nilai selisih maksimum.
Bagian e+06 adalah notasi ilmiah, yaitu berapa tempat titik desimal
harus digeser. Misalnya: 4.65489e+06 --> 4,654,890.0
Jadi nilainya kira-kira 4 juta, dan merupakan kuadrat dari 2157.52
PERINGATAN: angka-angka ini bergantung pada level Quality (Q) IM yang
ditetapkan saat kompilasi. Makin tinggi kualitasnya, makin besar angkanya. Hanya
PSNR yang semestinya tidak terpengaruh. Karena itu IM juga memberikan hasil
'ternormalisasi' yang tidak terpengaruh pengaturan kualitas saat kompilasi, walau
efek 'kuantum' atau 'pembulatan bilangan bulat' yang kecil masih mungkin ada.
Saya BELUM berhasil memastikan apakah ada opsi "-define" yang sudah ada
yang bisa dipakai untuk fungsi "compare".
CATATAN untuk warna opak, jarak AE -fuzz dan RMSE setara.
TETAPI, bila warna transparan terlibat, pengujian faktor fuzz AE
akan menganggap dua warna transparan penuh yang berbeda sebagai sama,
sedangkan RMSE menganggap keduanya berbeda!
Sebagai contoh...
Bagi AE, putih transparan penuh dan hitam transparan penuh itu sama.
magick compare -metric AE xc:#0000 xc:#FFF0 null:
0 (0)
Bagi RMSE keduanya warna yang sama karena sama-sama transparan penuh
magick compare -metric RMSE xc:#0000 xc:#FFF0 null:
0 (0)
Dissimilarity-threshold
Kalau muncul error 'too different', itu bisa dimatikan dengan...
-dissimilarity-threshold 1.0
Tapi apa sebenarnya ambang batas ini?
Untuk informasi lebih lanjut, lihat catatan teks mentah saya yang sudah sangat lama... Image Comparing, Tower of Computational Sorcery
Mencocokkan sub-gambar dan bentuk
Sedang dikerjakan
Memakai opsi "compare -subimage-search"...
magick compare -subimage-search large_image.png sub-image.png results-%d.png
Ini menghasilkan dua gambar
results-0.png
yang menampilkan lokasi kecocokannya
results-1.png
yang berupa peta lokasi sudut kiri-atas yang mungkin, menunjukkan seberapa baik
sub-gambar itu cocok pada lokasi tersebut.
Perhatikan gambar kedua lebih kecil, karena isinya hanya lokasi sudut kiri-atas.
Karena itu ukurannya adalah large_image - small_image + 1
Pencariannya sendiri berbasis selisih vektor warna, sehingga menghasilkan
perbandingan warna yang sangat akurat.
Pada dasarnya pencarian ini membandingkan gambar kecil itu di SETIAP lokasi
yang mungkin pada gambar besar. Karena itu lambat! **sangat sangat lambat.**.
Ide terbaiknya adalah membandingkan sub-gambar yang sangat sangat KECIL untuk
menemukan lokasi yang mungkin, lalu dari situ melakukan perbandingan selisih di
tiap lokasi yang mungkin demi kecocokan yang lebih akurat.
Lihat skrip
https://usage.imagemagick.org/scripts/overlap
dan diskusi terkaitnya
[Overlapped Images](https://magick.imagemagick.org/viewtopic.php?f=1&t=22526&p=95286)
Diskusi itu membahas cara menemukan sub-gambar ber-'entropi tinggi' dari satu
gambar untuk mencari kemungkinan kecocokan pada gambar kedua, sehingga offset
tumpang tindih keduanya bisa diketahui dan gambarnya digabung jadi lebih besar.
Diskusi lain memakai pencarian sub-gambar untuk menemukan pola tile pada
gambar yang lebih besar, dengan tujuan menghasilkan gambar yang bisa di-tile
[Stitching image over a canvas](https://magick.imagemagick.org/viewtopic.php?f=1&t=22860)
Contoh memakai RMSE dan fungsi -grayscale yang baru untuk menggabungkan
hasil kanal selisih warna yang terpisah menjadi satu gambar akhir
magick large_image.png small_image.png miff:- |
magick compare -metric RMSE -subimage-search - miff:- |
magick - -delete 0 -grayscale MS show:
Ambang batas kemiripan
Sering kali orang hanya tertarik pada kecocokan pertama yang ditemukan.
Begitu kecocokan yang 'bagus' itu ketemu, tidak perlu lagi meneruskan
pencarian kecocokan lain. Opsi -similarity-metric menentukan apa yang
Anda anggap sebagai kecocokan yang bagus.
"-similarity-threshold 0.0" akan berhenti pada kecocokan 'sempurna' pertama
yang ditemukan, sedangkan "-similarity-threshold 1.0" (bawaannya) tidak akan
pernah cocok dan akan menelusuri setiap titik yang mungkin. Nilai di antaranya
menetapkan faktor 'fuzz' warna atas apa yang Anda terima sebagai kecocokan.
Perhatikan bila pencarian sub-gambar dihentikan, gambar 'peta' yang kedua hanya
akan berisi hasil sebagian, yaitu hasil sampai titik ketika compare
menghentikan pencariannya).
Beberapa contoh dasar pencarian sub-gambar....
Ambil tangkapan layar jendela terminal ("screen.png"),
lalu potong satu huruf atau kata darinya ("letter.png").
Laporkan kecocokan pertama saja.... demi kecepatan,
langsung berhenti setelah kecocokan pertama itu ditemukan.
Tidak usah mengeluarkan gambar hasil yang belum lengkap.
magick compare -subimage-search -metric AE -similarity-threshold 1.0 \
screen.png letter.png null: 2>&1
CATATAN kecepatannya sangat bergantung pada bagian mana dari gambar itu
kecocokan pertama ditemukan.
Temukan semua kemunculan gambar itu persis,
sebagai gambar (titik putih pada kecocokan, hitam pada sisanya)
magick compare -subimage-search -metric AE \
screen.png letter.png miff:- 2>/dev/null |
magick - -delete 0 show:
Ambil daftar koordinat semua huruf yang cocok (titik putih)
(sebagai daftar piksel terenumerasi, mengabaikan yang hitam)
magick compare -subimage-search -metric AE \
screen.png letter.png miff:- 2>/dev/null |
magick - -delete 0 txt:- | grep -v '#000000'
Daftar koordinatnya saja
magick compare -subimage-search -metric AE \
screen.png letter.png miff:- 2>/dev/null |
magick - -delete 0 txt:- | sed -n '/#FFFFFF/s/:.*//p'
Solusi pencarian sub-gambar NON-ImageMagick...
"visgrep" dari paket "xautomation".
Ini program pencarian sub-gambar yang jauh lebih sederhana, yang hanya
mengeluarkan daftar koordinat kecocokan (bahkan untuk beberapa sub-gambar).
Karena jauh lebih sederhana (untuk kecocokan yang nyaris persis) dan tidak
berusaha membuat 'gambar hasil' untuk dikaji lebih jauh, ia JAUH LEBIH CEPAT.
Sebagai contoh...
visgrep screen.png letter.png
Hasil pengukuran waktu
memakai "compare" untuk kecocokan pertama saja 0.21 detik
memakai "compare" untuk mendapat 'gambar hasil' 1.56 detik
idem, tetapi mengambil daftar koordinatnya 1.76 detik
memakai "visgrep" untuk semua koordinat yang cocok 0.09 detik
Metode lain untuk pencarian sub-gambar....
Morfologi HitAndMiss
Pada dasarnya ini pencocokan biner: Anda menentukan piksel mana yang harus
'latar belakang' dan mana yang harus latar depan. Namun ia juga memungkinkan
penentuan area yang hasilnya tidak dipedulikan, mau latar depan
atau latar belakang.
Pada dasarnya metode pencarian pola biner.
Correlate (varian Convolve)
Ini mirip Hit and Miss tetapi memakai nilai grayscale. Nilai positif untuk
latar depan, nilai negatif untuk latar belakang, dan nol untuk yang tak dipedulikan.
Namun cara ini terbatas pada gambar grayscale saja.
Lihat [Korelasi dan pencarian bentuk](convolve.html#correlate_search).
Keduanya pada dasarnya sama lambatnya dengan perbandingan sub-gambar tadi,
tetapi kurang akurat soal warna. Namun kemampuannya menentukan
bentuk (area yang tak dipedulikan) pada sub-gambar membuatnya berguna sebagai
metode pencarian.
Namun sub-gambarnya perlu diubah menjadi 'kernel', atau larik nilai
floating point, alih-alih sebagai gambar sungguhan.
FFT Convolve (NCC)
Fast Fourier Transform adalah operator yang lambat, tetapi biasanya berkali-kali
lipat lebih cepat daripada dua metode sebelumnya. Alasannya, konvolusi
di ranah frekuensi hanyalah perkalian piksel demi piksel secara
langsung.
Metode 'Convolve' bisa diubah menjadi 'Correlate' cukup dengan memutar
sub-gambar yang dicari sebesar 180 derajat.
Lihat [Correlate](convolve.html#correlate).
Pada dasarnya dengan mengubah gambar ke ranah 'frekuensi', pencarian sub-gambar
bisa dilakukan sangat sangat cepat dibanding cara sebelumnya, terutama
untuk sub-gambar besar yang ukurannya bisa sama dengan gambar aslinya!
Saya kira ini sudah ditambahkan sebagai metrik compare NCC.
<a id="peak_finding"></a>
Menemukan dan mengekstrak puncak (untuk kecocokan yang nyaris sebagian)...
Setelah gambar dibandingkan, biasanya kita punya semacam 'peta probabilitas'
yang menyatakan seberapa 'sempurna' kecocokannya.
Yang ingin dilakukan sekarang adalah menemukan kecocokan terbaik, atau mungkin
beberapa kecocokan dalam gambar. Yaitu menemukan 'puncak' utama pada
peta hasilnya, lalu mengambil lokasi sebenarnya.
* Memakai kernel konvolusi Laplacian
Untuk mendapat hasil, 'puncak' dalam gambar harus ditemukan, dan itu belum
tentu titik yang paling terang. Ini bisa diperoleh dengan mengonvolusi
gambar sedemikian rupa sehingga rata-rata piksel sekelilingnya dikurangkan
dari piksel pusat. Karena kita hanya ingin hasil positif, bias membuang
hasil yang negatif.
magick mandril3_ncc1.png \
-bias -100% -convolve Laplacian:0 result.png
Dengan di-threshold lalu dipakai sebagai mask, hanya piksel-piksel itu yang kita ambil.
magick mandril3_ncc1.png \
\( +clone -bias -100% -convolve Laplacian:0 -threshold 50% \) \
-compose multiply -composite \
txt:- | grep -v black
Masalahnya, yang didapat bisa berupa gerombolan titik pada satu puncak, bukan
satu piksel yang pasti, terutama untuk dua piksel puncak yang dikelilingi nilai
yang sangat rendah.
* Memakai kernel morfologi Hit and Miss Peaks
magick mandril3_ncc1.png \
-morphology HMT Peaks:1.5 result.png
Masalahnya, cara ini bisa tidak menghasilkan apa-apa bila ada dua piksel puncak
dengan nilai yang persis sama (tak ada jarak antara latar depan dan latar belakang)
Namun ada kernel 'peak' lain yang tetap bisa menemukan gerombolan puncak
semacam itu.
* Dilasi lalu bandingkan
Dilasi (perluas nilai maksimum) gambar itu 3 kali lalu bandingkan dengan
gambar aslinya. Puncak mana pun dalam area seukuran kernel dilasi (7 piksel
persegi) akan tetap bernilai sama. Semua piksel yang menunjukkan selisih
diset ke nol.
Metode dari HugoRune (topik diskusi IM 14491)
* Cocokkan dan buang secara berulang.
Pada dasarnya cari nilai piksel tertinggi, lalu catat. Kemudian mask semua piksel
di area sekitar puncak itu, dan ulangi sampai suatu batas (jumlah titik atau
ambang batas) tercapai.
Lihat implementasinya dalam skrip shell milik Fred Weinhaus,
"[maxima](http://www.fmwconcepts.com/imagemagick/maxima/)"
Cara ini tidak mencari pusat dari 'gerombolan' besar piksel yang nilainya nyaris
sama, meski hal itu sangat jarang terjadi pada gambar nyata.
* Menemukan lokasi sub-piksel
Kalau puncaknya bukan tepat satu piksel, melainkan bisa jadi berada di lokasi
sub-piksel (di antara piksel), maka semacam pencocokan pola (pencocokan kurva
gaussian) di sekitar puncak itu memungkinkan puncaknya ditemukan sampai ke
koordinat sub-piksel.
Ini mungkin lebih penting pada registrasi gambar untuk stitching panorama,
terutama bila titik yang dipakai tidak banyak untuk memperoleh rata-rata
best-fit dari overlay perspektifnya.
* Menemukan pola tile dalam gambar
Setelah semua titik terkumpul, pencarian pola berulang (jarak vektor yang
serupa di antara beberapa puncak) semestinya menunjukkan adanya semacam
struktur tile.
Memperbaiki pencocokan sub-gambar...
Masalah utama Correlate (atau FFT correlate yang cepat, yang sebenarnya hal
yang sama) adalah ia sama sekali tidak memahami warna.
Korelasi (atau konvolusi) murni teknik matematis yang diterapkan pada
sekumpulan nilai. Pada gambar, artinya ia hanya diterapkan pada
masing-masing kanal gambar, BUKAN pada jarak warna berbentuk
vektor.
Sementara compare benar-benar membandingkan vektor warna. Cara ini menemukan
bentuk lebih baik daripada correlate tetapi jauh jauh lebih lambat.
Karena itu, agar correlate benar-benar berguna, gambarnya sebaiknya diolah
(lebih dulu demi kecepatan, atau belakangan terhadap hasilnya) untuk menonjolkan
selisih warna dalam gambar sebagai gambar 'korelasi' grayscale.
SELINGAN: memakai -channel untuk membatasi operasi ke satu kanal grayscale
akan mempercepat. Pada IMv7, meng-grayscale-kan gambar menyusutkannya ke satu
kanal sehingga peningkatan kecepatan didapat otomatis.
Sebagai contoh, alih-alih intensitas, pembedaan latar depan / latar belakang
bisa jadi lebih baik bila yang diambil adalah rona (Hue) gambar.
Meski rona itu mungkin perlu diputar bila ada banyak merah pada
sub-gambar yang dicari.
Lihat contoh pemisahan kanal HSL dan HSB untuk melihat masalah ini.
https://usage.imagemagick.org/color_basics/#separate
Metode grayscale lain yang semestinya bekerja sangat baik adalah melakukan
deteksi tepi pada kedua gambar. Ini menonjolkan batas dan bentuk, yang
biasanya jauh lebih penting daripada gradien halus atau perubahan warna
dalam gambar.
Untuk contoh metode deteksi tepi, lihat
https://usage.imagemagick.org/convolve/#edgedet
Anda mungkin juga tertarik pada deteksi tepi berarah atau tipe kompas.
Pada dasarnya apa pun yang menguatkan bentuk untuk kasus Anda adalah ide
yang bagus. Terapkan saja pada KEDUA gambar sebelum dikorelasikan.
Pencocokan yang invarian terhadap skala dan rotasi...
* tak bergantung posisi...
* mencocokkan sub-gambar yang diputar (tak bergantung sudut)
* mencocokkan sub-gambar yang diubah ukurannya (tak bergantung ukuran)
* Tak bergantung ukuran sekaligus sudut
--------------
Pencocokan gambar lain yang lebih khusus..
Mencocokkan garis...
Algoritma Hough
Mencocokkan lingkaran...
Varian algoritma Hough
Mencocokkan wajah
Kombinasi dari yang di atas.
Menemukan gambar duplikat
File yang identik
Apakah file-nya identik secara biner, artinya benar-benar file yang sama dan kemungkinan besar hanya salinan persis satu sama lain. Tidak perlu ImageMagick. Jangan remehkan cara ini. Banyak file bisa dibandingkan dengan sangat cepat lewat cara ini. Metode terbaik yang saya temukan adalah memakai checksum MD5.
md5sum * | sort | awk {'print $2 " " $1'} | uniq -Df 1
Perintah itu akan menampilkan md5 dari gambar-gambar yang identik. Dengan teknik ini saya membuat skrip yang bisa menghasilkan dan membandingkan daftar md5sum file, lalu mengembalikan file yang md5-nya identik. Namun perhatikan, perubahan apa pun pada file gambar selain penyalinan langsung akan digolongkan cara ini sebagai berbeda, meski data gambarnya sendiri sama. Cukup perubahan tanggal atau selisih metadata kecil lain pada file untuk membuat gambarnya dianggap berbeda.
Signature gambar IM
IM bisa diminta menghasilkan 'signature' untuk tiap gambar...
magick identify -quiet -format "%#" images...
Perintah itu menghasilkan string hash yang mirip dengan MD5 dan SHA256. Namun berbeda dengan keduanya, IM memakai data gambar yang sebenarnya untuk membuat signature itu, bukan metadata gambarnya. Jadi, kalau ada dua salinan gambar yang sama tetapi dengan stempel waktu pembuatan/pengubahan yang berbeda, signature keduanya semestinya sama, sedangkan MD5 dan SHA256 akan menghasilkan dua signature berbeda walau gambarnya sendiri sama. PERINGATAN: membaca lalu menulis gambar JPEG akan menghasilkan data gambar yang berbeda, jadi signature-nya pun berbeda. Ini semata-mata karena kompresi lossy yang dipakai format gambar JPEG.
Perbandingan langsung
Dua gambar bisa langsung dibandingkan (dengan program "magick compare") bila ukurannya sama, untuk melihat seberapa cocok keduanya. (Lihat di atas) Cara ini sangat lambat, dan menurut pengalaman saya kurang berguna bila dipakai pada gambar berukuran penuh, justru karena lambatnya itu. Namun cara ini mungkin yang terbaik untuk mendapat gambaran seberapa mirip dua gambar.
Klasifikasi gambar
Dalam upaya saya membandingkan gambar, saya menemukan bahwa gambar berwarna, gambar bergaya kartun, dan sketsa berperilaku sangat berbeda satu sama lain saat dibandingkan. Gambar garis dan gambar grayscale khususnya cenderung menghasilkan selisih yang lebih kecil daripada gambar berwarna, pada hampir semua metode perbandingan. Pada dasarnya, karena semua warnanya terletak pada satu garis, metrik warna apa pun cenderung menempatkan gambar semacam itu 3 kali lebih berdekatan (ruang warna 1 dimensi berbanding ruang warna 3 dimensi). Artinya, memisahkan gambar setidaknya ke dalam dua kelompok ini bisa menjadi langkah pertama yang sangat penting dalam upaya serius menemukan gambar duplikat atau yang sangat mirip. Klasifikasi besar lain atau tipe gambar juga bisa mempermudah perbandingan, cukup dengan mengurangi jumlah gambar pembandingnya. Lihat klasifikasi gambar di bawah.
Perbandingan thumbnail
Anda membuat program yang menghasilkan (di memori) banyak thumbnail kecil (misalnya 64x64 piksel) dari gambar-gambar yang hendak dicari duplikatnya, lalu membandingkannya secara langsung. Biasanya inilah hal pertama yang dicoba orang (saya juga), dan memang teknik inilah yang dipakai kebanyakan program pembanding gambar (misalnya perangkat lunak pengelola foto). Cara ini memang bekerja baik dan menemukan gambar yang persis sama. Dengan sedikit blur dan ambang batas selisih yang dilonggarkan, cara ini bahkan bisa menemukan gambar yang sedikit dipangkas dan diubah ukurannya. Namun mencoba menyimpan 10.000 thumbnail semacam itu di memori sering membuat komputer biasa mulai thrashing dan menjadi sangat lambat. Alternatifnya, menyimpan semua thumbnail itu (kecuali kalau programnya memang melakukannya supaya bisa dilihat pengguna) memakan banyak ruang disk. Salah satu cara memperbaiki masalah thrashing disk adalah dengan hanya menaruh lebih sedikit gambar di memori. Yaitu dengan membandingkan gambar per kelompok, bukan satu gambar terhadap semua gambar lain. Pengelompokan yang alami adalah per direktori, lalu membandingkan tiap direktori gambar dengan direktori gambar lainnya. Cara ini sebenarnya cukup bagus, sebab gambar cenderung terkumpul bersama, dan kelompok gambar itu sering cocok dengan kelompok yang serupa. Mengeluarkan gambar yang cocok per pasangan direktori jadi nilai tambahnya. Selain itu, seberapa mirip dua gambar bisa diterima juga bergantung pada tipe gambarnya. Membandingkan dua gambar garis perlu 'ambang batas' yang sangat kecil untuk menyingkirkan gambar yang berbeda, sedangkan membandingkan gambar dengan area warna yang luas sering perlu ambang batas jauh lebih besar agar gambar mirip yang dipangkas tetap tertangkap. Gambar dunia nyata punya masalah lebih besar, sebab tekstur bisa menimbulkan selisih tambahan yang sangat serius antara dua gambar yang offset-nya hanya berbeda sedikit. Karena itu gambar semacam itu mungkin perlu disederhanakan menjadi area-area warna umum, entah dengan filter median, blur, pengurangan warna, atau segmentasi warna. Setelah proses semacam itu, gambar dunia nyata umumnya bisa dibandingkan dengan cara yang mirip dengan kartun.
Metrik gambar
Membuat metrik kecil untuk tiap gambar adalah operasi berorde linear (O), sedangkan membandingkan semua gambar dengan semua gambar lain adalah operasi berorde kuadrat (O^2). Metrik tidak dimaksudkan untuk benar-benar menemukan gambar yang cocok, melainkan untuk mengelompokkan gambar yang mirip (yang berpeluang cocok) sedemikian rupa sehingga perbandingan yang lebih intensif bisa dilakukan pada kelompok yang lebih kecil. Karena itu perbandingan metrik apa pun sebaiknya longgar, dan menerima gambar yang peluang cocoknya rendah (tetapi tetap ada peluangnya). Namun jangan sampai begitu longgar sehingga terlalu banyak yang salah masuk. Anda juga bisa mempertimbangkan beberapa metrik sekaligus, sebab suatu metrik bisa mencocokkan gambar yang 'nyaris terlewat' oleh metrik lain karena jatuh di wilayah bertetangga yang berbeda (ambang batas tidak cocok). Pada bagian berikutnya (Metrik) ada sejumlah metrik hasil IM yang sudah saya coba atau saya reka secara teori, antara lain: warna rata-rata, warna dominan, latar depan latar belakang, warna tepi, matriks warna, dan lain-lain. Günter Bachelier juga melaporkan kemungkinan memakai metrik yang lebih eksotis untuk perbandingan gambar, misalnya: deskriptor Fourier, dimensi fraktal, area cembung, panjang dan sudut sumbu mayor/minor, kebulatan, kecembungan, curl, soliditas, varians bentuk, arah, bilangan Euler, deskriptor batas, kelengkungan, energi lentur, kelengkungan mutlak total, luas, sentrum geometris, pusat massa, kekompakan, eksentrisitas, momen terhadap pusat, dan seterusnya. Upaya saya saat ini adalah menghasilkan dan memakai matriks 3x3 sederhana berisi rata-rata warna untuk mewakili gambar (lihat Metrik matriks warna di bawah). Begitu metrik itu dihasilkan (atau diminta), metrik disimpan sebagai cache (bersama info file lain) ke dalam file khusus di tiap direktori. Dengan begitu saya hanya perlu membuat ulang suatu metrik bila cache-nya tidak tersedia, atau gambarnya berubah.
Kemiripan atau jarak
Metrik dua gambar (atau gambarnya sendiri) bisa dibandingkan dengan sejumlah metode berbeda, yang umumnya menghasilkan satu ukuran jarak atau 'metrik kemiripan' yang bisa dipakai untuk meng-cluster gambar-gambar yang 'mirip'.
- Ambang batas langsung, atau selisih maksimum, (jarak Chebyshev)
Cukup bandingkan gambar berdasarkan selisih terbesar pada satu metrik mana pun.
Ambang batas itu akan menghasilkan hiperkubus gambar-gambar mirip di ruang metrik multidimensi. Tentu saja selisih gambarnya hanya berdasarkan satu metrik, bukan seluruh metrik. - Selisih rata-rata (jarak rata-rata, jarak Manhattan yang dirata-ratakan)
Jumlahkan semua selisih dan bila perlu bagi dengan jumlah metriknya.
Ini juga dikenal sebagai jarak Manhattan antara dua metrik, sebab setara dengan jarak yang harus ditempuh untuk berjalan di jalanan kota yang berpetak. Semua metrik menyumbang sama besar, sehingga segala sesuatu tampak lebih 'dekat' daripada yang Anda kira. Di ruang metrik, ambang batas metrik ini menghasilkan bentuk seperti wajik. - Selisih Euclid (Pythagoras)
Atau jarak vektor langsung antara metrik-metrik di ruang metrik.
Nilainya cenderung lebih besar bila metrik yang terlibat lebih banyak. Namun satu metrik yang menghasilkan selisih besar cenderung menyumbang lebih banyak daripada metrik lain. Ambang batasnya menghasilkan volume berbentuk bola di ruang metrik. - Error matematis/kecocokan data atau (momen inersia???)
Jumlahkan kuadrat semua selisih, lalu ambil akar kuadratnya
Ini lebih lazim dipakai untuk menghitung seberapa dekat sebuah kurva matematis mencocoki sekumpulan data tertentu, tetapi bisa juga dipakai untuk membandingkan metrik gambar.
Cara ini tampaknya memberi ukuran jarak non-vektor yang terbaik. - Sudut vektor
Cari sudut antara dua garis dari pusat ruang vektor yang dibentuk metrik gambar itu. Ini semestinya menghilangkan pengaruh kontras atau penguatan gambar yang mungkin sudah diterapkan pada kedua gambar.
Belum diuji - Jarak vektor
Untuk gambar yang berupa gambar garis atau gambar grayscale, yang semua vektor warnanya dalam satu metrik searah, jarak relatif metrik terhadap warna rata-rata gambar mungkin lebih penting. Menormalkan jarak-jarak itu terhadap jarak terbesar bisa mengurangi pengaruh kontras.
Jadi, ini metode perbandingan untuk gambar garis.
Belum diuji - Analisis cluster
Semua metrik diplot dan dikelompokkan menjadi cluster-cluster yang mirip di dalam ruang multidimensi. Paket clustering yang baik bahkan mungkin bisa menemukan dan menyingkirkan metrik yang tidak menghasilkan clustering apa pun.
Belum diuji
Saat ini saya merasa teknik "Error matematis" bekerja baik untuk metrik grayscale maupun berwarna, dengan "Metrik matriks warna" 3x3 rata-rata yang sederhana (lihat di bawah).
Verifikasi oleh manusia
Setelah komputer selesai berusaha menemukan gambar yang cocok, giliran penggunalah yang harus benar-benar memastikan gambar-gambar itu cocok. Menyajikan hasil kecocokan kepada pengguna juga bisa jadi tugas yang sulit, sebab mereka kemungkinan menginginkan kemampuan untuk...
- Melihat gambar berdampingan
- Berganti sangat sangat cepat antara dua gambar, pada ukuran aslinya, dan bila perlu pada ukuran 'terskala' yang sama.
- Berganti antara, atau menimpakan, gambar dengan skala dan geseran berbeda, untuk mencoba menyelaraskan gambarnya.
- Melihat gambar lain dalam direktori (sumber) yang sama, atau mungkin cluster yang sama (kecocokan dekat lainnya) dengan gambar yang cocok itu, sehingga satu kelompok utuh bisa ditangani sekaligus, bukan tiap gambar satu per satu.
- Mengganti nama, memindahkan, mengganti, menghapus, menyalin gambar di antara dua (atau lebih) direktori, untuk memilah gambar dan menyingkirkan sisanya.
- dan seterusnya...
. Saat ini saya mengelompokkan hasil kecocokan menjadi beberapa set dan memakai gabungan beberapa program untuk menanganinya di bawah kendali pengguna. Program-program itu termasuk "magick display" dan "magick montage" milik IM, serta penampil gambar "XV" dan "GQview". Namun saya terbuka untuk usulan program lain yang bisa membuka dua direktori atau lebih sekaligus, dan menampilkan koleksi atau kelompok gambar dari beberapa direktori. Kendali jarak jauh atau kendali oleh program dan skrip lain bisa jadi sangat penting, sebab memungkinkan kelompok gambar disiapkan dan disajikan dengan cara terbaik untuk dilihat dan ditangani pengguna. Belum ada program yang memenuhi kebutuhan saya. Sebagai contoh, "gqview" punya koleksi dan tampilan satu direktori, tetapi tidak memungkinkan tampilan banyak direktori, ataupun kendali penyajian dari jarak jauh / baris perintah. Koleksinya pun tidak menunjukkan tiap gambar berasal dari direktori mana, dan tidak bisa memindahkan tampilan satu direktori itu ke direktori lain. Program itu juga tidak bisa dikendalikan program lain. Di sisi lain, "xv" yang sudah sangat tua memang memungkinkan tampilan banyak direktori (memakai beberapa jendela 'visual schnauzer'), dan daftar koleksi di jendela kendalinya, tetapi hanya satu gambar yang bisa dilihat pada satu waktu, dan hanya satu direktori yang bisa dibuka dan diposisikan dari baris perintahnya. Tentu saja program itu juga tak punya kendali jarak jauh. Inilah program verifikasi oleh manusia terbaik yang saya temukan, yang saya siapkan dan jalankan lewat skrip untuk tiap kelompok gambar, pasangan yang cocok, atau semua gambar yang cocok dalam kelompok. Tapi tak satu pun benar-benar memuaskan. Meja cahaya beserta perangkat lunaknya menurut saya cara yang lebih baik untuk memilah gambar, tetapi untuk itu diperlukan layar sentuh yang besar, dan di situlah biayanya membengkak.
Perbandingan gambar lintas tipe
Salah satu hal yang lebih sulit yang ingin saya lakukan adalah menemukan gambar yang dibuat dari gambar lain. Sebagai contoh, saya ingin mencocokkan gambar garis yang diwarnai atau dilukis orang lain sehingga menjadi gambar kartun atau bahkan gambar yang sangat realistis. Latar belakang pun bisa saja sudah ditambahkan. Hal-hal semacam ini sangat sulit, dan percobaan saya dengan teknik deteksi tepi sejauh ini belum memberi kesimpulan. Kuncinya adalah menemukan metrik yang tepat, sebab manusia jauh lebih baik dalam menarik hubungan 'kemiripan', tetapi kemungkinan kecocokan tetap harus ditemukan lebih dulu untuk disajikan kepada pengguna.
Ringkasan menemukan gambar duplikat
Ringkasnya, prosedur saya saat ini untuk menemukan dan menangani gambar duplikat adalah rangkaian program untuk menemukan dan memilah gambar yang 'mirip'.
Hasilkan/Cache tipe gambar dan metrik
-> Bandingkan metrik lalu cluster gambarnya.
-> bandingkan gambar dalam cluster untuk mencari kecocokan
-> kelompokkan menjadi set gambar yang cocok (per direktori sumber)
-> verifikasi oleh manusia
Seperti terlihat, saya menempuh pendekatan yang sangat bertahap. Kirimi saya ide Anda!!!
Mengelompokkan gambar berdasarkan tipe
Menentukan tipe gambar itu penting, sebab kebanyakan metode perbandingan gambar hanya bekerja untuk tipe gambar tertentu. Tidak ada gunanya membandingkan gambar teks dengan sketsa seorang seniman, misalnya. Tidak berguna pula memakai metode perbandingan gambar berwarna pada gambar yang nyaris putih murni (sketsa). Biasanya hal pertama yang dilakukan saat membandingkan gambar adalah menentukan tipe gambar, atau 'ruang warna' apa yang dipakai gambar itu. Klasifikasi dasar gambar bisa mencakup...
- Gambar garis hitam putih atau gambar teks (hampir seluruhnya satu warna)
- Gambar yang terdiri dari dua warna dasar dengan porsi seimbang (gambar pola?).
- Sketsa seniman dalam grayscale (banyak gradasi)
- Gambar berwarna linear (warnanya membentuk gradien tetapi bukan dari hitam ke putih)
- Gambar berwarna bergaya kartun dengan area warna polos yang luas.
- Gambar dunia nyata dengan area warna bergradasi
- Gambar yang memuat teks anotasi atau overlay logo. (satu lonjakan warna)
Setelah kategori dasarnya ada, gambar juga bisa dipilah memakai berbagai metrik gambar, misalnya... * Warna rata-rata seluruh gambar * warna dominan dalam gambar * Warna latar depan/latar belakang gambar.
Yang lebih parah, gambar JPEG atau gambar yang diubah ukurannya sering juga terdistorsi warnanya, sehingga klasifikasi semacam ini jauh lebih sulit karena warnanya tidak persis seperti seharusnya. Abu-abu tidak akan abu-abu murni, dan garisnya bisa jadi tidak tajam dan jelas. Diskusi panjang yang masih berlangsung tentang pemilahan gambar berdasarkan tipe ada di IM Users Forum... How to check image color or black and white.
Gambar grayscale
Cara paling sederhana untuk memeriksa apakah sebuah gambar grayscale adalah melihat level saturasi warnanya. Itu mudah dilakukan dengan mengonversi gambar ke ruang warna gambar 'Hue' lalu mengambil nilai rata-rata dan maksimum dari kanal warna (biasanya hijau). Sebagai contoh..
magick rose: granite: -colorspace HCL \
-format '%M avg=%[fx:mean.g] peak=%[fx:maxima.g]\n' info:
Angka-angkanya dinormalkan ke rentang 0 sampai 1. Seperti terlihat, "rose" sangat berwarna (rata-rata 30%), dengan puncak yang kuat (mendekati 1). Gambar "granite" sebaliknya punya saturasi yang sangat rendah (sekitar 2%) dan nilai puncak yang rendah. Meski bukan grayscale murni, gambarnya sangat mendekati itu. Rata-rata yang rendah dengan puncak yang tinggi menandakan adanya bercak kecil berwarna kuat. Men-threshold kanal yang sama bisa menghasilkan mask dari area gambar yang berwarna. MASALAH: cara di atas tidak menemukan gambar yang warnanya linear. Yaitu gambar yang hanya memuat warna-warna yang membentuk gradien warna linear, seperti foto yang menguning (sepiatone), atau cetak biru. Gambar semacam itu pada dasarnya adalah gambar grayscale yang berwarna. Lihat tipe gambar berikutnya.
Apakah gambar berwarna linear
Teknik lain adalah melakukan 'best fit' langsung sebuah garis 3 dimensi terhadap semua warna (atau matriks warna metrik yang disederhanakan) dalam gambar. Error dari kecocokan itu (umumnya rata-rata kuadrat error) memberi petunjuk yang sangat baik tentang seberapa cocok gambar itu terhadap garis tersebut. Mencocokkan garis pada gambar 3 dimensi umumnya melibatkan sedikit matematika vektor. Hasilnya bukan hanya memberi tahu apakah gambar memakai himpunan warna yang nyaris 'linear', tetapi juga bekerja untuk SEMBARANG skala warna, bukan cuma terang ke gelap, melainkan juga garis keabu-abuan di atas kertas kuning. Hasil itu juga bisa dipakai untuk mengubah gambar menjadi gambar 'grayscale' yang lebih sederhana (atau sekadar mengubah sekumpulan metrik warna menjadi metrik grayscale) demi perbandingan yang lebih sederhana dan pencarian kecocokan yang lebih baik. Program uji coba saya bahkan tidak memakai gambar utuh untuk penentuan ini, melainkan bekerja dengan Metrik matriks warna sederhana di bawah, yang terdiri dari 9 warna (27 nilai) untuk mewakili gambar. Namun hati-hati, uji ini umumnya kurang bisa membedakan gambar garis yang tanpa gradasi. Gambar semacam itu hampir seluruhnya satu warna latar belakang (biasanya putih) sehingga bisa jadi tidak menunjukkan gradien warna linear apa pun. Gambar seperti itu sebaiknya dipisahkan lebih dulu dengan uji yang berbeda (lihat berikutnya, sebenarnya jauh lebih mudah). Kirimi saya email kalau tertarik, dan beri tahu apa saja yang sudah Anda coba.
Gambar hitam putih murni
Untuk melihat apakah sebuah gambar nyaris hitam putih murni, dengan sedikit sekali warna atau bahkan abu-abu (akibat anti-aliasing), kita bisa memakai opsi "-solarize" dengan cara yang tidak biasa (lihat contoh IM tentang Solarize). Menerapkan operasi ini pada gambar apa pun membuat warna terang menjadi warna gelap (dinegasikan). Dengan begitu warna yang nyaris putih akan menjadi nyaris hitam. Dari gambar semacam itu, analisis statistik sederhana akan menentukan apakah gambarnya murni (atau hampir murni) hitam putih.
magick wmark_dragon.jpg -solarize 50% -colorspace Gray wmark_bw_test.png
magick identify -verbose -alpha off wmark_bw_test.png | \
sed -n '/Histogram/q; /Colormap/q; /statistics:/,$ p' > wmark_stats.txt
Kalau Anda lihat statistik di atas, 'mean' warnanya sangat dekat ke hitam murni ('0'), sedangkan 'standard deviation'-nya juga sangat kecil, tetapi lebih besar daripada 'mean'. Jadi gambar ini pastilah sebagian besar hitam putih murni, dengan sangat sedikit warna atau abu-abu mid-tone. Untuk gambar grayscale dan gambar berwarna pada umumnya, 'mean'-nya akan jauh lebih besar, dan umumnya 'standard deviation'-nya lebih kecil daripada mean. Kalau itu yang terjadi, artinya gambar hasil solarize sangat sedikit memuat warna yang mendekati hitam murni. Yaitu, sangat sedikit warna hitam atau putih murni yang hadir. Mari kita ulangi uji ini memakai gambar granite bawaan.
magick granite: granite.jpg
magick granite.jpg -solarize 50% -colorspace Gray granite_bw_test.png
magick identify -verbose -alpha off granite_bw_test.png | \
sed -n '/Histogram/q; /Colormap/q; /statistics:/,$ p' > granite_stats.txt
Perhatikan 'mean'-nya kini jauh lebih besar, mengarah ke tengah rentang warna, dengan 'standard deviation' yang jauh lebih kecil daripada besarnya 'mean'. Sejak IM v6.4.8-3 Anda juga akan melihat dua nilai statistik lain yang bisa membantu menentukan tipe gambar. Baik 'Kurtosis' maupun 'Skewness' relatif besar (dan positif) pada gambar hitam putih yang pertama, dan itu mencerminkan kenyataan bahwa sangat sedikit abu-abu yang terlibat dibandingkan dengan gambar Gray. Namun 'mean' berbanding 'standard deviation' agaknya masih indikator yang lebih baik untuk keperluan perbandingan. Perhatikan bahwa perbandingan ini tidak membedakan 'hitam di atas putih' dari 'putih di atas hitam', tetapi begitu Anda tahu gambarnya memang bukan grayscale, pemeriksaan sederhana atas mean normal gambar itu akan memberi tahu warna latar belakangnya yang sebenarnya.
Gambar dengan warna spot
Gambar-gambar ini gagal pada uji grayscale di atas, tetapi tetap hitam putih, hanya saja ada area atau bercak warna kecil di dalamnya. Bercak warna kecil mudah tenggelam oleh rata-rata keseluruhan gambar yang besar, sehingga tipenya bisa salah dikenali sebagai grayscale. Kita tidak tertarik pada gambar yang, katakanlah, hanya punya satu piksel berwarna, yang kemungkinan besar adalah error bit, atau bintik-bintik piksel semacam itu yang tersebar di seluruh gambar. Yang dimaksud adalah gambar dengan panah berwarna atau objek kecil berwarna. Dengan kata lain, satu titik warna yang terpusat. Dalam sebuah diskusi di IM Forum False positive for greyscale images using the "saturation test" muncul gagasan untuk memecah gambar menjadi bagian-bagian yang lebih kecil, lalu mencari saturasi tinggi di salah satu area itu. Dari situ lahirlah metode berikut.
- ubah gambar ke ruang warna yang punya kanal Saturation atau Chroma
- Perkecil gambar dengan rasio 1:50 (2%) (misalnya 'ukuran spot' untuk warna)
- Threshold untuk mendapatkan nilai saturation/chroma maksimum
Titik tunggal atau yang sangat kecil akan terbuang, tetapi titik warna yang lebih besar akan menyisakan setidaknya satu piksel berwarna pada gambar yang sudah diperkecil.
Gambar berwarna midtone
Gambar yang bernada sepia, atau yang abu-abu midtone-nya diwarnai dengan warna sorot tertentu (misalnya gambar di sebelah kanan) bisa jauh lebih sulit dibedakan. Membuat gambar semacam itu mudah, seperti ditunjukkan di Pewarnaan nada tengah, meski gambar seperti itu tidak umum. Warnanya tetap membentuk gradien (garis) warna di ruang warna, tetapi gradien itu jatuh di sepanjang lintasan melengkung, biasanya semacam parabola, pada sebuah bidang. Namun membedakan gambar semacam ini bisa sangat sulit. Salah satu tekniknya adalah mengambil standard deviation dari rona mana pun yang saturasinya tidak teramat kecil. Semua rona dalam gambar berwarna midtone semestinya sangat mirip meski jumlahnya tidak banyak. Teknik ini dipaparkan pada kiriman tertentu di How to check image color or back and white. Sekadar pengingat, rona adalah nilai siklis yang berputar kembali ke warna 'merah'. Untuk mengujinya dengan benar, mungkin perlu dilakukan dua kali, dengan rona digeser 180 derajat. Rona juga tidak punya makna berarti bagi warna dengan saturasi yang sangat rendah (abu-abu), jadi warna semacam itu sebaiknya diabaikan saat menguji standard deviation rona.
Teks vs gambar garis
Kalau Anda punya gambar yang nyaris seluruhnya satu warna (biasanya putih), Anda bisa mencoba melihat apakah isinya bisa digolongkan sebagai teks atau gambar garis. Teks punya banyak objek kecil yang terpisah-pisah, umumnya tersusun dalam baris-baris mendatar. Sebaliknya, gambar garis semestinya sebagian besar saling terhubung sebagai satu kesatuan, dan melibatkan banyak sudut yang berbeda. Perhatikan bahwa gambar berwarna bergaya kartun juga bisa diubah menjadi gambar garis demi perbandingan yang lebih sederhana, jadi metode perbandingan gambar garis akan sangat berguna. Ada yang punya? Untuk mengetahui lebih banyak tentang teks, sejumlah teknik sudah dibahas di forum IM, Check if image contains text.
Dunia nyata vs bergaya kartun
Pada dasarnya kartun punya blok warna yang sangat spesifik dengan wilayah bertepi tajam, sering dipertajam lagi dengan garis hitam pemisah. Kartun juga biasanya sangat minim gradien atau efek gradasi. Sebaliknya gambar dunia nyata punya banyak efek tepi yang lembut, gradien warna, dan tekstur, serta memakai banyak warna berbeda. Tentu saja ini tidak selalu benar. Gambar dunia nyata bisa saja terasa sangat seperti kartun, terutama bila kontrasnya sangat tinggi, dan sebagian kartun modern begitu menyerupai kehidupan nyata sehingga sulit digolongkan sebagai kartun. Umumnya perbedaan utama antara gambar dunia nyata dan kartun adalah tekstur dan gradien. Karena itu, untuk menentukan tipe sebuah gambar, gambar itu perlu dibandingkan dengan versi dirinya sendiri yang tekstur halusnya sudah dibuang. Selisih yang besar berarti gambarnya lebih 'realistis' dan mirip dunia nyata, bukan 'bergaya kartun' atau 'datar'. Ingat pula bahwa gambar garis, sketsa seniman, dan teks juga bisa sangat bergaya kartun, tetapi teksturnya begitu halus dan rinci sehingga cara di atas bisa menganggapnya gambar dunia nyata. Karena itu gambar garis dan sketsa sebaiknya dipisahkan lebih dulu.
Jim Van Zandt menawarkan solusi ini...
- tuliskan warna setiap piksel
- urutkan berdasarkan warna
- tuliskan cacah piksel untuk setiap warna
- urutkan berdasarkan cacah piksel
- Telusuri daftarnya sampai separuh piksel dalam gambar terhitung.
- Kalau #piksel >>> #warna maka gambarnya bergaya kartun.
Bagian awalnya bisa digolongkan sebagai histogram. Lihat contoh "histogram:".
Kalau Anda sudah membuat semacam skema klasifikasi gambar.. sekalipun baru kasar, tolong beri tahu kami hasilnya, supaya orang lain (termasuk saya sendiri) bisa ikut memetik manfaatnya.
Menangani tipe gambar tertentu
Berikut catatan dan informasi tentang teknik penentuan gambar yang lebih khusus.
Hasil pindai atau cetakan yang buruk
Di dunia nyata, segala sesuatu tidak pernah bekerja sesempurna yang kita mau. Sensor pemindai bisa rusak dan drum printer bisa tergores. Kedua masalah itu umumnya membuat hasil pindai dan cetakan memuat garis vertikal yang panjang. Namun menentukan apakah sebuah gambar punya garis vertikal semacam itu cukup mudah. Idenya adalah merata-ratakan piksel semua baris dalam gambar. 'Cacat' apa pun akan muncul sebagai lonjakan tajam pada baris piksel akhir, dan jumlahnya bisa dihitung dengan 'histogram threshold' dari baris piksel itu.
FUTURE -- image example needed for testing
magick bad_printout.png -crop 0x1+0+0 -evaluate-sequence mean \
-threshold 50% -format %c histogram:info:-
metode yang lebih cepat tetapi perlu tinggi gambar (diasumsikan 1024)
magick bad_printout.png -scale 1024x1 \
-threshold 50% -format %c histogram:info:-
Setelah 'garis cacat' semacam itu ditemukan dan dibuang dari faks, cetakan, atau hasil pindai, uji-uji lain bisa diteruskan tanpa perlu mengkhawatirkan cacat dunia nyata semacam ini.
Faks kosong
Pertama, header dan footer yang mungkin ditambahkan faks ke sebuah halaman perlu di-"-shave". Setelah itu bisa dibuat 'histogram threshold' (lihat sebelumnya) untuk melihat ada berapa piksel hitam di sana.
FUTURE -- image example needed for testing
magick blank_fax.png -threshold 50% -format %c histogram:info:-
Atau bisa juga dilakukan Trim gambar 'noisy' untuk melihat apakah gambar itu sebenarnya masih memuat area padat atau objek yang layak diperhatikan.
FUTURE -- image example needed for testing
Gambar yang di-spam
Gambar yang di-spam umumnya menunjukkan lonjakan warna murni yang dominan pada histogram warna gambar. Pemeriksaan warna itu di dalam gambar biasanya menunjukkan letaknya di salah satu sudut gambar. Namun cara ini tidak berhasil pada gambar bergaya kartun.
Gambar spam email
Ini gambar yang dirancang untuk lolos dari berbagai penyaring spam. Pada dasarnya teks iklannya disembunyikan di dalam gambar memakai berbagai warna, ditambah 'kotoran' dan noise lain supaya lebih sulit dideteksi. Meski gambar semacam ini sulit dibedakan dari, katakanlah, logo pada header email perusahaan, ukurannya biasanya jauh lebih besar daripada logo email pada umumnya. Salah satu teknik untuk menemukannya adalah memakai filter median yang besar pada gambar. Teks spam email umumnya akan lenyap, sedangkan logo atau gambar akan tetap sangat berwarna.
Metrik gambar, cepat menemukan gambar untuk dibandingkan
Metrik adalah semacam 'sidik jari' yang mewakili sebuah gambar dalam memori yang sangat kecil. Gambar yang mirip semestinya menghasilkan metrik yang mirip pula. Namun perhatikan, metrik tidak dirancang untuk benar-benar menemukan gambar yang cocok, melainkan untuk menyingkirkan gambar yang jelas-jelas tidak cocok. Artinya, metrik yang baik memungkinkan sebagian besar gambar dikesampingkan dari perbandingan lanjutan, sehingga waktu yang dibutuhkan untuk menelusuri semua gambar berkurang.
Warna rata-rata sebuah gambar
Anda bisa memakai -scale untuk mendapat warna rata-rata sebuah gambar, tetapi saya
sarankan juga membuang tepi luar gambar untuk mengurangi pengaruh
'embel-embel' yang mungkin ditambahkan di sekeliling gambar.
magick image.png -gravity center -crop 70x70%+0+0 \
-scale 1x1\! -depth 8 txt:-
Sebagai alternatif, untuk mendapat warna 'centroid terbobot' berdasarkan clustering
warna, bukan rata-rata, Anda bisa memakai -colors
magick rose: -colors 1 -crop 1x1+0+0 -depth 8 -format '%[pixel:s]' info:-
rgb(146,89,80)
Cara ini umumnya mencocokkan gambar yang sudah diubah ukurannya, dipangkas sedikit, diputar, atau digeser. Tetapi cara ini juga akan mencocokkan banyak gambar yang sebenarnya tidak berkaitan erat. Masalah terbesarnya, metrik ini umumnya mengabaikan gambar yang sudah dicerahkan, diredupkan, atau diubah rona keseluruhannya. Selain itu, meski metrik ini bagus untuk gambar berwarna dan gambar dunia nyata, ia sama sekali tidak berguna untuk gambar grayscale. Semua gambar semacam itu umumnya menumpuk jadi satu tanpa clustering lebih lanjut di dalam tipenya. Ini pada gilirannya menunjukkan mengapa klasifikasi tipe gambar di awal bisa sangat menentukan bagi pemilahan dan pencocokan gambar yang baik.
Warna dominan sebuah gambar
Warna dominan sebuah gambar agak berbeda: alih-alih rata-rata yang mencampur warna latar belakang dengan latar depan, yang dicari adalah warna latar depan yang paling umum, dan mungkin persentase seberapa besar bagian gambar yang terdiri dari warna dominan itu. Karena itu histogram gambar saja tidak cukup, sebab gambarnya bisa memakai banyak gradasi warna satuan alih-alih satu warna tertentu. Ini bisa dilakukan dengan fungsi kuantisasi tingkat rendah -segment, lalu mengambil histogramnya. Cara ini lebih unggul daripada memakai -colors secara langsung karena tidak berusaha menggabungkan cluster warna yang berjauhan (secara warna), meski hasilnya bisa lebih sulit ditafsirkan.
FUTURE example
Setelah itu histogram akan memberi tahu banyaknya masing-masing warna dominan. Namun biasanya warna dominan sebuah kartun atau gambar garis adalah warna latar belakang gambar itu. Jadi cara ini benar-benar berguna hanya untuk gambar dunia nyata. Di sisi lain, cara ini bisa dipakai untuk mengetahui apakah sebuah gambar punya latar belakang yang sungguhan, dengan membandingkannya terhadap warna tepi rata-rata gambar. Perlu dicatat, warna dominan sebuah gambar lebih mungkin dipengaruhi kuat oleh warna latar belakangnya ketimbang oleh objek yang menjadi perhatian, yaitu objek yang biasanya berada di tengah atau dekat tengah gambar.
Warna tepi
Dengan memangkas berulang kali masing-masing dari keempat tepi gambar (paling banyak 2 sampai 3 piksel) lalu menghitung warna rata-rata tepinya, Anda bisa menentukan apakah gambar itu punya frame, dan seberapa tebal frame-nya. Apakah gambar itu punya latar belakang yang jelas. Atau apakah ada semacam pemisahan warna langit/darat atau dekat/jauh pada gambar secara keseluruhan. Dengan membandingkan rata-rata warna sisi terhadap rata-rata warna bagian tengah gambar, Anda bisa mengetahui apakah gambarnya seragam tanpa tema atau subjek utama, misalnya foto bentang alam yang kosong.
Histogram - pencocokan warna umum
Untuk metrik yang menyangkut jenis-jenis warna yang ada dalam sebuah gambar, dipakailah histogram dalam bentuk ini atau itu. Caranya dengan membuat larik 'bin warna' lalu menaikkan cacah tiap 'bin' setiap kali warnanya ditemukan. Nah, saya tidak membayangkan Anda menyimpan histogram besar untuk tiap gambar! Jadi Anda hanya akan menyimpan warna paling dominan dalam histogram itu, atau memakai jumlah bin yang jauh lebih sedikit (dengan lebih banyak piksel di tiap bin). Histogram 'bin warna' yang biasa sebenarnya tidak bekerja terlalu baik. Sebabnya, tiap warna selalu jatuh ke dalam satu bin. Yaitu tiap piksel dimasukkan ke tiap bin secara semua-atau-tidak-sama-sekali, tanpa memperhatikan seberapa dekat warna itu ke tepi sebuah bin. Ini pada gilirannya bukan metrik yang baik. Salah satu solusinya adalah membuat histogram dengan bin yang saling tumpang tindih. Jadi tiap warna (kecuali mungkin hitam atau putih) akan jatuh ke dalam dua bin warna. Nanti, saat gambar dibandingkan, warna yang berdekatan akan cocok dengan setidaknya salah satu bin itu. Alternatif lain adalah membuat histogram yang tiap warnanya menyumbang ke tiap 'bin' sesuai seberapa dekat warna itu ke pusat bin. Jadi warna di tepi sebuah bin sebenarnya membagi dirinya ke dua bin. Ini menghasilkan semacam histogram yang kabur, atau terinterpolasi, tetapi yang mewakili gambar dengan lebih akurat, terutama bila jumlah 'bin' warnanya sangat sedikit. Selain itu, histogram secara tradisional hanya berupa komponen grayscale sebuah gambar atau tiga komponen RGB terpisah. Tetapi ini bukan representasi yang baik. Anda bisa mencoba histogram Hue, Saturation, dan Luminance untuk mewakili gambar dengan lebih baik. Atau, mengapa membatasi diri pada histogram 1 dimensi? Bagaimana kalau warnanya dipetakan ke sekumpulan warna nyata di seluruh ruang warna! Yaitu, alih-alih mem-bin nilai 'merah' saja, mengapa tidak menghitungnya dalam bin warna 3 dimensi (dalam ruang warna apa pun yang paling cocok). Itu akan menghasilkan histogram yang benar-benar mewakili warna-warna yang ada dalam sebuah gambar. Metrik histogram 3 dimensi semacam itu bisa berupa larik sederhana berukuran, katakanlah, 8x8x8 atau 2048 bin. Yaitu metrik sebesar 2 Kbyte. Pencarian warna kemudian akan menemukan sejumlah bin tetangga yang tepat, lalu mengambil cacah terinterpolasi dari bin-bin di dekatnya. Cacah itulah yang mewakili jumlah warna yang 'dekat' dengan warna tersebut di dalam gambar!
Pemisahan warna latar depan/latar belakang
Dengan -colors Anda bisa mencoba memisahkan gambar menjadi bagian latar depan dan latar belakang, dengan menyusutkan gambar menjadi dua warna saja. Memakai filter -median lebih dulu akan menghilangkan pengaruh detail kecil, tepi garis, dan noise yang mungkin ada dalam gambar. Tentu saja cara ini kurang bagus untuk gambar mirip sketsa yang sebagian besar putih.
magick rose: -median 5 +dither -colors 2 \
-depth 8 -format %c histogram:info:-
Hasilnya menunjukkan warna merah dan abu-abu sebagai warna dominan dalam gambar. Trim/crop ke bagian tengah gambar kemudian semestinya menentukan mana latar depan dan mana latar belakang.
magick rose: -median 5 +dither -colors 2 \
-trim +repage -gravity center -crop 50% \
-depth 8 -format %c histogram:info:-
Hasilnya menunjukkan warna merah 'rose' sebagai warna latar depan yang dominan. Perhatikan bahwa gambar bentang alam bisa terpisah dengan cara berbeda: yang didapat adalah warna tanah di bagian bawah dan warna langit di bagian atas. Karena itu, melihat sekilas bagaimana warnanya terpisah bisa sangat berguna untuk menentukan tipe gambar. Selain itu, gambar dengan 'spam' teks sering menunjukkan gumpalan warna di salah satu sudut yang jauh lebih menonjol daripada bagian gambar lainnya. Kalau ketemu, ulangi dengan 3 warna, lalu hapus area itu dengan warna 'latar belakang' paling umum yang ditemukan sebelum melakukan uji akhir. Teknik ini kemungkinan cara yang bagus untuk memisahkan gambar ke dalam kelas seperti 'warna kulit', 'dedaunan', 'bentang alam', dan seterusnya.
Matriks warna rata-rata
Skema warna matriks tiga kali tiga ("-scale 3x3\!") adalah skema klasifikasi warna yang cukup masuk akal. Skema ini memisahkan dan mengelompokkan gambar yang mirip dengan sangat baik. Sebagai contoh, sketsa (semuanya nyaris putih), grayscale, bentang alam, bentang laut, ruangan, wajah, dan lain-lain, semuanya akan terpisah ke dalam kelompok dasar yang serupa (secara teori). Ini juga metrik yang masuk akal untuk mengindeks gambar demi menghasilkan Photo Mosaics. Keluaran format gambar NetPBM sangat cocok untuk menghasilkan metrik semacam itu, sebab ia bisa mengeluarkan nilai piksel saja sebagai angka teks. Ingat, ini akan menghasilkan hasil berdimensi 27 (3x3 warna dengan 3 nilai), jadi algoritma clustering multidimensi mungkin dibutuhkan. Apakah Anda tahu program/algoritma clustering 3d yang bagus? Sebagai contoh, berikut warna RGB 3 x 3 (pada depth 8) untuk logo IM.
magick logo: -scale 3x3\! -compress none -depth 8 ppm:- |\
sed '/^#/d' | tail -n +4
251 241 240 245 234 231 229 233 236 254 254 254
192 196 204 231 231 231 255 255 255 211 221 231
188 196 210
Cara di atas bisa diperbaiki dengan memakai nilai 16 bit, dan bila perlu memangkas 10% tepinya untuk membuang logo dan sampah frame yang mungkin sudah ditambahkan...
magick logo: -gravity center -crop 80% -scale 3x3\! \
-compress none -depth 16 ppm:- | sed '/^#/d' | tail -n +4
63999 59442 58776 62326 58785 58178 51740 54203 54965 65277 65262 65166
45674 47023 49782 56375 55648 55601 65535 65535 65535 52406 55842 58941
44635 48423 52881
Tentu saja, seperti metrik warna rata-rata sebelumnya, metrik ini juga bermasalah saat mencocokkan gambar yang warnanya sudah diubah, misalnya perubahan rona atau kecerlangan. (Lihat bagian berikutnya) Metrik ini juga bisa memisahkan gambar garis di dalam kelompoknya, meski hanya secara sangat umum. Gambar semacam itu tetap akan lebih dikelompokkan menurut warna 'kertas' latar belakangnya ketimbang menurut isinya, dan umumnya perlu 'ambang batas' kemiripan yang lebih kecil daripada gambar berwarna.
Matriks selisih warna
Masalah terbesar memakai warna secara langsung sebagai metrik adalah gambarnya jadi terikat pada satu warna umum tertentu. Artinya gambar apa pun yang sudah dicerahkan atau digelapkan, atau ronanya diubah, tidak akan dikelompokkan bersama. Salah satu solusinya adalah mengurangkan warna dominan atau warna rata-rata gambar dari metriknya, dan memakai matriks warna membuat hal itu mungkin. Di sini, misalnya, saya mengurangkan warna rata-rata bagian tengah dari semua warna di sekelilingnya dalam matriks.
magick logo: -gravity center -crop 80% -scale 3x3\! -fx '.5+u-p{1,1}' \
-compress none -depth 16 ppm:- | sed '/^#/d' | tail -n +4
51093 45187 41761 49419 44529 41163 38834 39947 37950 52371 51007 48152
32767 32767 32767 43469 41393 38587 52629 51279 48521 39500 41587 41926
31729 34168 35867
Perhatikan saya menambahkan .5 pada selisihnya, sebab nilai warna negatif tidak bisa disimpan dalam gambar. Pemakaian operator "-fx" yang lambat pun masih bisa diterima karena hanya 9 piksel yang diproses. Perhatikan pula bahwa piksel pusat ("32767 32767 32767" di awal baris kedua pada contoh di atas) tidak banyak berubah (perubahannya semata-mata karena error pembulatan kecil), dan bisa dibuang dari hasilnya sehingga metriknya menyusut menjadi 24 dimensi (nilai). Sebagai alternatif, Anda bisa mengurangkan warna rata-rata gambar dari kesembilan nilai warnanya.
magick logo: -scale 3x3\! \( +clone -scale 1x1 \) -fx '.5+u-v.p{0,0}' \
-compress none ppm:- | sed '/^#/d' | tail -n +4
38604 35917 34642 37011 33949 32441 32839 33841 33649 39447 39259 38369
23358 24377 25436 33538 33174 32426 39612 39434 38605 28225 30576 32319
22271 24381 27021
Ini juga bisa dikerjakan oleh pembanding metrik, bukan oleh pembuat metriknya. Metrik ini tetap memisahkan dan meng-cluster gambar berwarna dengan sangat baik, menempatkan gambar yang mirip berdekatan, terlepas dari perubahan warna umum atau kecerlangan. Meski begitu ia masih peka terhadap perubahan kontras. Modifikasi metrik ini sebenarnya bisa dilakukan pada saat proses perbandingan, sehingga Metrik matriks warna yang mentah tetap bisa dipakai sebagai metrik gambar standar untuk dikumpulkan, di-cache, dan dibandingkan. Inilah yang sekarang saya lakukan sendiri untuk perbandingan gambar berskala besar. Berbeda dengan rata-rata warna biasa, metrik ini bisa dipakai untuk membedakan gambar garis yang satu dari yang lain. Namun karena gambar garis memakai skala warna linear (semua warnanya jatuh pada satu garis di ruang metrik), selisih antar gambarnya kira-kira 1/3 dari selisih pada gambar berwarna. Karena itu ambang batas yang sangat berbeda diperlukan saat membandingkan gambar garis. Jadi tetap lebih baik memisahkan gambar garis dan gambar grayscale dari gambar berwarna. Dengan kata lain, inilah salah satu metrik terbaik yang sejauh ini saya temukan untuk gambar berwarna. Pastikan saja Anda menentukan lebih dulu gambar mana yang merupakan gambar garis, lalu bandingkan gambar-gambar itu secara terpisah dengan ambang batas yang jauh lebih rendah. Untungnya metrik itu sendiri bisa dipakai untuk memisahkan gambar menjadi grayscale, atau gambar berwarna linear. Saran dipersilakan.
Selisih terhadap tetangga
Cara di atas menghasilkan matriks 3x3, dengan piksel pusat dikurangkan, dan semua nilainya di-offset ke abu-abu sempurna. Namun metode yang lebih baik adalah, alih-alih menyimpan warna tiap sel, menghasilkan selisih antara tiap sel dan tetangganya (8 tetangga). Yaitu, alih-alih menyimpan warna sudut kiri-atas, simpan selisih antara sudut itu dengan sel tengah-atas, pusat, dan tengah-kiri. Tentu saja, bahkan dengan larik 3x3 yang kecil, hasilnya adalah signature berisi 12 selisih, meski selisih penuhnya tidak perlu dikodekan, cukup taraf selisih secara umum, misalnya sama, atau selisih positif/negatif yang besar/kecil. Cara ini jauh lebih mungkin menemukan gambar yang cocok bahkan di antara gambar dengan warna yang sangat berbeda, sebab warnanya sendiri sama sekali tidak berperan dalam signature itu. Pustaka perbandingan gambar 'libpuzzle' melakukan persis itu, hanya saja memakai matriks 9x9, dengan hanya piksel pusat tiap sel yang dirata-ratakan. Pustaka itu juga membatasi diri pada versi grayscale dari gambarnya. Tekniknya diuraikan lengkap dalam sebuah paper postscript, Image Signature for Any Kind of Image. Paper itu juga membahas cara menyimpan signature tersebut dalam basis data dan cara melakukan pencarian untuk menemukan gambar dengan signature yang mirip (tidak harus sama). Inilah paper pertama yang saya temukan yang benar-benar merinci cara melakukannya. :-)
Perceptual hash
Susutkan gambar menjadi 8x8 lalu hitung intensitas rata-ratanya. Tiap bit dari hash 64-bit itu bernilai 1 bila pikselnya di atas rata-rata, atau 0 bila di bawah rata-rata. Untuk membandingkan kemiripan dua gambar, cukup bandingkan hash-nya bit demi bit, lalu kembalikan jarak hamming. Makin dekat jarak hamming-nya, makin mirip kedua gambar itu. Apa pun di atas 21 / 64 dianggap tidak mirip. pHash tampaknya memakai pengodean YCbCr. Ada juga yang membicarakan cara bekerja langsung dengan DCT dari JPEG, dan yang paling menjanjikan bekerja dengan magnitudo / fase lalu memetakannya ke sistem koordinat log polar.
Mencocokkan gambar dengan lebih baik
Aneka catatan dan teknik yang belum saya coba, atau yang kurang berhasil, untuk membandingkan gambar yang lebih besar demi pencocokan gambar yang lebih tepat.
Warna segmentasi
Seperti terlihat, banyak metrik di atas memakai filter blur/median yang diikuti teknik pengurangan warna, yang pada dasarnya adalah upaya menyederhanakan gambar supaya lebih mudah diklasifikasikan. Namun kuantisasi warna sebenarnya tidak dirancang untuk keperluan itu. Tugasnya adalah mengurangi warna supaya detail penting gambar menonjol. Untuk perbandingan gambar, yang kita inginkan bukan menonjolkan fitur-fitur itu, melainkan menonjolkan area yang menarik untuk dibandingkan. Itulah tugas teknik warna terkait yang dikenal sebagai segmentasi... SELINGAN: dari Leptonica: segmentasi gambar adalah pembagian gambar menjadi wilayah-wilayah yang punya sifat berbeda. Operator ini menyatukan area berwarna serupa menjadi blok warna seragam dan membuang detail dari area itu. Lalu, saat kedua gambar dibandingkan, yang dibandingkan adalah area, bukan detail tingkat rendah dalam gambar. IM mengimplementasikan algoritma segmentasi, "-segment"; untuk rincian implementasinya lihat SegmentImage(). Contoh:
magick logo: -median 10 -segment 1x1 \
+dither -scale 100x100\! segment_image.gif
Satu masalahnya, -segment SANGAT lambat, dan tampaknya hanya bekerja untuk gambar yang lebih besar. Gambar kecil (seperti rose: atau logo: yang diskalakan ke 100x100) tampaknya hanya menghasilkan satu warna saja. Ini mungkin bug. Tentu saja gambarnya masih bisa diskalakan setelah disegmentasi, seperti yang kita lakukan di atas. Dengan begitu lebih banyak gambar bisa disimpan di memori untuk saling dibandingkan. Selain itu hasil segmentasinya tampaknya kurang bagus bila dibandingkan dengan algoritma segmentasi gambar yang disediakan Leptonica. Lihat Leptonica: Color Segmentation. Namun sebagai alternatif segmentasi IM, fungsi kuantisasi warna bisa disalahgunakan untuk menemukan area berwarna serupa. Contoh:
magick logo: -scale 100x100\! -median 3 \
-quantize YIQ +dither -colors 3 segment_image.gif
Kerugiannya, -color membatasi jumlah area warna yang boleh ada dalam sebuah gambar, sedangkan segment berusaha mempertahankan area yang serupa, berapa pun jumlah area yang sebenarnya ada dalam gambar (atau setidaknya begitulah semestinya).
Perbandingan tepi tanpa warna
Warna gambar terkenal tidak bisa diandalkan, terutama untuk gambar bergaya kartun. Pengguna yang berbeda bisa dengan mudah mewarnai ulang gambar semacam itu, menambahkan latar belakang berwarna lain, atau bahkan mengambil sketsa lalu mewarnainya. Salah satu cara mencocokkan gambar semacam itu adalah dengan melakukan pengurangan warna dasar seperti metode di atas, tetapi kemudian, alih-alih membandingkan gambar berdasarkan warna hasilnya, Anda melakukan deteksi tepi dan pemrosesan lanjutan sehingga hanya garis luar dari perubahan warna yang paling penting yang dipakai untuk metrik dan perbandingan gambar. Sebagai contoh...
magick logo: -scale 100x100\! -median 3 \
-quantize YIQ +dither -colors 3 -edge 1 \
-colorspace gray -blur 0x1 outline_image.gif
Alternatif lain mungkin memakai -lat (Local Area threshold) untuk deteksi tepi, yang bisa memberi kendali yang lebih baik...
magick logo: -scale 100x100\! -median 3 \
-quantize YIQ +dither -colors 3 \
-lat 3x3-5% -negate \
-colorspace gray -blur 0x1 outline_image.gif
Tentu saja untuk membandingkannya Anda akan memakai metode perbandingan gambar garis.
??? bagaimana cara membandingkan gambar garis yang benar-benar bisa dipakai ???
Kalikan gambar-gambarnya lalu lihat apakah gambar hasilnya menambah atau mengurangi intensitas garisnya. Garis yang tidak cocok akan menjadi hitam.
Kamera web Apa yang berubah pada kamera tetap
Sedang dikerjakan
Walter Perry
![[IM Output]](../static/img/images/bag_frame1.gif)
![[IM Output]](../static/img/images/bag_frame2.gif)
![[IM Output]](../static/img/compare/compare.gif)
![[IM Output]](../static/img/compare/bag_frame1.jpg)
![[IM Output]](../static/img/compare/compare_lossy_jpeg.gif)
![[IM Text]](../static/img/compare/greyscale_test.txt.gif)
![[IM Output]](../static/img/compare/wmark_dragon.jpg)
![[IM Output]](../static/img/compare/wmark_bw_test.png)
![[IM Text]](../static/img/compare/wmark_stats.txt.gif)
![[IM Output]](../static/img/compare/granite.jpg)
![[IM Output]](../static/img/compare/granite_bw_test.png)
![[IM Text]](../static/img/compare/granite_stats.txt.gif)