[PYTHON] Programme pour rechercher la même image

Programme pour rechercher la même image

C'est un programme qui trouve des images en double dispersées dans un certain dossier Calculez la distance entre les vecteurs après avoir réduit et monochrome l'image et l'avoir vectorisée tout en gardant les caractéristiques de l'image au minimum. Les objets avec une distance de 0 ou proche de 0 sont considérés comme la même image. Un tel programme.

Rendre l'image aussi petite que possible

Puis convertissez-le en numpy.array pour un calcul plus facile.

def img2vec(filename):
    img = Image.open(filename)
    img = img.resize((200, 200), resample=Image.BILINEAR) #Rétrécir
    img = img.convert('1') #Binarisation
    #img.save(get_mono_filename(filename)) #Si vous voulez vérifier l'image
    return np.array(img)

La taille de 200 x 200 définie ici peut être trop grande, et il a fallu environ 9 heures pour exécuter ce programme pour 22000 feuilles, donc je pense qu'environ 50 x 50 est bien.

Comparer des images

Trouvez la distance entre les vecteurs avec numpy, il est très facile d'utiliser numpy.

def normdiff(vec1, vec2):
    norm = np.linalg.norm(vec1 - vec2)
    return norm

Code de test

    norm = normdiff(img2vec("picture1.bmp"), img2vec("picture2.bmp"))
    print(norm)

Si vous exécutez un code de test comme celui-ci en utilisant la fonction ci-dessus, à quelle distance sont les images? Est affiché.

Toute la source

import csv
import datetime
import glob
import multiprocessing as mulproc
import numpy as np
import os
from PIL import Image
import sys

def log(*args):
    timestr = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
    body = " ".join([timestr] + [str(v) for v in args])
    print(body)
    with open("log.txt", mode="a", encoding="utf-8") as wf:
        wf.write(body + "\n")

def get_mono_filename(filename):
    dirname, filename = os.path.split(filename)
    return os.path.join("mono", filename)

def img2vec(filename):
    # ANTIALIAS
    # BILINEAR
    # BICUBIC
    # NEAREST
    img = Image.open(filename)
    img = img.resize((200, 200), resample=Image.BILINEAR)
    img = img.convert('1')
    #img.save(get_mono_filename(filename)) #Si vous voulez vérifier l'image
    return np.array(img)

def normdiff(vec1, vec2):
    norm = np.linalg.norm(vec1 - vec2)
    return norm

def walk_img_files(walk_dir):
    for root, dirs, files in os.walk(walk_dir):
        yield root
        for file in files:
            yield os.path.join(root, file)

def is_picture_filename(filename):
    extensions = ["png", "jpg"]
    for ext in extensions:
        if filename.endswith("." + ext): return True
    return False

def save_vector(filename, vec):
    with open(filename, mode="w", encoding="utf-8") as wf:
        writer = csv.writer(wf, lineterminator='\n')
        writer.writerows(vec)

def save_labels(filenames):
    with open("./labels.txt", mode="w", encoding="utf-8") as wf:
        wf.write("\n".join(filenames))

def create_vector_dump(search_dir):
    files = list(walk_img_files(search_dir))
    img_files = []
    for f in files:
        if is_picture_filename(f): img_files.append(f)

    for img_file in img_files:
        vec = img2vec(img_file)
        dir, filename = os.path.split(img_file)
        save_vector(os.path.join("vector", filename) + ".vector", list(vec.astype(int)))
    save_labels(img_files)
    return

def load_labels():
    with open("./labels.txt", mode="r", encoding="utf-8") as rf:
        body = rf.read()
        labels = body.split("\n")
        labels = [l for l in labels if len(l) > 0]
        return labels

def load_vecs(labels):
    log("start load vectoes")
    vecs = []
    for i, l in enumerate(labels):
        dirname, filename = os.path.split(l)
        filename = os.path.join("vector", filename + ".vector")
        vecs.append(np.loadtxt(filename, delimiter=","))
        log("load vectoes {}/{} complete".format(i, len(labels)))
    log("end load vectoes")
    return np.array(vecs)

def save_results(rows):
    with open("results.csv", mode="w", encoding="utf-8") as wf:
        writer = csv.writer(wf, lineterminator='\n')
        writer.writerows(rows)

def create_join_imgs(filename, vecs):
    vecs = np.concatenate(vecs, axis=1)
    vecs *= 255
    img = Image.fromarray(vecs).convert("1")
    img.save(filename)

def create_dup_imgs(approximates, vecs, labels):
    for i, approximate in enumerate(approximates):
        orig_label = labels[i]
        if len(approximate) < 1: continue
        img_vecs = [vecs[i]] + [vecs[ai] for ai in approximate]
        dirname, filename = os.path.split(orig_label)
        filename = os.path.join("dupulicate", filename)
        img = create_join_imgs(filename, img_vecs)

class EnumApproximate:
    def __init__(self):
        labels = load_labels()
        #labels = labels[0:1000]
        self.labels = labels
        vecs = load_vecs(labels)
        self.vecs = vecs
        self.threthold = float(10.0)

    def enum_approximate(self, index):
        indexes = []
        vec = self.vecs[index]
        for i, v in enumerate(self.vecs):
            if i == index: continue
            dif = normdiff(vec, v)
            if dif <= self.threthold: indexes.append(i)
        return indexes

    def exec(self):
        log("start")
        approximates = []
        for i in range(len(self.labels)):
            log("enum_approximate vectoes {}/{} complete".format(i, len(self.labels)))
            approximates.append(self.enum_approximate(i))
        rows = []
        for i in range(len(self.labels)):
            idxs = approximates[i]
            cols = [self.labels[i]] + [self.labels[ii] for ii in idxs]
            rows.append(cols)
        save_results(rows)
        create_dup_imgs(approximates, self.vecs, self.labels)
        log("end")

def main():
    x = EnumApproximate()
    x.exec()

if __name__ == '__main__':
    create_vector_dump(r"O:\picture\Expédier ceci")
    main()

À propos de l'exécution

Créez un dossier appelé vector, dupulicate dans la même hiérarchie que la source

create_vector_dump(r"O:\picture\Expédier ceci")

L'exécution de cette ligne créera une image vectorisée CSV dans le dossier vectoriel. Exécutez main lorsque la vectorisation est terminée. Vous pouvez exécuter les deux en même temps.

Une fois l'exécution terminée, un fichier de type CSV appelé result.csv et une image dans laquelle les images dupliquées sont connectées au dossier dupliqué sont créés.

43164116_big_p1.png

Le trouver ne signifie pas supprimer les doublons, donc si vous voulez faire quelque chose à partir de là, vous pouvez écrire un script basé sur result.csv.

Recommended Posts

Programme pour rechercher la même image
Programme Python qui recherche le même nom de fichier
Algorithme de hachage pour déterminer la même image
[Python] Un programme qui arrondit le score
Un programme shell qui affiche une séquence de Fibonacci
Création d'une image trompeuse pour le modèle de génération de légende
[Python] Un programme qui compte le nombre de vallées
[Python] Un programme qui compare les positions des kangourous.
L'image est Namekuji
Une histoire sur l'amélioration du programme pour le remplissage partiel des données d'image binarisées 3D
Essayez une recherche similaire de recherche d'images à l'aide du SDK Python [Recherche]
Un programme qui appuie et relâche simplement la touche Échap
[Python] Un programme qui trouve les types d'oiseaux les plus courants
[Golang] Un programme qui détermine le tour avec des nombres aléatoires
J'ai écrit un script qui divise l'image en deux
Un programme qui redimensionne automatiquement la taille d'image requise pour les icônes d'application iOS en Python
L'histoire de l'exportation d'un programme
Écrivons un programme de simulation simple pour le "problème de Monty Hall"
[Ev3dev] Créez un programme qui capture LCD (écran) en utilisant python
Ecrire un programme qui abuse du programme et envoie 100 e-mails
Un programme qui répond à quelques questions et prédit la prochaine réponse
J'ai fait un programme qui calcule automatiquement le zodiaque avec tkinter
[Python] Un programme qui fait pivoter le contenu de la liste vers la gauche
Essayez de générer une image de veste de type death metal avec DCGAN + grattez le site de base de données de métaux pour cela
Comprendre les probabilités et les statistiques qui peuvent être utilisées pour la gestion des progrès avec un programme python
Téléchargez les n principales recherches d'images Google
Divulguer le savoir-faire qui a créé un service de recherche d'images similaire pour les actrices audiovisuelles grâce à l'apprentissage profond par chainer
[Python] Un programme qui crée des escaliers avec #
[Python] Un programme qui calcule le nombre de segments de chocolat qui remplissent les conditions
Si vous créez un programme qui démarre / arrête automatiquement l'environnement de vérification pour la demande d'extraction, la vérification a progressé.
Classe qui atteint l'API de DMM
Découvrez les dates du tournoi fou
[Python] Un programme qui calcule le nombre de chaussettes jumelées
Apprendre le latin dans le but d'écrire un programme d'analyse de phrases latines (partie 1)
Changer la liste dans l'instruction for
Un programme qui récupère en douceur toute rubrique d'actualité
Un programme python qui redimensionne une vidéo et la transforme en image
Un programme qui utilise Python pour lire des fichiers indésirables
Configurer un serveur qui traite plusieurs connexions en même temps
J'ai créé un LINE BOT qui renvoie une image de riz terroriste en utilisant l'API Flickr
Une solution de contournement simple pour que les robots essaient de publier des tweets avec le même contenu
Trouvez un bâtiment de la même hauteur que Shin Godzilla sur Google Earth
[Python] Un programme qui trouve les valeurs minimales et maximales sans utiliser de méthodes
Affichons un template simple idéal pour le premier Django
[Python] Un programme qui calcule la différence entre les valeurs totales diagonales
[Python] Un programme qui calcule le nombre de mises à jour des enregistrements les plus élevés et les plus faibles
Transformez plusieurs listes avec l'instruction for en même temps en Python
Un modèle qui identifie la guitare avec fast.ai
Création d'un wrapper Python pour l'API Qiita
Nogizaka46 Un programme qui enregistre automatiquement les images de blog
Faire un histogramme pour le moment (matplotlib)
Un programme qui supprime les instructions en double en Python
Python: préparez un sérialiseur pour l'instance de classe:
Traitement d'image? L'histoire du démarrage de Python pour
Détecter les dossiers avec la même image dans ImageHash
Un programme qui notifie l'état de fonctionnement des équipements de photographie d'usine entièrement automatiques
Un script python qui obtient le nombre de travaux pour une condition spécifiée sur Indeed.com
Un programme qui demande quelques kilogrammes pour atteindre l'IMC et le poids standard [Python]