36 Stimmen

OpenCV-Objekterkennung - Mittelpunkt

Gegeben ein Objekt auf einem einfachen weißen Hintergrund, weiß jemand, ob OpenCV bietet Funktionalität, um leicht ein Objekt aus einem erfassten Frame zu erkennen?

Ich versuche, die Eck-/Mittelpunkte eines Objekts (Rechteck) zu finden. Die Art und Weise, wie ich es derzeit tue, ist mit roher Gewalt (Scannen des Bildes für das Objekt) und nicht genau. Ich frage mich, ob es eine Funktionalität unter der Haube, die ich nicht bewusst sind.

Details bearbeiten : Die Größe entspricht in etwa einer kleinen Limodose. Die Kamera ist über dem Objekt positioniert, um ihm ein 2D/Rechteck-Gefühl zu geben. Die Ausrichtung/Winkel von der Kamera aus ist zufällig und wird anhand der Eckpunkte berechnet.

Es ist nur ein weißer Hintergrund, auf dem sich das Objekt befindet (schwarz). Die Qualität der Aufnahme entspricht in etwa dem, was man von einer Logitech-Webkamera erwarten würde.

Sobald ich die Eckpunkte ermittelt habe, berechne ich den Mittelpunkt. Der Mittelpunkt wird dann in Zentimeter umgerechnet.

Ich versuche, mich darauf zu konzentrieren, wie ich diese 4 Ecken erreiche. Sie können meine rohe Gewalt Methode mit diesem Bild zu sehen: Bild

26voto

Ismael C Punkte 111

Es gibt bereits ein Beispiel für die Erkennung von Rechtecken in OpenCV (siehe samples/squares.c), und es ist eigentlich ganz einfach.

Hier ist der grobe Algorithmus, den sie verwenden:

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}

Das ist keine exakte Übersetzung dessen, was sie tun, aber es sollte Ihnen helfen.

7voto

Rod Dockter Punkte 71

Ich hoffe, das hilft, denn es verwendet die Moment-Methode, um den Schwerpunkt eines Schwarz-Weiß-Bildes zu ermitteln.

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 Punkte 2908

OpenCV verfügt über eine Vielzahl von Funktionen, die Ihnen dabei helfen können. Laden Sie Emgu.CV herunter, um eine C#.NET-Verpackung der Bibliothek zu erhalten, wenn Sie in dieser Sprache programmieren.

Einige Methoden, um zu bekommen, was Sie wollen:

  1. Finden Sie die Ecken wie zuvor - z. B. mit der OpenCV-Funktion "CornerHarris".

  2. Schwellenwert für das Bild und Berechnung des Schwerpunkts - siehe http://www.roborealm.com/help/Center%20of%20Gravity.php ... dies ist die Methode, die ich anwenden würde. Sie können die Schwellenwertbildung sogar in der COG-Routine durchführen. d.h. cog_x += *imagePtr < 128 ? 255 : 0;

  3. Finden Sie die Momente des Bildes, um Rotation, Schwerpunkt usw. zu bestimmen - z. B. die OpenCV-Funktion "Moments". (Ich habe dies nicht verwendet)

  4. (edit) Die AForge.NET Bibliothek hat Funktionen zur Eckenerkennung sowie ein Beispielprojekt (MotionDetector) und Bibliotheken zur Verbindung mit Webcams. Ich denke, das wäre der einfachste Weg, vorausgesetzt, Sie verwenden Windows und .NET.

1voto

nathancy Punkte 33814

Da niemand eine vollständige OpenCV-Lösung veröffentlicht hat, hier ein einfacher Ansatz:

  1. Erhalten Sie ein binäres Bild. Wir laden das Bild, wandeln es in Graustufen um und erhalten dann ein binäres Bild mit Otsus Schwelle

  2. Finden Sie die äußere Kontur. Wir finden Konturen mit findContours und extrahieren Sie dann die Bounding-Box-Koordinaten mit boundingRect

  3. Finden Sie die mittlere Koordinate. Da wir die Kontur haben, können wir die Mittelpunktskoordinate finden, indem wir Momente zur Extraktion des Schwerpunkts der Kontur


Hier ein Beispiel, bei dem der Begrenzungsrahmen und der Mittelpunkt grün hervorgehoben sind

Eingangsbild -> Ausgabe

Center: (100, 100)

Center: (200, 200)

Center: (300, 300)

Um es noch einmal zusammenzufassen:

Gegeben ein Objekt auf einem einfachen weißen Hintergrund, weiß jemand, ob OpenCV bietet Funktionalität, um leicht ein Objekt aus einem erfassten Frame zu erkennen?

Erstellen Sie zunächst ein binäres Bild ( Geschickte Kantenerkennung , einfache Schwellenwertberechnung , Otsus Schwelle , oder Adaptive Schwelle ) und dann die Konturen mit findContours . Um die Koordinaten des begrenzenden Rechtecks zu erhalten, können Sie Folgendes verwenden boundingRect die Ihnen die Koordinaten in Form von x,y,w,h . Um das Rechteck zu zeichnen, können Sie es mit rectangle . So erhalten Sie die 4 Eckpunkte der Kontur. Wenn Sie den Mittelpunkt erhalten möchten, verwenden Sie moments zur Extraktion des Schwerpunkts der Kontur

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 Punkte 20102

In anderen Bildverarbeitungsbibliotheken wird sie gewöhnlich als Blob-Analyse bezeichnet. Ich habe opencv noch nicht benutzt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X