Je veux obtenir le contour d'un objet dans une image avec OpenCV et le découper. Quand je l'examine, je ne peux trouver que le motif découpé par le rectangle / carré circonscrit même dans divers contours. Je veux découper uniquement l'objet tel qu'il est.
La seule façon de recadrer une image avec OpenCV + python est de spécifier la plage de pixels de l'image d'origine, telle que img [10: 100, 20: 100].
Alors, découpez d'abord avec le rectangle circonscrit, puis faites une toile avec la taille du rectangle circonscrit, Les données sont organisées dans les informations de contour acquises, et la valeur maximale et la valeur minimale sont acquises pour chaque ligne et transformées en un tableau. Si vous allez entre le minimum et le maximum ligne par ligne sur la toile transparente que vous avez créée précédemment, récupérez-la à partir de l'image d'origine et tracez-la ..., Il semble que nous devrions le répéter ligne par ligne.
Aller!
import cv2
import numpy as np
from pprint import pprint
from copy import deepcopy
import sys
import os
#Conversion de l'échelle de gris de l'image d'entrée> Binarisation, retourne l'image binarisée
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]
#Obtenez le rectangle circonscrit
def getBoundingRectAngle(contour):
#Puisque la structure du tableau est multiple, faites-en un simple tableau une fois(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)]
#Coupé
def getPartImageByRect(img, rect):
#[axe y, axe x]
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:
#Obtenez un tableau de x avec une valeur spécifique de y à partir du tableau de contours
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
##Obtenez la plage de coordonnées x le long de l'axe y
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) :
#coordonnées de l'image d'entrée
in_y = point[0]
in_x = x + left
in_x_min = point[1]
in_x_max = point[2]
#coordonnées de l'image de sortie
out_y = point[0] - top
out_x = x
out_x_min = point[1] - left
out_x_max = point[2] - left
#Copier de l'image d'origine vers la nouvelle image s'il s'agit de la plage maximale et minimale de l'axe x
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
##Pour l'image extraite une fois
##Obtenez la plage de coordonnées y le long de l'axe x
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) :
#coordonnées de l'image d'entrée
y = y
x = point[0] - left
y_min = point[1] - top
y_max = point[2] - top
#Copie de l'image d'origine vers la nouvelle image si elle se situe dans la plage maximale et minimale de l'axe y
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/'
#Obtenir le chemin de l'image à partir de l'argument
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)
#Chargement d'image
im_src = cv2.imread(src_file, -1) #Canal alpha inclus
# cv2.imwrite(tempdir + "original" + extention, im_src)
#Obtenir le contour sous forme binaire
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] #Obtenez tous les chemins
for i, cnt in enumerate(contours):
#Obtenez le rectangle circonscrit
rect = getBoundingRectAngle(cnt)
#Couper dans la plage des bords gauche et droit de x à la coordonnée y
crop_data = getCropData(cnt, 1) #référence de l'axe des x
im_out = doCropY(im_src, crop_data, rect)
# # #Rend l'extérieur de la plage au-dessus et au-dessous de y transparent pour chaque coordonnée x
crop_data = getCropData(cnt, 0) #référence de l'axe des x
im_out = doCropX(im_out, crop_data, rect)
cv2.imwrite(outdir + "out" + str(i) + extention, im_out)
nom du fichier crop.py python3
Sortie de fichier intermédiaire vers temporaire / Sortie du fichier image découpé vers /
Il peut être difficile de comprendre que le fond du rectangle circonscrit est transparent ...
Recommended Posts