De nombreuses méthodes ont été proposées pour segmenter (extraire) une zone spécifique d'une image. Les méthodes bien connues incluent la méthode de coupe de graphe, la méthode de réglage de niveau et la méthode d'expansion de surface. Les méthodes de coupe de graphe et de réglage de niveau peuvent extraire des zones avec une grande précision, mais il est assez difficile de créer un programme. La méthode d'expansion de zone est facile à configurer, mais la précision n'est pas bonne car elle extrait simplement la zone qui correspond au seuil à partir du point de départ. Cependant, une méthode spéciale a été proposée qui rend très facile la construction d'un programme et a une bonne précision. Telle est la méthode de coupe de croissance. growcut est une méthode d'extraction de région utilisant un automate cellulaire. La zone est déterminée en répétant le processus dans lequel le pixel d'intérêt est attaqué par les pixels voisins et remplacé par les étiquettes des pixels voisins. Cette fois, j'ai essayé de construire cette méthode growcut avec python, donc je vais expliquer le programme.
La méthode
growcut est une méthode pour segmenter le premier plan lorsque des points de départ pour le premier plan et l'arrière-plan sont donnés dans l'image. Cette méthode est basée sur un automate cellulaire et peut être interprétée comme des bactéries avec une étiquette de premier plan et des bactéries avec une étiquette de fond diffusent à partir du point de départ et se brouillent pour chaque pixel de l'image en compétition. Chaque pixel remarquable est envahi par des bactéries qui se cachent dans les pixels voisins. Chaque bactérie a un pouvoir offensif et défensif, et lorsqu'une bactérie tente d'envahir un pixel (donnez sa propre étiquette à ce pixel), le pouvoir défensif de ce pixel atténue dans une certaine mesure l'attaque. Même ainsi, si la puissance d'attaque est supérieure à la puissance d'attaque du pixel à envahir, ce pixel sera envahi. Il semble que le premier plan puisse être extrait en effectuant ce processus d'invasion pour tous les pixels et en répétant cette série d'étapes plusieurs fois. Veuillez vous référer aux références pour les formules détaillées. </ p>
Les données utilisées sont une image en niveaux de gris de M. Lenna. Cette fois, cette Lenna est extraite par la méthode de coupe de croissance.
L'ensemble du programme créé cette fois est le suivant.
python
# encoding:utf-8
import numpy as np
import cv2
import matplotlib.pyplot as plt
class Sampling:
def __init__(self, image):
self.image = image
self.points = []
def mouse(self, event):
if event.button == 3:
self.axis.plot(event.xdata, event.ydata, "ro")
self.points.append([event.ydata, event.xdata])
self.fig.canvas.draw()
def start(self):
self.fig = plt.figure()
self.axis = self.fig.add_subplot(111)
self.fig.canvas.mpl_connect("button_press_event", self.mouse)
plt.gray()
self.axis.imshow(self.image)
plt.show()
plt.clf()
return np.array(self.points).astype(np.int)
def growCut(image, foreGround, backGround, iter=100):
#Près de 8
diffY = [-1,-1,-1,0,0,1,1,1]
diffX = [-1,0,1,-1,1,-1,0,1]
#Initialisation de l'étiquette
label = np.zeros(image.shape)
label[foreGround[:,0], foreGround[:,1]] = 1
label[backGround[:,0], backGround[:,1]] = -1
#Puissance offensive
power = np.zeros(image.shape)
power[foreGround[:,0], foreGround[:,1]] = 1.0
power[backGround[:,0], backGround[:,1]] = 1.0
power_next = np.copy(power)
label_next = np.copy(label)
#commencer growcut
for t in range(iter):
print(t)
power = np.copy(power_next)
label = np.copy(label_next)
for i in range(1,image.shape[0]-1):
for j in range(1,image.shape[1]-1):
for k in range(8):
dy, dx = diffY[k], diffX[k]
#Pouvoir défensif de la cellule d'attention
shield = 1.0 - np.abs(image[i,j] - image[i+dy,j+dx])
#La puissance d'attaque des cellules voisines dépasse-t-elle la puissance de défense du pixel d'intérêt?
if shield * power[i+dy,j+dx] > power[i,j]:
label_next[i,j] = label[i+dy,j+dx]
power_next[i,j] = power[i+dy,j+dx] * shield
return label_next
def main():
image = cv2.imread("Lenna.png ", 0).astype(np.float)
image = (image - image.min()) / (image.max() - image.min())
plt.gray()
plt.imshow(image)
plt.show()
foreGround = Sampling(image).start()
backGround = Sampling(image).start()
mask = growCut(image, foreGround, backGround)
mask[mask != 1] = 0
plt.gray()
plt.subplot(131)
plt.imshow(image)
plt.subplot(132)
plt.imshow(image)
plt.plot(foreGround[:,1], foreGround[:,0], "ro")
plt.plot(backGround[:,1], backGround[:,0], "bo")
plt.subplot(133)
plt.imshow(image * mask)
plt.show()
La classe Sampling est une classe pour déterminer le point de départ. Cliquez avec le bouton droit pour atteindre le point de départ. Enfin, tous les points d'amorçage sont renvoyés. Puisqu'il ne s'agit pas d'une partie particulièrement importante, une explication détaillée est omise.
python
class Sampling:
def __init__(self, image):
self.image = image
self.points = []
def mouse(self, event):
if event.button == 3:
self.axis.plot(event.xdata, event.ydata, "ro")
self.points.append([event.ydata, event.xdata])
self.fig.canvas.draw()
def start(self):
self.fig = plt.figure()
self.axis = self.fig.add_subplot(111)
self.fig.canvas.mpl_connect("button_press_event", self.mouse)
plt.gray()
self.axis.imshow(self.image)
plt.show()
plt.clf()
return np.array(self.points).astype(np.int)
Ce qui suit est une explication de la fonction growcut. Dans la méthode growcut, le processus d'envahissement de tous les pixels des pixels voisins est répété plusieurs fois. En d'autres termes
python
for t in range(iter):
#Répétez le processus d'invasion plusieurs fois
Cela signifie que. Ce processus d'invasion définit chaque pixel comme le pixel d'intérêt, et la différence des valeurs de pixel des pixels voisins est définie comme la puissance de défense du pixel d'intérêt. C'est
python
shield = 1.0 - np.abs(image[i,j] - image[i+dy,j+dx])
est. Cette puissance défensive atténue l'attaque des pixels voisins, mais si elle dépasse encore l'attaque du pixel d'intérêt, le pixel d'intérêt est envahi et l'étiquette du pixel voisin est donnée au pixel d'intérêt. Et la puissance d'attaque du pixel d'attention est également mise à jour. C'est,
python
if shield * power[i+dy,j+dx] > power[i,j]:
label_next[i,j] = label[i+dy,j+dx]
power_next[i,j] = power[i+dy,j+dx] * shield
Il devient. Il semble que la segmentation du premier plan soit possible en répétant ces étapes.
Le point rouge est le point de départ du premier plan et le point bleu est le point de départ de l'arrière-plan. C'est un peu sale, mais vous pouvez voir que c'est principalement segmenté. Je n'ai aucune idée de pourquoi cela fonctionne si bien. La personne qui y pense est incroyable.
Ceci est un papier original par growcut. “GrowCut” - Interactive Multi-Label N-D Image Segmentation By Cellular Automata
Il semble qu'un certain professeur de l'Université de Tokyo l'ait écrit. Growthcut de pointe pour le traitement d'image écrit en 100 lignes