web-dev-qa-db-fra.com

Comment recadrer la zone interne d'un contour?

Je travaille sur des images du fond de l'utérus rétinien. L'image est constituée d'une rétine circulaire sur fond noir. Avec OpenCV, j'ai réussi à obtenir un contour qui entoure toute la rétine circulaire. Ce dont j'ai besoin, c'est de recadrer la rétine circulaire du fond noir.

20
Gaurav Patil

Il n'est pas clair dans votre question si vous voulez réellement rogner les informations définies dans le contour ou masquer les informations qui ne sont pas pertinentes pour le contour choisi. J'explorerai quoi faire dans les deux situations.


Masquer les informations

En supposant que vous avez couru cv2.findContours sur votre image, vous aurez reçu une structure répertoriant tous les contours disponibles dans votre image. Je suppose également que vous connaissez l'index du contour qui a été utilisé pour entourer l'objet que vous voulez. En supposant que cela soit stocké dans idx, utilisez d'abord cv2.drawContours pour dessiner une version remplie de ce contour sur une image vierge, puis utilisez cette image pour indexer dans votre image pour extraire l'objet . Cette logique masque toutes les informations non pertinentes et ne conserve que ce qui est important - qui est défini dans le contour que vous avez sélectionné. Le code pour cela ressemblerait à ceci, en supposant que votre image est une image en niveaux de gris stockée dans img:

import numpy as np
import cv2
img = cv2.imread('...', 0) # Read in your image
# contours, _ = cv2.findContours(...) # Your call to find the contours using OpenCV 2.4.x
_, contours, _ = cv2.findContours(...) # Your call to find the contours
idx = ... # The index of the contour that surrounds your object
mask = np.zeros_like(img) # Create mask where white is what we want, black otherwise
cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask
out = np.zeros_like(img) # Extract out the object and place into output image
out[mask == 255] = img[mask == 255]

# Show the output image
cv2.imshow('Output', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

Si vous voulez réellement recadrer ...

Si vous souhaitez recadrer l'image, vous devez définir la zone de délimitation minimale de la zone définie par le contour. Vous pouvez trouver le coin supérieur gauche et le coin inférieur droit du cadre de sélection, puis utiliser l'indexation pour recadrer ce dont vous avez besoin. Le code sera le même qu'avant, mais il y aura une étape de recadrage supplémentaire:

import numpy as np
import cv2
img = cv2.imread('...', 0) # Read in your image
# contours, _ = cv2.findContours(...) # Your call to find the contours using OpenCV 2.4.x
_, contours, _ = cv2.findContours(...) # Your call to find the contours
idx = ... # The index of the contour that surrounds your object
mask = np.zeros_like(img) # Create mask where white is what we want, black otherwise
cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask
out = np.zeros_like(img) # Extract out the object and place into output image
out[mask == 255] = img[mask == 255]

# Now crop
(y, x) = np.where(mask == 255)
(topy, topx) = (np.min(y), np.min(x))
(bottomy, bottomx) = (np.max(y), np.max(x))
out = out[topy:bottomy+1, topx:bottomx+1]

# Show the output image
cv2.imshow('Output', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

Le code de recadrage fonctionne de telle sorte que lorsque nous définissons le masque pour extraire la zone définie par le contour, nous trouvons en outre les plus petites coordonnées horizontales et verticales qui définissent le coin supérieur gauche du contour. Nous trouvons également les plus grandes coordonnées horizontales et verticales qui définissent le coin inférieur gauche du contour. Nous utilisons ensuite l'indexation avec ces coordonnées pour recadrer ce dont nous avons réellement besoin. Notez que cela effectue un recadrage sur l'image masquée - c'est-à-dire l'image qui supprime tout sauf les informations contenues dans le plus grand contour.

Remarque avec OpenCV 3.x

Il convient de noter que le code ci-dessus suppose que vous utilisez OpenCV 2.4.x. Notez que dans OpenCV 3.x, la définition de cv2.drawContours a changé. Plus précisément, la sortie est une sortie Tuple à trois éléments où la première image est l'image source, tandis que les deux autres paramètres sont les mêmes que dans OpenCV 2.4.x. Par conséquent, modifiez simplement le cv2.findContours instruction dans le code ci-dessus pour ignorer la première sortie:

_, contours, _ = cv2.findContours(...) # Your call to find contours
33
rayryeng