Hilangkan Duplikasi Foto

By | July 30, 2024
Print Friendly, PDF & Email
1,306 Views

— Mendeteksi Gambar Serupa atau biasa remove duplicate image –  Hilangkan Duplikasi Foto akan saya gunakan untuk mengurangi file media pada WhatsApp yang kadang isinya belasan ribu file, bila kalian sudah membaca akses storage ponsel yang menggunakan bahasa C# dengan Media Transfer Protocol. Belasan ribu file media yang isinya gambar semua tentu tidak semuanya dipakai! akan terasa sekali kalau kita menggunakan storage jenis HDD yang cukup lambat!

Namun walaupun kalian telah menggunakan storage bertipe SSD untuk meningkatkan akses baca tulis, maka alangkah baiknya kalian menerapkan Mendeteksi Gambar Serupa – remove dupilcate image sehingga ukurannya yang belasan ribu tersebut bisa dikurangi lagi. Ada beberapa aplikasi android untuk deteksi gambar serupa – remove duplicate image

tapi saya tertarik membuat algoritma tersendiri atau kalian tertarik ingin tahu cara kerja aplikasi hilangkan duplikasi foto tersebut?

Algoritma deteksi gambar serupa – remove duplicate image

Algoritma deteksi gambar serupa – remove duplicate image yang paling mudah yaitu menggunakan teknik hashing. Fungsi hash/hash function adalah sebuah pemetaan dari sebuah himpunan asal/domain (berupa teks/gambar/atau sembarang object) yang memiliki panjang/ukuran yang beragam ke suatu nilai/vektor/string yang (biasanya) memiliki panjang tetap. Hasil pemetaan-nya sering disebut sebagai nilai hash (terkadang disebut juga hash codes, digests, atau hashes) atau sering disebut dengan Perceptual image hashing

Kegunaan hash value

Fungsi hash digunakan di banyak aplikasi, baik cryptography, database, sampai di data science dalam pengolahan data besar. Fungsi Hash juga bermacam-macam, salah satu yang paling tenar mungkin Secure Hash Algorithm 1 (SHA-1) dalam cryptographic hashing.  Nah contoh yang akan kita gunakan dengan tujuan untuk deteksi gambar serupa – remove duplicate image dengan menghitung jarak antar hash value. Tentu jika ada 2 file gambar hanya berbeda nama file maka akan dianggap 2 file yang berbeda, nah hash function yang akan kita gunakan lebih dari itu! misalkan terjadi resize, terjadi perubahan content (dikasih coretan).

See also  Corner Detection

Library hash Image

Library hash image ada banyak sekali dan yang paling gampang menggunakan bahasa Python yaitu

  1. imagehash
  2. imagededup

Imagedash sesuai dengan dokumentasinya menggunakan beberapa algoritma seperti average, perceptual, difference, dan wavelet

The image hash algorithms (average, perceptual, difference, wavelet) analyse the image structure on luminance (without color information). The color hash algorithm analyses the color distribution and black & gray fractions (without position information).

Imagededup lebih advance lagi karena banyak menggunakan library tensorflow

Mendeteksi Gambar Serupa – remove dupilcate image secara mudah gunakan saja library imagedash, yuk kita buat algoritmanya secara visual menggunakan excel saja terlebih dahulu. Misalkan saja kita punya record file ada 10, maka perhitungannya menggunakan teknik combination dengan r = 2, maksudnya adalah semua file akan dihitung jaraknya dengan file lain tapi tidak dengan dirinya sendiri.

jadi file 1 akan dihitung jarak terhadap 2,3,4,5,6,7,8,9,10, kemudian file 2 akan dihitung jarak terhadap 3,4,5,6,7,8,9,10 dan begitu seterusnya. Kita gunakan library numpy dan itertools

import numpy as np
from itertools import combinations

n = 10 #jumlah file
comb  = combinations(np.arange(1,n+1),r=2)
records = list()
# Print the obtained permutations
for idx in list(comb):
    print(idx)

kalian bisa melihat hasilnya sebagai berikut

(1, 2)
(1, 3)
(1, 4)
(1, 5)
(1, 6)
(1, 7)
(1, 8)
(1, 9)
(1, 10)
(2, 3)
(2, 4)
(2, 5)
(2, 6)
(2, 7)
(2, 8)
(2, 9)
(2, 10)
(3, 4)
(3, 5)
(3, 6)
(3, 7)
(3, 8)
(3, 9)
(3, 10)
(4, 5)
(4, 6)
(4, 7)
(4, 8)
(4, 9)
(4, 10)
(5, 6)
(5, 7)
(5, 8)
(5, 9)
(5, 10)
(6, 7)
(6, 8)
(6, 9)
(6, 10)
(7, 8)
(7, 9)
(7, 10)
(8, 9)
(8, 10)
(9, 10)

Jadi sudah paham ya, kita menggunakan teknik combination, yuk sekarang kita coba saja, misalkan saya punya folder data yang berisi gambar *.jpg. Langsung kita lakukan enumerasi sebagai berikut dan menyimpannya dalam bentuk list()

from PIL import Image
import imagehash
import glob

files = glob.glob("data/*.jpg")
n = len(files)
nilai_hash = list()
for file in files:
    nilai_hash.append(imagehash.average_hash(Image.open(file)))

Jadi semua file akan dihitung nilai hash nya, langkah selanjutnya melakukan perhitungan jarak dan menerapkan nilai ambang batas. Variabel global records = list() digunakan untuk menyimpan hasil setiap perhitungan jika memenuhi syarat jarak<jarak_minimal

import numpy as np
from itertools import combinations
comb  = combinations(np.arange(0,n),r=2)
records = list()
jarak_minimal = 5
for idx in list(comb):
    a = idx[0]
    b = idx[1]
    jarak = (nilai_hash[a]-nilai_hash[b])
    print(files[a]+" --> "+file[b]+" : "+str(jarak))    
    record ={'file1':files[a],'file2':files[b],'jarak':jarak}
    if(jarak<jarak_minimal):
        records.append(record)

Agar tampil menarik dibuatlah data frame

import pandas as pd

final = pd.DataFrame(records)
print(final)

hasilnya

         file1        file2  jarak
0  data\12.jpg  data\13.jpg      2
1   data\7.jpg   data\8.jpg      2
2   data\7.jpg   data\9.jpg      2
3   data\8.jpg   data\9.jpg      0

artinya file 12.jpg mirip dengan 13.jpg dan begitu seterusnya.

See also  Simple Convert JPG ke PDF via Python

Perbaikan kode

Pada contoh diatas harus ada beberapa perbaikanya, kalian bisa melihat hasil mengenai file 7.jpg; 8; jpg; dan 9.jpg

         file1        file2  jarak
0  data\12.jpg  data\13.jpg      2
1   data\7.jpg   data\8.jpg      2
2   data\7.jpg   data\9.jpg      2
3   data\8.jpg   data\9.jpg      0

Kira-kira mana yang harus didelete? karena artinya adalah 3 file tersebut harus didelete dengan meninggalkan satu file saja, untuk hal tersebut kalian gunakan teknik meta file yaitu selain membaca nama file juga membaca file tersebut di create. Sehingga misalkan saja yang akan dihapus 7.jpg dan 9.jpg karena 8.jpg baru saja dibuat/create! hemm… itu PR kalian saja…untuk melengkapi perbaikan kodenya sendiri, saya kasih bocoran cara mengelola date time di Python

Hash Image di Java

Tentu bila kalian ingin membuat aplikasi berbasis android java, maka library diatas tidak bisa digunakan. Ada beberapa library/kode yang bisa kalian pakai salah satunya adalah

  1. https://github.com/srch07/Duplicate-Image-Finder-API kode/library ini simple tapi sayang nya tidak robust! kalau beda ukuran width dan height nya maka tidak bisa!
  2. http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html pembahasan mengenai algoritma phash.org
  3. https://github.com/krishnact/jphash bisa juga kalian gunakan
  4. https://reposhub.com/java/imagery/KilianB-JImageHash.html yang kode ada di https://github.com/KilianB/JImageHash

Saya sarankan untuk menggunakan point 4 karena lebih robust, bila ingin mencoba bisa gunakan gradle (kalau menggunakan gradle ada error di JDFX nya) dan maven https://mvnrepository.com/artifact/dev.brachtendorf/JImageHash/1.0.0 . Mari kita coba menggunakan maven saja, oiya saya memilih PerceptiveHash berdasarkan fitur Frequency dimana Hash based on Discrete Cosine Transformation. Smaller hash distribution but best accuracy / bitResolution sehingga semakin kecil nilainya semakin tidak sensitif.

Algo / Resolution 2^6 = 64 bit 2^8 = 256 bit 2^12 = 4096 bit 2^18 = 262144 bit
Perceptive Hash

Kode yang saya gunakan u ntuk menghitung mendeteksi gambar serupa atau biasa remove duplicate image yaitu

File lokasi = new File("D:\\C# akses storage ponsel\\data");
File [] files = lokasi.listFiles();
HashingAlgorithm hasher = new PerceptiveHash(128);
Map map = new HashMap();
int index=0;
for(File f : files){                
   Hash hash = hasher.hash(f);
   map.put(index,hash);
   index++;
}
double ambang_batas = .2;
for(int i=0;i<map.size();i++){
   for(int j=i;j<map.size();j++){
      if(i!=j){                        
         String a= files[i].getName();
         String b= files[j].getName();                        
         Hash hash0 = (Hash)map.get(i);
         Hash hash1 = (Hash)map.get(j);                        
         double similarityScore = hash0.normalizedHammingDistance(hash1);
         if(similarityScore<=ambang_batas){
            System.out.println(a+" , "+b+": "+similarityScore);
         }
            
      }
      
   }
}

hasilnya

12.jpg , 13.jpg: 0.17424242424242425
7.jpg , 8.jpg: 0.1590909090909091
8.jpg , 9.jpg: 0.16666666666666666

 

See also  Python Pandas Merging DataFrames