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.
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.
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
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é.
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()
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.
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