Ich möchte das Bild entlang der Kontur anstelle des Rechtecks zuschneiden [Python OpenCV]

Zweck

Ich möchte mit OpenCV den Umriss eines Objekts in einem Bild abrufen und ausschneiden. Wenn ich es untersuche, kann ich nur das Muster finden, das durch das umschreibende Rechteck / Quadrat ausgeschnitten ist, selbst in verschiedenen Konturen. Ich möchte nur das Objekt so ausschneiden, wie es ist.

Denkweise

Die einzige Möglichkeit, ein Bild mit OpenCV + Python zuzuschneiden, besteht darin, den Pixelbereich des Originalbilds anzugeben, z. B. img [10: 100, 20: 100].

Schneiden Sie also zuerst mit dem umschreibenden Rechteck aus und erstellen Sie dann eine Leinwand mit der Größe des umschreibenden Rechtecks. Daten werden in den erfassten Konturinformationen organisiert, und der Maximalwert und der Minimalwert werden für jede Zeile erfasst und zu einem Array verarbeitet. Wenn Sie auf der transparenten Leinwand, die Sie zuvor erstellt haben, Zeile für Zeile zwischen dem Minimum und dem Maximum wechseln, holen Sie es aus dem Originalbild und zeichnen Sie es ..., Es scheint, dass wir es Zeile für Zeile wiederholen sollten.

Gehen!

Code

import cv2
import numpy as np
from pprint import pprint
from copy import deepcopy
import sys
import os


#Graustufenkonvertierung des Eingabebildes> Binarisierung, Rückgabe des binärisierten Bildes
def getBinary(im):
    im_gray = cv2.cvtColor(im , cv2.COLOR_BGR2GRAY) 
    return cv2.threshold(im_gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1] 

#Holen Sie sich das umschreibende Rechteck
def getBoundingRectAngle(contour):
    #Da die Array-Struktur mehrfach ist, machen Sie sie einmal zu einem einfachen Array(point [x y])
    contour = list(map(lambda point: point[0], contour))
    x_list = [ point[0] for point in contour ] # width
    y_list = [ point[1] for point in contour ] # height
    return  [min(x_list), max(x_list), min(y_list), max(y_list)]

#Ausgeschnitten
def getPartImageByRect(img, rect):
    #[y-Achse, x-Achse]
    return img[ rect[2]:rect[3], rect[0]:rect[1],]

def getCropData(contour, main_axis=0):
    target_axis =  1  if main_axis == 0 else 0

    #axis = 0 = x 
    #axis = 1 = y 
    contour = list(map(lambda i: i[0], contour))
    

    axis_point_list = set([ point[main_axis] for point in contour ]) # unique
    arr = []

    for val in axis_point_list:
        #Ruft ein Array von x mit einem bestimmten Wert von y aus dem Konturarray ab
        target_axis_point_list = list(filter(lambda i: i[main_axis] == val, contour))
        tmp_list = [ i[target_axis] for i in target_axis_point_list ] # 
        arr.append( [ val, min(tmp_list), max(tmp_list)] )
    return arr

##Ermitteln Sie den x-Koordinatenbereich entlang der y-Achse
def doCropY(input_im,  points, rect) :
    height = rect[3]-rect[2]
    width = rect[1]-rect[0] 
    left = rect[0]    
    top = rect[2]
    output_im = np.zeros((height, width, 4), np.uint8)

    for point in points :
        for x in range(0, width) :
            #Bildkoordinaten eingeben
            in_y = point[0]
            in_x = x + left
            in_x_min = point[1]
            in_x_max = point[2]

            #Bildkoordinaten ausgeben
            out_y = point[0] - top
            out_x = x
            out_x_min = point[1] - left
            out_x_max = point[2] - left

            #Kopieren Sie vom Originalbild in das neue Bild, wenn dies der maximale und minimale Bereich der x-Achse ist
            if( out_x_min < x  and x < out_x_max):
                output_im[out_y : out_y + 1, out_x : out_x + 1, ] = input_im[in_y : in_y + 1, in_x : in_x + 1, ]
    return output_im


##Für das Bild, das einmal extrahiert wurde
##Ermitteln Sie den y-Koordinatenbereich entlang der x-Achse
def doCropX(im, points, rect):
    height = rect[3]-rect[2]
    width = rect[1]-rect[0] 
    left = rect[0]    
    top = rect[2]

    for point in points :
        for y in range(0, height) :
            #Bildkoordinaten eingeben
            y = y
            x = point[0] - left
            y_min = point[1] - top
            y_max = point[2] - top            
            #Kopieren Sie vom Originalbild in das neue Bild, wenn es innerhalb des maximalen und minimalen Bereichs der y-Achse liegt
            if(  y < y_min  or y_max < y):
                im[y:y+1, x:x+1,] = [0,0,0,0] #Transparent
    return im

##########################
#  main
##########################
outdir = './out/'
tempdir = './temporary/'

#Bildpfad aus Argument abrufen
args = sys.argv
if(len(args) <= 1):
    print("need arg 1. input file path.")
    sys.exit()
src_file = args[1]
root, extention = os.path.splitext(src_file)

#Bild wird geladen
im_src = cv2.imread(src_file, -1) #Alpha-Kanal enthalten
# cv2.imwrite(tempdir + "original" + extention, im_src)

#Kontur als binär erhalten
im_bin = getBinary(im_src)

#contours = cv2.findContours(im_bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0]
contours = cv2.findContours(im_bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)[0] #Holen Sie sich alle Pfade

for i, cnt in  enumerate(contours):
    #Holen Sie sich das umschreibende Rechteck
    rect = getBoundingRectAngle(cnt)
    #Schneiden Sie im Bereich der linken und rechten Kante von x an der y-Koordinate
    crop_data  = getCropData(cnt, 1) #x-Achsenreferenz
    im_out = doCropY(im_src, crop_data, rect)
    
    # # #Macht die Außenseite des Bereichs von oben nach unten für jede x-Koordinate transparent
    crop_data  = getCropData(cnt, 0) #x-Achsenreferenz
    im_out = doCropX(im_out, crop_data, rect)

    cv2.imwrite(outdir + "out" + str(i) + extention, im_out)

Bewegung

python3 crop.py Dateiname

Zwischendateiausgabe an temporär / Geben Sie die ausgeschnittene Bilddatei aus

Stichprobe

Bild eingeben

Bild ausschneiden

Es kann schwierig sein zu verstehen, dass der Hintergrund des umschreibenden Rechtecks transparent ist ...

Recommended Posts

Ich möchte das Bild entlang der Kontur anstelle des Rechtecks zuschneiden [Python OpenCV]
Ich habe eine Funktion zum Trimmen des Bildes von Python openCV erstellt. Verwenden Sie sie daher bitte.
So schneiden Sie den unteren rechten Teil des Bildes mit Python OpenCV
Ich habe versucht, die Entropie des Bildes mit Python zu finden
Ich habe versucht, das Bild mit Python + OpenCV "gammakorrektur" zu machen
Ich möchte die Natur von Python und Pip kennenlernen
Ich möchte die HTML-Version der OpenCV 3.1-Version "OpenCV-Python Tutorials" lesen
Ich möchte den Anfang des nächsten Monats mit Python ausgeben
Ich möchte die Position meines Gesichts mit OpenCV überprüfen!
Ich möchte das Ergebnis von "Zeichenfolge" .split () in Python stapelweise konvertieren
Ich möchte die abstrakte Klasse (ABCmeta) von Python im Detail erklären
Python: Ich möchte die Verarbeitungszeit einer Funktion genau messen
Ich habe versucht, das Bild mit Python + OpenCV zu "glätten"
Ich habe versucht, das Bild mit Python + OpenCV zu "differenzieren"
So beschneiden Sie ein Bild mit Python + OpenCV
Ich habe versucht, die Trapezform des Bildes zu korrigieren
Ich habe versucht, das Bild mit Python + OpenCV zu "binarisieren"
Ich möchte das Erscheinungsbild von zabbix anpassen
Ich habe versucht, den Bildfilter von OpenCV zu verwenden
Ich möchte den Fortschritt in Python anzeigen!
[Python + OpenCV] Malen Sie den transparenten Teil des Bildes weiß
[Python] Ich habe versucht, das Mitgliederbild der Idolgruppe mithilfe von Keras zu beurteilen
Ich möchte Python in der Umgebung von pyenv + pipenv unter Windows 10 verwenden
Ich möchte das Ausführungsergebnis von strace erfassen
[OpenCV / Python] Ich habe versucht, Bilder mit OpenCV zu analysieren
Ich möchte mit Python-Datenklasse nach hinten erben
Ich möchte die Grundlagen von Bokeh vollständig verstehen
Ich möchte in Python schreiben! (3) Verwenden Sie Mock
Ich möchte R-Datensatz mit Python verwenden
Python Open CV hat versucht, das Bild im Text anzuzeigen.
Ich möchte die Sicherheit der SSH-Verbindung erhöhen
Ich habe versucht, die String-Operationen von Python zusammenzufassen
Ich möchte auch Linux-Befehle an der Eingabeaufforderung verwenden! Verwenden Sie Linux-Befehle an der Eingabeaufforderung anstelle von Git Bash
Ich möchte initialisieren, wenn der Wert leer ist (Python)
maya Python Ich möchte die gebackene Animation wieder reparieren.
Ich möchte viele Prozesse von Python aus starten
Ich möchte nur die SudachiPy-Normalisierungsverarbeitung verwenden
Ich möchte Betriebsinformationen über die Yahoo-Route erhalten
[Python] Ich möchte die Option -h mit argparse verwenden
[Python] Ich habe versucht, die folgende Beziehung von Twitter zu visualisieren
Ich möchte die Authentizität eines Elements eines numpy-Arrays bestimmen
Keras Ich möchte die Ausgabe einer beliebigen Ebene erhalten !!
Ich möchte die Legende der IT-Technologiewelt kennenlernen
Einführung in die Bildanalyse opencv python
Ich möchte mit Python debuggen
Ich möchte den Namen der ausgeführten Funktion / Methode erhalten
[Pytorch] Ich möchte die Trainingsparameter des Modells manuell zuweisen
Ich möchte das Wetter mit LINE bot feat.Heroku + Python wissen
Ich habe versucht, das SD-Boot-Image von LicheePi Nano zu erstellen
Ich habe versucht, das Bild mit OpenCV im "Skizzenstil" zu verarbeiten
Ich möchte Python GUI ausführen, wenn Raspberry Pi startet
Ich habe den Code geschrieben, um den Brainf * ck-Code in Python zu schreiben
Ich habe versucht, die Videowiedergabezeit anzuzeigen (OpenCV: Python-Version)
Ich möchte sowohl den Schlüssel als auch den Wert des Python-Iterators verwenden
Ich habe das Objekt gerade mit Image Repair (Inpaint) (OpenCV: Python) gelöscht.
Ich habe versucht, das Bild mit OpenCV im "Bleistift-Zeichenstil" zu verarbeiten
Ich möchte die Bevölkerung jedes Landes der Welt kennenlernen.
Ich habe versucht, die Effizienz der täglichen Arbeit mit Python zu verbessern