C++ OpenCV: die Verfolgung von sich bewegenden Menschen auf der Straße
Ich versuche, mich bewegt die Menschen-tracking arbeiten mit OpenCV in C++, mit einem Kamera-Blick auf eine Straße und die Leute bewegen. für ein Beispiel-video habe ich gedreht und ich bin mit, siehe hier: http://akos.maroy.hu/~akos/eszesp/MVI_0778.MOV
Ich Lesen Sie zu diesem Thema, und ich habe versucht, eine Reihe von Dingen, einschließlich:
- hintergrund-Erkennung und das erstellen von Konturen
- versuchen zu erkennen, blobs (Eckdaten für blobs)
- mit einem Menschen-Detektor für jeden Rahmen mit einem HOGDescriptor
aber keines dieser ein gutes Ergebnis liefern. für mein Beispiel-code, siehe unten. für die Ausgabe des Codes auf der Grundlage der oben genannten video finden Sie unter: http://akos.maroy.hu/~akos/eszesp/ize.avi . die Konturen erkannt, vor dem hintergrund sind in rot, die begrenzungsrechtecke die Konturen sind grün, und die SCHWEIN-Menschen-Detektor Ergebnisse sind in blau.
die spezifischen Probleme, die ich habe sind:
hintergrund-Erkennung und dann das finden der Konturen scheint gut zu funktionieren, obwohl es einige false positives. aber der größte Nachteil ist, dass oft eine einzige person, die 'zerschnitten' in mehrere Konturen. gibt es eine einfache Möglichkeit, 'join' diese zusammen, vielleicht durch eine angenommene "ideale" person Größe, oder eine andere Möglichkeit?
als für den HOG-Menschen-Detektor, in meinem Fall ist es sehr selten identifiziert die realen Personen auf dem Bild. was könnte ich falsch gemacht es?
alle Zeiger, Ideen willkommen!
sind und daher der code, den ich verwende bisher, das ist ein cust und fügen Herrlichkeit der verschiedenen Proben fand ich hier und da:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
int main(int argc, char *argv[])
{
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " in.file out.file" << std::endl;
return -1;
}
cv::Mat frame;
cv::Mat back;
cv::Mat fore;
std::cerr << "opening " << argv[1] << std::endl;
cv::VideoCapture cap(argv[1]);
cv::BackgroundSubtractorMOG2 bg;
//bg.nmixtures = 3;
//bg.bShadowDetection = false;
cv::VideoWriter output;
//int ex = static_cast<int>(cap.get(CV_CAP_PROP_FOURCC));
int ex = CV_FOURCC('P','I','M','1');
cv::Size size = cv::Size((int) cap.get(CV_CAP_PROP_FRAME_WIDTH),
(int) cap.get(CV_CAP_PROP_FRAME_HEIGHT));
std::cerr << "saving to " << argv[2] << std::endl;
output.open(argv[2], ex, cap.get(CV_CAP_PROP_FPS), size, true);
std::vector<std::vector<cv::Point> > contours;
cv::namedWindow("Frame");
cv::namedWindow("Fore");
cv::namedWindow("Background");
cv::SimpleBlobDetector::Params params;
params.minThreshold = 40;
params.maxThreshold = 60;
params.thresholdStep = 5;
params.minArea = 100;
params.minConvexity = 0.3;
params.minInertiaRatio = 0.01;
params.maxArea = 8000;
params.maxConvexity = 10;
params.filterByColor = false;
params.filterByCircularity = false;
cv::SimpleBlobDetector blobDtor(params);
blobDtor.create("SimpleBlob");
std::vector<std::vector<cv::Point> > blobContours;
std::vector<cv::KeyPoint> keyPoints;
cv::Mat out;
cv::HOGDescriptor hog;
hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());
for(;;)
{
cap >> frame;
bg.operator ()(frame, fore);
bg.getBackgroundImage(back);
cv::erode(fore, fore, cv::Mat());
cv::dilate(fore, fore, cv::Mat());
blobDtor.detect(fore, keyPoints, cv::Mat());
//cv::imshow("Fore", fore);
cv::findContours(fore, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
cv::drawContours(frame, contours, -1, cv::Scalar(0,0,255), 2);
std::vector<std::vector<cv::Point> >::const_iterator it = contours.begin();
std::vector<std::vector<cv::Point> >::const_iterator end = contours.end();
while (it != end) {
cv::Rect bounds = cv::boundingRect(*it);
cv::rectangle(frame, bounds, cv::Scalar(0,255,0), 2);
++it;
}
cv::drawKeypoints(fore, keyPoints, out, CV_RGB(0,255,0), cv::DrawMatchesFlags::DEFAULT);
cv::imshow("Fore", out);
std::vector<cv::Rect> found, found_filtered;
hog.detectMultiScale(frame, found, 0, cv::Size(8,8), cv::Size(32,32), 1.05, 2);
for (int i = 0; i < found.size(); ++i) {
cv::Rect r = found[i];
int j = 0;
for (; j < found.size(); ++j) {
if (j != i && (r & found[j]) == r) {
break;
}
}
if (j == found.size()) {
found_filtered.push_back(r);
}
}
for (int i = 0; i < found_filtered.size(); ++i) {
cv::Rect r = found_filtered[i];
cv::rectangle(frame, r.tl(), r.br(), cv::Scalar(255,0,0), 3);
}
output << frame;
cv::resize(frame, frame, cv::Size(1280, 720));
cv::imshow("Frame", frame);
cv::resize(back, back, cv::Size(1280, 720));
cv::imshow("Background", back);
if(cv::waitKey(30) >= 0) break;
}
return 0;
}
InformationsquelleAutor | 2013-08-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Eigentlich ist es ein sehr breites Thema. Es gibt viele wissenschaftliche arbeiten, die versucht, anzugreifen dieses problem. Lesen Sie etwas vor.
Kurz:
Hintergrund-Erkennung und-Konturen ist die einfachste Technik. OpenCV hat eine sehr schöne Umsetzungen, auch optimiert für die gpu. Zum verfeinern von Vordergrund - /hintergrund-blobs können Sie einige morphologische operation, versuchen, schließen Sie Löcher in die blobs um bessere Ergebnisse zu erhalten. Aber erwarte keine perfekten Ergebnisse. Hintergrund-Subtraktion ist eine schwierige operation, Sie können Stunden damit verbringen, in fine tune-Parameter für einen gegebenen Datensatz, dann versuchen Sie, Ihren code in der realen Welt und.. nichts funktioniert. Licht, Schatten, hintergrund ändert sich mit nicht-interessiert-Objekte.. nur für erwähnen einige Probleme.
So.. Nein, es gibt keine eine einfache und standard-Technik für den Umgang mit den so genannten "blob-Fragmentierung" oder "split-merge" - problem (irgendwann einer person ist aufgeteilt in mehrere blobs, irgendwann mehr Menschen verschmolzen zu einem einzigen blob). Wieder, es ist voll von wissenschaftlichen Abhandlungen über dieses argument. Aber es gibt Techniken für den Umgang mit der Verfolgung von unvollständigen oder Unordnung Beobachtung. Eine der einfachsten ist es, zu versuchen, zu folgern den tatsächlichen Zustand des Systems gegeben, einige unvollständige Beobachtung mit Kalman-filter. Opencv hat eine schöne Umsetzung. Wieder,, wenn Sie einige Suche nach "Kalman-filter-tracking" oder "GNN-Daten Verein" finden Sie eine Menge.
Wenn Sie wollen verwenden Sie einige geometrische Informationen, wie die Abschätzung der Höhe einer person, etc, Sie können es tun, aber Sie müssen die Kalibrierung der Parameter der Kamera. Das bedeutet, haben Sie zur Verfügung (kinect von microsoft der standard-iphone-Kamera hat Ihre Parameter zur Verfügung) oder Sie zu berechnen, obwohl eine Kalibrierung der Kamera-Prozess. Dies bedeutet, dass der download eines Schachbrett-Bild, drucken Sie es auf einem Papier, und nehmen Sie einige Bilder von ihm. Dann, OpenCV hat alle Methoden, die für die Durchführung der Kalibrierung. Danach, Sie brauchen, um abzuschätzen, den Boden ein Flugzeug, und verwenden Sie dann einige einfache render-Projekt/unproject Methoden von 2d-zu-3d-Koordinaten her und zurück, und die Schätzung der 2d-bounding-box des 3d-standard-person.
Moderne Ansätze, die auf "pedestrian tracking" extrahieren Beobachtung mit einigen Detektor. Hintergrund-Subtraktion geben kann eine Karte, wo, um zu versuchen zu erkennen, um die Suche nicht auf das gesamte Bild, sondern blob-Erkennung ist nutzlos in diesem Fall. In OpenCV die verwendeten Implementierungen in diesem Fall sind die Haar Adaboost-Detektor und HOG-Detektor.HOG-Detektor zu geben scheint bessere Ergebnisse in einigen Fällen. Bereits umgesetzt Klassifizierer in OpenCV beinhaltet Gesichtserkennung für Haar und die Menschen erkennen, für SCHWEIN. Sie finden Beispiele in beiden cpp-und python-Muster in der OpenCV-repository.
Wenn die standard-Erkennungen nicht (mit Ihrem video sind mit der unterschiedlichen Größe, oder Sie haben zu erkennen, andere Objekt als Fußgänger).. Sie müssen trainieren Sie Ihren eigenen Detektor. Das bedeutet, dass sammeln ein paar Bilder von Objekt, das Sie erkennen möchten (positive Proben), und noch ein paar Bilder mit etwas anderem (negative Proben) und trainieren Sie Ihren eigenen Klassifikatoren mit machine learning-Techniken wie SVN. wieder, google ist dein Freund : )
Glück!
InformationsquelleAutor nkint
Haben Sie gesehen, die das Lesen Menschen, die Tracker. Dies war ein Forschungsprojekt, sondern ist open source und sehr effektiv. Sehen hier
Ist es wohl nicht ganz state-of-the-art jetzt, aber der Quellcode ist verfügbar und es ist sehr gut strukturiert.
InformationsquelleAutor David Elliman
Ich würde eine menschliche tracker wie diesem:
Zuerst müssen wir initialisieren die Objekte. Wie? Objekt-Erkennung. Verwenden HOG oder die cascade classifier mit dem richtigen Modell (d.h. haarcascade_fullbody.xml) (oder verwenden Sie alle zusammen).
Dann müssen wir VERFOLGEN, diejenigen Pixel, die innerhalb der bounding-Boxen. Wie? Entsprechen Vergangenheit Vorlagen! Idee: sammeln Sie mehr als eine in einer
vector<cv::Mat>
und verwenden Sie diemean template
für die Korrelation.Mehr Ideen:
Kombinieren die Ergebnisse: Verwenden Sie den Detektor als die zuverlässige Beobachtung-Modell-und wenn es nicht gelingt, wechseln Sie zum template-matching.
Background modeling-filer False Positives (FPs korrelieren sehr gut mit den hintergrund).
Versuchen Sie auch, blobtrack_sample.cpp fand in opencv-Ordner, wenn Sie möchten, Konturen-basiertes tracking.
InformationsquelleAutor William
Fehlt der "motion model" - Komponente von tracking. Kalman - /partikelfilter sollte helfen. Ich bevorzuge Kalman.
InformationsquelleAutor Bhanu Challa