web-dev-qa-db-fra.com

Détection d'objets OpenCV - Point central

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

J'essaie de localiser les coins/points centraux d'un objet (rectangle). La façon dont je le fais actuellement, est par force brute (numérisation de l'image pour l'objet) et non précise. Je me demande s'il y a des fonctionnalités sous le capot que je ne connais pas.

Modifier les détails : la taille à peu près la même qu'une petite canette de soda. La caméra est positionnée au-dessus de l'objet, pour lui donner une sensation 2D/Rectangle. L'orientation/l'angle par rapport à la caméra est aléatoire, qui est calculé à partir des points d'angle.

C'est juste un fond blanc, avec l'objet dessus (noir). La qualité de la prise de vue correspond à ce que vous attendez 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.

C'est le raffinement de la façon dont j'obtiens ces 4 virages, c'est ce sur quoi j'essaie de me concentrer. Vous pouvez voir ma méthode de force brute avec cette image: Image

35
David McGraw

Il y a déjà un exemple de comment faire la 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}

Pas une translittération exacte de ce qu'ils font, mais cela devrait vous aider.

26
Ismael C

J'espère que cela aide, utilise la méthode du moment 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;
}
7
Rod Dockter

OpenCV a des tas de fonctions qui peuvent vous aider à y parvenir. Téléchargez Emgu.CV pour un C # .NET encapsulé dans la bibliothèque si vous programmez dans ce langage.

Quelques méthodes pour obtenir ce que vous voulez:

  1. Trouvez les coins comme avant - par exemple Fonction "CornerHarris" OpenCV

  2. Seuil l'image et calculer le 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. c'est-à-dire cog_x + = * imagePtr <128? 255: 0;

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

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

4
geometrikal

Puisque personne n'a publié de 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 seuil d'Ots

  2. Trouver le contour extérieur. Nous trouvons les contours en utilisant findContours puis extraire les coordonnées de la boîte englobante en utilisant boundingRect

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


Voici un exemple avec le cadre de sélection et le point central surlignés en vert

Image d'entrée -> Production

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 des fonctionnalités pour détecter facilement un objet à partir d'une image capturée?

Obtenez d'abord une image binaire ( détection Canny Edge , seuillage simple , seuil d'Ots , ou seuil adaptatif ) puis trouver les contours en utilisant findContours . Pour obtenir les coordonnées du rectangle englobant, 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 . Cela vous donnera les 4 points d'angle du contour. Si vous souhaitez 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()
1
nathancy

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

0
kenny