Je veux recadrer l'image le long du contour au lieu du rectangle [python OpenCV]

Objectif

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.

Façon de penser

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!

code

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)

bouge toi

nom du fichier crop.py python3

Sortie de fichier intermédiaire vers temporaire / Sortie du fichier image découpé vers /

échantillon

Image d'entrée

Découper l'image

Il peut être difficile de comprendre que le fond du rectangle circonscrit est transparent ...

Recommended Posts

Je veux recadrer l'image le long du contour au lieu du rectangle [python OpenCV]
J'ai créé une fonction pour découper l'image de python openCV, alors veuillez l'utiliser.
Comment couper la partie inférieure droite de l'image avec Python OpenCV
J'ai essayé de trouver l'entropie de l'image avec python
J'ai essayé la "correction gamma" de l'image avec Python + OpenCV
Je veux connaître la nature de Python et pip
Je veux lire la version html de la version "OpenCV-Python Tutorials" OpenCV 3.1
Je veux sortir le début du mois prochain avec Python
Je veux vérifier la position de mon visage avec OpenCV!
Je veux convertir par lots le résultat de "chaîne de caractères" .split () en Python
Je veux expliquer en détail la classe abstraite (ABCmeta) de Python
Python: je souhaite mesurer proprement le temps de traitement d'une fonction
J'ai essayé de "lisser" l'image avec Python + OpenCV
J'ai essayé de "différencier" l'image avec Python + OpenCV
Comment recadrer une image avec Python + OpenCV
J'ai essayé de corriger la forme trapézoïdale de l'image
J'ai essayé de "binariser" l'image avec Python + OpenCV
Je souhaite personnaliser l'apparence de zabbix
J'ai essayé d'utiliser le filtre d'image d'OpenCV
Je veux afficher la progression en Python!
[Python + OpenCV] Peignez la partie transparente de l'image en blanc
[Python] J'ai essayé de juger l'image du membre du groupe d'idols en utilisant Keras
Je souhaite utiliser Python dans l'environnement de pyenv + pipenv sous Windows 10
Je veux grep le résultat de l'exécution de strace
[OpenCV / Python] J'ai essayé l'analyse d'image de cellules avec OpenCV
Je veux hériter de l'arrière avec la classe de données python
Je veux bien comprendre les bases de Bokeh
Je veux écrire en Python! (3) Utiliser des simulacres
Je veux utiliser le jeu de données R avec python
Python Open CV a essayé d'afficher l'image sous forme de texte.
Je souhaite augmenter la sécurité de la connexion SSH
J'ai essayé de résumer les opérations de chaîne de Python
Je souhaite également utiliser les commandes Linux à l'invite de commande! Utilisez les commandes Linux à l'invite de commande au lieu de Git Bash
Je veux initialiser si la valeur est vide (python)
maya Python Je veux réparer à nouveau l'animation cuite.
Je veux démarrer beaucoup de processus à partir de python
Je souhaite utiliser uniquement le traitement de normalisation SudachiPy
Je veux obtenir des informations sur le fonctionnement de Yahoo Route
[Python] Je souhaite utiliser l'option -h avec argparse
[Python] J'ai essayé de visualiser la relation de suivi de Twitter
Je veux déterminer l'authenticité d'un élément du tableau numpy
Keras Je veux obtenir la sortie de n'importe quelle couche !!
Je veux connaître la légende du monde des technologies informatiques
Introduction à l'analyse d'image opencv python
Je veux déboguer avec Python
Je veux obtenir le nom de la fonction / méthode en cours d'exécution
[Pytorch] Je souhaite attribuer manuellement les paramètres d'entraînement du modèle
Je veux connaître la météo avec LINE bot avec Heroku + Python
J'ai essayé de créer l'image de démarrage SD de LicheePi Nano
J'ai essayé de traiter l'image en "style croquis" avec OpenCV
Je veux exécuter l'interface graphique Python au démarrage de Raspberry Pi
J'ai écrit le code pour écrire le code Brainf * ck en python
J'ai essayé d'afficher le temps de lecture de la vidéo (OpenCV: version Python)
Je souhaite utiliser à la fois la clé et la valeur de l'itérateur Python
Je viens d'effacer l'objet en utilisant la réparation d'image (inpaint) (OpenCV: Python)
J'ai essayé de traiter l'image dans un "style de dessin au crayon" avec OpenCV
Je veux connaître la population de chaque pays du monde.
J'ai essayé d'améliorer l'efficacité du travail quotidien avec Python