10

私は、カメラが通りを見て、人々がその周りを移動することで、移動する人々の追跡を C++ の OpenCV で機能させようとしています。私が撮影して使用しているサンプル ビデオについては、こちらを参照してください: http://akos.maroy.hu/~akos/eszesp/MVI_0778.MOV

私はこのトピックを読み、次のような多くのことを試しました。

  • 背景の検出と輪郭の作成
  • ブロブの検出を試みます (ブロブのキーポイント)
  • HOGDescriptor を使用してフレームごとに人検出器を使用する

しかし、どれも良い結果をもたらしません。私のサンプルコードについては、以下を参照してください。上記のビデオに基づくコードの出力については、http: //akos.maroy.hu/~akos/eszesp/ize.aviを参照してください。背景に対して検出された輪郭は赤、輪郭の境界四角形は緑、HOG 人物検出器の結果は青です。

私が抱えている特定の問題は次のとおりです。

背景の検出と輪郭の検出は正常に機能しているように見えますが、いくつかの誤検知があります。しかし、主な欠点は、多くの場合、1 人の人物が複数の輪郭に「切り刻まれる」ことです。これらを一緒に「結合」する簡単な方法はありますか、おそらく「理想的な」人物のサイズ、または他の手段を想定していますか?

HOG人物検出器に関しては、私の場合、画像上の実際の人物を識別することはめったにありません。私はそこで何が間違っているのでしょうか?

すべての指針、アイデアを歓迎します!

したがって、私がこれまでに使用しているコードは、あちこちで見つけたさまざまなサンプルの貼り付けの栄光です。

#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;
}
4

4 に答える 4

3

次のようなヒューマン トラッカーを作成します。

  1. まず、オブジェクトを初期化する必要があります。どのように?物体検出。HOG またはカスケード分類器を適切なモデル (つまり、haarcascade_fullbody.xml) で使用します (またはそれらをすべて一緒に使用します)。

  2. 次に、境界ボックス内で見つかったピクセルを追跡する必要があります。どのように?過去のテンプレートにマッチ!アイデア: 複数を a に蓄積し、を相関vector<cv::Mat>に使用します。mean template

その他のアイデア:

  • 結果を組み合わせる: 検出器を最も信頼できる観測モデルとして使用し、失敗した場合はテンプレート マッチングに切り替えます。

  • バックグラウンド モデリングを使用して、False Positive をファイラーします (FP はバックグラウンドと良好に相関します)。

また、輪郭ベースのトラッキングが必要な場合は、opencv サンプル フォルダーにある blobtrack_sample.cpp を試してください。

于 2014-01-27T13:43:07.170 に答える
3

Reading People Tracker を見たことがありますか。これは研究プロジェクトでしたが、オープンソースで非常に効果的です。こちらをご覧ください

現在はおそらく最先端ではありませんが、ソースが利用可能であり、非常によく構造化されています。

于 2013-08-07T22:25:52.477 に答える