Aus dem von PIXTA gesammelten Katzenbild habe ich versucht, mit möglichst geringem Aufwand nur den Katzenteil zu extrahieren.
Das Trennen von Vordergrund und Hintergrund vom Bild wird als Mattierung bezeichnet. Es scheint eine Hauptfunktion in Photoshop zu sein, und im Fall von Gimp entspricht die Funktion "Vordergrundextraktion" dieser Funktion. Es scheint, dass das allgemeine Verhalten darin besteht, das Bild in drei Typen zu unterteilen, "Vordergrund", "Hintergrund" und "entweder", und die Grenze durch Betrachten der Bildmerkmale in jedem Bereich zu bestimmen.
Es scheint schwierig zu sein, diesen Prozess zu automatisieren, und im Rahmen meiner Forschung konnte ich nur eine Methode namens Deep Automatic Portrait Matting finden, die nur Personen aus Porträtfotos extrahiert.
Abgesehen davon gab es ein Papier über eine Methode zum automatischen Generieren von Informationen (Trimap), die zum Mattieren verwendet wurden.
Eine automatische Mattierung ist jedoch nicht immer möglich, solange eine entsprechende Trimap generiert werden kann. Tatsächlich gibt es bei der Verarbeitung mit Gimp usw. viele Situationen, in denen die Vordergrund- / Hintergrundbeurteilung nicht als erwartet eingestuft wird und eine Feineinstellung erforderlich ist.
Als weiteren Ansatz habe ich die Verwendung der semantischen Segmentierung in Betracht gezogen. Die semantische Segmentierung unterscheidet verschiedene Objekte pixelweise für ein einzelnes Eingabebild.
In dem zuvor geschriebenen Artikel habe ich geschrieben, dass ChainerCV auch die semantische Segmentierung unterstützt, aber das als Vorlernmodell erstellte Modell ist CamVid. Es basiert auf Trainingsdaten, die als Datensatz bezeichnet werden, und unterstützt 11 Klassen wie Himmel, Straße, Auto und Fußgänger. Es gibt keine Informationen über die Katze, mit der ich diesmal umgehen möchte.
Bei der Suche nach anderen Implementierungen und Datensätzen für die semantische Segmentierung wurde Keras-Implementierung von DilatedNet in [PASCAL VOC2011 challange](http: //host.robots.ox) gefunden. Ich verteilte es einschließlich eines trainierten Modells unter Verwendung eines Datensatzes, der auf dem Datensatz .ac.uk / pascal / VOC / voc2012 /) basiert, und entschied mich daher, es dieses Mal zu verwenden.
Sie können es verwenden, indem Sie den Code klonen, alle Python-Module installieren, die die Abhängigkeiten von require.txt erfüllen, und das Pre-Learning-Modell herunterladen. Da wir das alte Keras- und TensorFlow-Backend (0.12.1) verwenden werden, ist es eine gute Idee, eine dedizierte virtuelle Umgebung zu haben.
$ pip install -r requirements.txt
$ curl -L https://github.com/nicolov/segmentation_keras/releases/download/model/nicolov_segmentation_model.tar.gz \
| tar xvf -
$ python predict.py --weights_path \
conversion/converted/dilation8_pascal_voc.npy \
images/cat.jpg
dilation8_pascal_voc.npy ist die Modelldatei vor dem Training. Durch die Verarbeitung der enthaltenen Bilder / cat.jpg wird eine Datei mit dem Namen images / cat_seg.png generiert.
Verwenden wir dieses Modell, um ein unbekanntes Bild zu verarbeiten. Leider ist bei dieser Implementierung die Größe des Eingabebilds begrenzt, und es scheint, dass es nur verarbeitet werden kann, wenn die Breite und Höhe weniger als ungefähr 500 betragen. Nachdem ich das Bild im Voraus auf eine Größe geändert hatte, die diese Grenze erreicht, habe ich versucht, es zu verarbeiten.
Zu verarbeitendes Bild:
Segmentierungsausgabe
Der als Katzenbild identifizierte Bereich wird durch die Farbe # 400000 (R: 0x40, G: 0x00, B: 0x00) identifiziert. Auf den ersten Blick scheint es zu funktionieren. Wenn Sie sich danach auf jedes Pixel dieses Bildes beziehen, können Sie das gewünschte Ergebnis erzielen, indem Sie den anderen bewerteten Teil als das Katzenbild aus dem Originalbild ausfüllen.
Wenn Sie sich die Grenzen genau ansehen, werden sie jedoch nicht genau nach den numerischen Werten unterteilt.
Wie Sie sehen können, sind die Werte an den Rändern leicht unscharf. Wenn Sie also einfach die absoluten Werte der Segmentierungspixel vergleichen, um festzustellen, ob es sich um ein Vordergrundbild handelt, fehlt dieser Teil des Bildes.
Als Ergebnis verschiedener Gedanken und Versuche habe ich numpys linalg.norm verwendet, um den Abstand zwischen der Farbe des Segmentierungspixels und # 400000 zu berechnen. Wenn es innerhalb einer bestimmten Zahl liegt, wird festgestellt, dass es sich um ein Katzenbildpixel handelt. Ich tat. Das Ergebnis der Betrachtung des Bereichs entsprechend 32, der die Hälfte von 64 ist, als gültig ist wie folgt.
Es fühlt sich gut an. Der Code zur Ausgabe dieses Ergebnisses ist unten dargestellt.
# -*- coding: utf-8 -*-
import argparse
import os, sys
from PIL import Image
import numpy as np
def get_args():
p = argparse.ArgumentParser()
p.add_argument("--contents-dir", '-c', default=None)
p.add_argument("--segments-dir", '-s', default=None)
p.add_argument("--output-dir", '-o', default=None)
p.add_argument("--cat-label-vals", '-v', default="64,0,0")
args = p.parse_args()
if args.contents_dir is None or args.segments_dir is None or args.output_dir is None:
p.print_help()
sys.exit(1)
return args
def cat_col_array(val_str):
vals = val_str.split(',')
vals = [int(i) for i in vals]
return vals
def cmpary(a1, a2):
v1 = np.asarray(a1)
v2 = np.asarray(a2)
norm = np.linalg.norm(v1-v2)
if norm <= 32:
return True
return False
def make_images(cont_dir, seg_dir, out_dir, cat_vals):
files = []
for fname in os.listdir(cont_dir): # make target file list
seg_fname = os.path.join(seg_dir, fname)
if os.path.exists(seg_fname):
files.append(fname)
for fname in files:
print("processing: %s" % fname)
c_fname = os.path.join(cont_dir, fname)
cont = np.asarray(Image.open(c_fname)).copy()
s_fname = os.path.join(seg_dir, fname)
seg = np.asarray(Image.open(s_fname))
width, height, _ = seg.shape
for y in range(height):
for x in range(width):
vals = seg[x, y]
if not cmpary(vals, cat_vals):
cont[x, y] = [255, 255, 255]
out = Image.fromarray(cont)
o_fname = os.path.join(out_dir, fname)
out.save(o_fname)
def main():
args = get_args()
cat_vals = cat_col_array(args.cat_label_vals)
make_images(args.contents_dir, args.segments_dir, args.output_dir,
cat_vals)
if __name__ == '__main__':
main()
Wenn das diesmal verwendete Modell auf alle von Pixabay gesammelten und ausgewählten Bilder angewendet wurde, wurden nicht immer 100% erwartete Ergebnisse angezeigt. Es gibt Fälle, in denen beurteilt wird, dass es Merkmale für einen der verbleibenden 19 Typen außer Katzen gibt.
Bei der Verarbeitung des folgenden Bildes wurde ein Teil des Körperteils als Hund identifiziert.
Violett-ähnlicher Farbton (# 400080) ist der Bereich, der als Hund identifiziert wird. Natürlich finde ich, dass Hunde mit dieser Farbe relativ teuer sind. Wenn Sie dieses Ergebnis dem vorherigen Skript geben, sieht es folgendermaßen aus:
Da das diesmal erstellte Bild fast keine Hunde enthält, kann es möglich sein, den als Hund eingestuften Bereich zu verlassen.
Schwarze Katzen sind auf dem Bild nur schwer sauber zu erfassen, daher scheint es wahrscheinlich, dass Probleme in Bezug auf Diskriminierung auftreten.
Der Schattenteil ist ein Teil der Katze geworden, und der Körperteil, der nur schwarz aussieht, ist verschwunden.
Dieses Mal werden die URLs zu den Daten, die für die Segmentierung / Mattierung bestimmt sind, aufgelistet und auf github veröffentlicht.
1100 Es wird ein kleines Bild sein.
Ich denke, dass die edge2cats von pix2pix auch mit dieser Datenmenge bis zu einem gewissen Grad reproduziert werden können, also werde ich es tatsächlich lernen.
Außerdem möchte ich das Papier lesen, um mein Verständnis der Struktur von SegNet zu vertiefen, die diesmal mit DilatedNet und ChainerCV verwendet werden kann. Außerdem möchte ich versuchen, die in der DilatedNet Keras-Implementierung verwendeten Trainingsdaten mit SegNet von ChainerCV zu lernen.
Recommended Posts