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.
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!
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)
python3 crop.py Dateiname
Zwischendateiausgabe an temporär / Geben Sie die ausgeschnittene Bilddatei aus
Es kann schwierig sein zu verstehen, dass der Hintergrund des umschreibenden Rechtecks transparent ist ...
Recommended Posts