36 votes

Détection d'objets OpenCV - Point central

Étant donné un objet sur un fond blanc uni, quelqu'un sait-il si OpenCV fournit une fonctionnalité permettant de détecter facilement un objet à partir d'une image capturée ?

J'essaie de localiser les coins/centres d'un objet (rectangle). La façon dont je le fais actuellement, est par la force brute (balayage de l'image pour l'objet) et pas précis. Je me demande s'il existe une fonctionnalité sous le capot dont je ne suis pas au courant.

Editer les détails : La taille correspond à peu près à celle d'une petite canette de soda. La caméra est positionnée au-dessus de l'objet, pour lui donner un aspect 2D/Rectangle. L'orientation/angle de la caméra est aléatoire, et est calculée à partir des points d'angle.

C'est juste un fond blanc, avec l'objet dessus (noir). La qualité de l'image est à peu près celle que l'on attend d'une webcam Logitech.

Une fois que j'ai obtenu les points d'angle, je calcule le centre. Le point central est ensuite converti en centimètres.

J'essaie d'affiner la façon dont j'obtiens ces 4 coins. Vous pouvez voir ma méthode de force brute avec cette image : Imagen

26voto

Ismael C Points 76

Il existe déjà un exemple de détection de rectangle dans OpenCV (regardez dans samples/squares.c), et c'est assez simple, en fait.

Voici l'algorithme approximatif qu'ils utilisent :

0. rectangles <- {}
1. image <- load image
2. for every channel:
2.1  image_canny <- apply canny edge detector to this channel
2.2  for threshold in bunch_of_increasing_thresholds:
2.2.1   image_thresholds[threshold] <- apply threshold to this channel
2.3  for each contour found in {image_canny} U image_thresholds:
2.3.1   Approximate contour with polygons
2.3.2   if the approximation has four corners and the angles are close to 90 degrees.
2.3.2.1    rectangles <- rectangles U {contour}

Ce n'est pas une translittération exacte de ce qu'ils font, mais cela devrait vous aider.

0 votes

Je suis en train de réaliser un projet similaire. Je suis novice en matière d'OpenCV. Pourriez-vous m'envoyer le code source permettant de réaliser ces étapes ?

1 votes

Je pense que le fichier que vous recherchez est maintenant [OpenCV_proj_dir]/samples/cpp/squares.cpp.

7voto

Rod Dockter Points 41

J'espère que cela vous aidera. Il utilise la méthode des moments pour obtenir le centroïde d'une image en noir et blanc.

cv::Point getCentroid(cv::Mat img)
{
    cv::Point Coord;
    cv::Moments mm = cv::moments(img,false);
    double moment10 = mm.m10;
    double moment01 = mm.m01;
    double moment00 = mm.m00;
    Coord.x = int(moment10 / moment00);
    Coord.y = int(moment01 / moment00);
    return Coord;
}

4voto

geometrikal Points 551

OpenCV dispose d'un grand nombre de fonctions qui peuvent vous aider à atteindre cet objectif. Téléchargez Emgu.CV pour une enveloppe C#.NET de la bibliothèque si vous programmez dans ce langage.

Quelques méthodes pour obtenir ce que vous voulez :

  1. Trouver les coins comme avant - par exemple, la fonction OpenCV "CornerHarris".

  2. Seuil de l'image et calcul du centre de gravité - voir http://www.roborealm.com/help/Center%20of%20Gravity.php ... c'est la méthode que j'utiliserais. Vous pouvez même effectuer le seuillage dans la routine COG. i.e. cog_x += *imagePtr < 128 ? 255 : 0 ;

  3. Trouver les moments de l'image pour donner la rotation, le centre de gravité etc. - par exemple la fonction OpenCV "Moments". (Je ne l'ai pas utilisée)

  4. (edit) La bibliothèque AForge.NET possède des fonctions de détection d'angle ainsi qu'un projet d'exemple (MotionDetector) et des bibliothèques pour se connecter aux webcams. Je pense que c'est la façon la plus simple de procéder, en supposant que vous utilisez Windows et .NET.

0 votes

En ce qui concerne le cvCornerHarris, pouvez-vous préciser comment il est utilisé ? D'après ce que je vois, vous créez une image et exécutez cvCornerHarris(image, cornerimg, blockSize( ?), apertureSize( ?)). Et, comment êtes-vous capable de tirer des informations de l'image du coin ?

0 votes

D'après ce que je sais, le système fonctionne de la manière suivante : pour chaque pixel, il exécute un détecteur d'arêtes de Sobel de taille 'apertureSize' sur le groupe de pixels environnant 'blockSize' par 'blockSize'. Il utilise ensuite une formule pour donner un score aux bords détectés dans cette zone. Un coin aura des bords horizontaux et verticaux.

0 votes

L'image résultante a la même taille que l'original, sauf que les pixels les plus brillants correspondent aux coins les plus forts. Choisissez une taille de bloc plus grande que le coin à détecter - essayez 5 ou 7 pour votre image. Choisissez apertureSize et un peu plus petit - essayez 3. Je n'ai pas utilisé cette fonction moi-même, alors dites comment ça se passe

1voto

nathancy Points 6407

Puisque personne n'a mis en ligne une solution OpenCV complète, voici une approche simple :

  1. Obtenir une image binaire. Nous chargeons l'image, la convertissons en niveaux de gris, puis obtenons une image binaire en utilisant Le seuil d'Otsu

  2. Trouvez le contour extérieur. Nous trouvons les contours en utilisant findContours et ensuite extraire les coordonnées de la boîte de délimitation en utilisant boundingRect

  3. Trouver la coordonnée du centre. Puisque nous avons le contour, nous pouvons trouver la coordonnée centrale en utilisant moments pour extraire le centroïde du contour


Voici un exemple avec la boîte englobante et le point central mis en évidence en vert.

Image d'entrée -> Sortie

Center: (100, 100)

Center: (200, 200)

Center: (300, 300)

Donc, pour récapituler :

Étant donné un objet sur un fond blanc uni, quelqu'un sait-il si OpenCV fournit une fonctionnalité permettant de détecter facilement un objet à partir d'une image capturée ?

Obtenez d'abord une image binaire ( Détection des bords à la Canny , seuillage simple , Le seuil d'Otsu o Seuil adaptatif ) et ensuite trouver les contours en utilisant findContours . Pour obtenir les coordonnées du rectangle de délimitation, vous pouvez utiliser boundingRect qui vous donnera les coordonnées sous la forme de x,y,w,h . Pour dessiner le rectangle, vous pouvez le dessiner avec rectangle . Vous obtiendrez ainsi les 4 points d'angle du contour. Si vous vouliez obtenir le point central, utilisez moments pour extraire le centroïde du contour

Code

import cv2
import numpy as np

# Load image, convert to grayscale, and Otsu's threshold 
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find contours and extract the bounding rectangle coordintes
# then find moments to obtain the centroid
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    # Obtain bounding box coordinates and draw rectangle
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)

    # Find center coordinate and draw center point
    M = cv2.moments(c)
    cx = int(M['m10']/M['m00'])
    cy = int(M['m01']/M['m00'])
    cv2.circle(image, (cx, cy), 2, (36,255,12), -1)
    print('Center: ({}, {})'.format(cx,cy))

cv2.imshow('image', image)
cv2.waitKey()

0voto

kenny Points 9150

Elle est généralement appelée analyse des blobs dans d'autres bibliothèques de vision industrielle. Je n'ai pas encore utilisé opencv.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X