优化形状跟踪程序 - C ++ OpenCV

时间:2017-07-28 20:49:28

标签: c++ performance opencv video-capture file-writing

以下代码旨在根据相机Feed中的形状(通过顶点)跟踪对象。虽然此代码可以正常工作,但存储有关被跟踪对象的信息(位置,形状,记录数据的时间)的文件每秒仅写入约30次。我想显着提高这个速度(最好是每秒约100次)。我已经尝试更换正在使用的相机,它可以捕获远远超过100 fps,但这对上述问题没有影响,并产生与30 fps网络摄像头相同的结果。我的代码中是否有某些东西会不必要地减慢进程,或者我可以在代码中添加一些东西来加速它的进程?任何帮助都非常感谢。

编辑:我完全忘记了 - Dan Mašek致写了大部分以下代码的信用。

编辑: Here是一个跟踪视频,在这种情况下只是球面上的一个四边形。

编辑:现在,我的目标是记录此程序指定的形状的“质心”,以便尽可能准确地跟踪数据文件(我已实施),最好每秒至少记录100个数据点(我继续努力)。

编辑:修改后的代码包含两个摄像头,每个摄像头都写入一个单独的文本文件。目前,都写入shape_data1.txt,因此无法正常工作。另外,findPos()被删除了,因为它实际上没有记录位置,只是当前CPU时间的毫秒值。

代码:

#include <fstream>
#include <time.h>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>

std::vector<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
std::ofstream file_;
std::ofstream file1_;

void morphOps(cv::Mat &thresh){

    //create structuring element that will be used to "dilate" and "erode" image.
    //the element chosen here is a 3px by 3px rectangle

    cv::Mat erodeElement = cv::getStructuringElement( cv::MORPH_RECT,cv::Size(10,10));
    //dilate with larger element so make sure object is nicely visible
    cv::Mat dilateElement = cv::getStructuringElement( cv::MORPH_RECT,cv::Size(10,10));

    cv::erode(thresh,thresh,erodeElement);
    cv::erode(thresh,thresh,erodeElement);


    cv::dilate(thresh,thresh,dilateElement);
    cv::dilate(thresh,thresh,dilateElement);
}

void process_contour(cv::Mat& frame, std::vector<cv::Point> const& contour, int num)
{
    clock_t t;
    t = clock();

    int minArea = 100;
    int x1,y1;

    cv::Scalar TRIANGLE_COLOR(0, 0, 255);
    cv::Scalar QUADRILATERAL_COLOR(0, 255, 0);
    cv::Scalar HEPTAGON_COLOR(255, 0, 0);
    cv::Scalar DECA_COLOR(126, 126, 0);

    cv::Scalar color;

    if (contour.size() == 3 && contourArea(contour) > minArea) {
        color = TRIANGLE_COLOR;
        for (int index = 0; index >= 0; index = hierarchy[index][0]) {
            cv::Moments moment = cv::moments((cv::Mat)contours[index]);
            double area = moment.m00;
            if(area > minArea){
                x1 = moment.m10/area;
                y1 = moment.m01/area;
            }
        }
        if (num = 0) {
            file_ << "Triangle  " << "X: " << x1 << " Y: " << y1 << "  " << /*"Area: " << contourArea(contour) << "  " <<*/ double(t)/CLOCKS_PER_SEC << " seconds" << "\n";
        } else {
            file1_ << "Triangle  " << "X: " << x1 << " Y: " << y1 << "  " << /*"Area: " << contourArea(contour) << "  " <<*/ double(t)/CLOCKS_PER_SEC << " seconds" << "\n";
        }

    } else if (contour.size() == 4 && contourArea(contour) > minArea) {
        color = QUADRILATERAL_COLOR;
        for (int index = 0; index >= 0; index = hierarchy[index][0]) {
            cv::Moments moment = cv::moments((cv::Mat)contours[index]);
            double area = moment.m00;
            if(area > minArea){
                x1 = moment.m10/area;
                y1 = moment.m01/area;
            }
        }
        if (num = 0) {
            file_ << "Quadrilateral  " << "X: " << x1 << " Y: " << y1 << "  " << /*"Area: " << contourArea(contour) << "  " <<*/ double(t)/CLOCKS_PER_SEC << " seconds" << "\n";
        } else {
            file1_ << "Quadrilateral  " << "X: " << x1 << " Y: " << y1 << "  " << /*"Area: " << contourArea(contour) << "  " <<*/ double(t)/CLOCKS_PER_SEC << " seconds" << "\n";
        }

    } else if (contour.size() == 7 && contourArea(contour) > minArea) {
        color = HEPTAGON_COLOR;
        for (int index = 0; index >= 0; index = hierarchy[index][0]) {
            cv::Moments moment = cv::moments((cv::Mat)contours[index]);
            double area = moment.m00;
            if(area > minArea){
                x1 = moment.m10/area;
                y1 = moment.m01/area;
            }
        }
        if (num = 0) {
            file_ << "Heptagon  " << "X: " << x1 << " Y: " << y1 << "  " << /*"Area: " << contourArea(contour) << "  " <<*/ double(t)/CLOCKS_PER_SEC << " seconds" << "\n";
        } else {
            file1_ << "Heptagon  " << "X: " << x1 << " Y: " << y1 << "  " << /*"Area: " << contourArea(contour) << "  " <<*/ double(t)/CLOCKS_PER_SEC << " seconds" << "\n";
        }

    } else if (contour.size() == 10 && contourArea(contour) > minArea) {
        color = DECA_COLOR;
        for (int index = 0; index >= 0; index = hierarchy[index][0]) {
            cv::Moments moment = cv::moments((cv::Mat)contours[index]);
            double area = moment.m00;
            if(area > minArea){
                x1 = moment.m10/area;
                y1 = moment.m01/area;
            }
        }
        if (num = 0) {
            file_ << "Decagon  " << "X: " << x1 << " Y: " << y1 << "  " << /*"Area: " << contourArea(contour) << "  " <<*/ double(t)/CLOCKS_PER_SEC << " seconds" << "\n";
        } else {
            file1_ << "Decagon  " << "X: " << x1 << " Y: " << y1 << "  " << /*"Area: " << contourArea(contour) << "  " <<*/ double(t)/CLOCKS_PER_SEC << " seconds" << "\n";
        }

    } else {
        return;
    }

    cv::Point const* points(&contour[0]);
    int n_points(static_cast<int>(contour.size()));

    polylines(frame, &points, &n_points, 1, true, color, 4);
}

void process_frame(cv::Mat const& frame, cv::Mat& result_frame, int num)
{
    cv::Mat feedGrayScale;
    cv::cvtColor(frame, feedGrayScale, cv::COLOR_BGR2GRAY);
    //cv::imshow("Grayscale", feedGrayScale);

    frame.copyTo(result_frame);

    //thresholding the grayscale image to get better results
    cv::threshold(feedGrayScale, feedGrayScale, 128, 255, cv::THRESH_BINARY);
    //morphOps(feedGrayScale);
    if (num = 0) {
        cv::imshow("Threshold - Webcam", feedGrayScale);
    }
    if (num = 1) {
        cv::imshow("Threshold - Basler Cam", feedGrayScale);
    }

    cv::findContours(feedGrayScale, contours, hierarchy, CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE );
    for (size_t k(0); k < contours.size(); ++k) {
        std::vector<cv::Point> approx_contour;
        cv::approxPolyDP(cv::Mat(contours[k]), approx_contour, 3, true);
        process_contour(result_frame, approx_contour, num);
    }
}

int main()
{
    file_.open("shape_data.txt");
    file1_.open("shape_data1.txt");

    cv::VideoCapture cap(0); // open the video camera no.0 
    cv::VideoCapture cap1(1); // open the video camera no.0 
    //cap.set(CV_CAP_PROP_FRAME_WIDTH,1000);
    //cap.set(CV_CAP_PROP_FRAME_HEIGHT,1000);
    //cap.set(CV_CAP_PROP_FPS,120);
    //cap.set(CV_CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));
    if (!cap.isOpened() || !cap1.isOpened())  // if not success, exit program
    {
        std::cout << "Cannot open the video cam\n";
        return -1;
    }

    //cv::namedWindow("Original", CV_WINDOW_AUTOSIZE);
    cv::namedWindow("Tracked - Webcam", CV_WINDOW_AUTOSIZE);
    cv::namedWindow("Tracked - Basler Cam", CV_WINDOW_AUTOSIZE);

    // Process frames from the video stream...
    for(;;) {
        cv::Mat frame, result_frame;
        cv::Mat frame1, result_frame1;

        // read a new frame from video
        if (!cap.read(frame)) {
            std::cout << "Cannot read a frame from video stream\n";
            break;
        }
        if (!cap1.read(frame1)) {
            std::cout << "Cannot read a frame from video stream\n";
            break;
        }
        process_frame(frame, result_frame, 0);
        process_frame(frame1, result_frame1, 1);

        cv::imshow("Tracked - Webcam", result_frame);
        cv::imshow("Tracked - Basler Cam", result_frame1);

        cv::waitKey(1);
    }

    return 0;
}

正在写入文本文件的示例部分:

Quadrilateral  X: 361 Y: 136  168.156 seconds
Quadrilateral  X: 361 Y: 138  168.204 seconds
Quadrilateral  X: 361 Y: 138  168.212 seconds
Quadrilateral  X: 371 Y: 138  168.259 seconds
Quadrilateral  X: 371 Y: 138  168.308 seconds
Quadrilateral  X: 372 Y: 139  168.349 seconds
Quadrilateral  X: 372 Y: 139  168.381 seconds
Quadrilateral  X: 372 Y: 138  168.411 seconds
Quadrilateral  X: 372 Y: 140  168.443 seconds
Quadrilateral  X: 372 Y: 140  168.473 seconds
Quadrilateral  X: 373 Y: 141  168.504 seconds
Quadrilateral  X: 374 Y: 140  168.535 seconds
Quadrilateral  X: 374 Y: 142  168.566 seconds
Quadrilateral  X: 374 Y: 143  168.597 seconds
Quadrilateral  X: 375 Y: 145  168.631 seconds
Quadrilateral  X: 376 Y: 145  168.663 seconds
Quadrilateral  X: 376 Y: 146  168.694 seconds
Quadrilateral  X: 375 Y: 147  168.769 seconds
Quadrilateral  X: 376 Y: 147  168.799 seconds
Quadrilateral  X: 377 Y: 146  168.831 seconds
Quadrilateral  X: 376 Y: 145  168.862 seconds
Quadrilateral  X: 376 Y: 145  168.894 seconds
Quadrilateral  X: 377 Y: 145  168.925 seconds
Quadrilateral  X: 376 Y: 146  169.034 seconds
Quadrilateral  X: 376 Y: 146  169.065 seconds
Quadrilateral  X: 377 Y: 146  169.095 seconds
Quadrilateral  X: 378 Y: 145  169.127 seconds
Quadrilateral  X: 377 Y: 144  169.158 seconds
Quadrilateral  X: 377 Y: 144  169.192 seconds
Quadrilateral  X: 378 Y: 144  169.254 seconds
Quadrilateral  X: 378 Y: 144  169.286 seconds
Quadrilateral  X: 377 Y: 145  169.319 seconds
Quadrilateral  X: 378 Y: 145  169.366 seconds
Quadrilateral  X: 378 Y: 145  169.398 seconds
Quadrilateral  X: 379 Y: 144  169.439 seconds
Quadrilateral  X: 379 Y: 144  169.471 seconds
Quadrilateral  X: 380 Y: 144  169.534 seconds
Quadrilateral  X: 380 Y: 144  169.565 seconds
Quadrilateral  X: 380 Y: 144  169.595 seconds
Quadrilateral  X: 378 Y: 145  169.628 seconds
Quadrilateral  X: 379 Y: 145  169.658 seconds
Quadrilateral  X: 379 Y: 145  169.688 seconds
Quadrilateral  X: 380 Y: 143  169.758 seconds
Quadrilateral  X: 380 Y: 143  169.807 seconds
Quadrilateral  X: 379 Y: 143  169.85 seconds
Quadrilateral  X: 377 Y: 135  169.928 seconds
Quadrilateral  X: 377 Y: 134  169.975 seconds
Quadrilateral  X: 381 Y: 134  170.02 seconds
Quadrilateral  X: 382 Y: 134  170.051 seconds
Quadrilateral  X: 381 Y: 136  170.113 seconds
Quadrilateral  X: 382 Y: 137  170.145 seconds
Quadrilateral  X: 382 Y: 137  170.175 seconds
Quadrilateral  X: 380 Y: 135  170.267 seconds
Quadrilateral  X: 380 Y: 135  170.295 seconds
Quadrilateral  X: 381 Y: 134  170.328 seconds
Quadrilateral  X: 380 Y: 133  170.391 seconds
Quadrilateral  X: 381 Y: 134  170.47 seconds
Quadrilateral  X: 381 Y: 134  170.502 seconds
Quadrilateral  X: 380 Y: 134  170.534 seconds
Quadrilateral  X: 380 Y: 134  170.566 seconds
Quadrilateral  X: 380 Y: 134  170.597 seconds
Quadrilateral  X: 381 Y: 133  170.629 seconds
Quadrilateral  X: 381 Y: 133  170.662 seconds
Quadrilateral  X: 381 Y: 133  170.735 seconds
Quadrilateral  X: 381 Y: 133  170.765 seconds
Quadrilateral  X: 381 Y: 134  170.806 seconds
Quadrilateral  X: 380 Y: 134  170.855 seconds
Quadrilateral  X: 381 Y: 134  170.891 seconds
Quadrilateral  X: 381 Y: 135  170.923 seconds
Quadrilateral  X: 382 Y: 134  170.955 seconds
Quadrilateral  X: 382 Y: 134  170.986 seconds
Quadrilateral  X: 382 Y: 134  171.018 seconds
Quadrilateral  X: 382 Y: 134  171.048 seconds
Quadrilateral  X: 382 Y: 134  171.079 seconds
Quadrilateral  X: 381 Y: 135  171.142 seconds
Quadrilateral  X: 382 Y: 135  171.176 seconds
Quadrilateral  X: 382 Y: 135  171.219 seconds
Quadrilateral  X: 383 Y: 134  171.251 seconds
Quadrilateral  X: 383 Y: 134  171.283 seconds
Quadrilateral  X: 383 Y: 134  171.314 seconds
Quadrilateral  X: 383 Y: 134  171.345 seconds
Quadrilateral  X: 383 Y: 134  171.376 seconds
Quadrilateral  X: 383 Y: 134  171.408 seconds
Quadrilateral  X: 382 Y: 135  171.438 seconds
Quadrilateral  X: 383 Y: 135  171.468 seconds
Quadrilateral  X: 383 Y: 135  171.5 seconds
Quadrilateral  X: 384 Y: 134  171.544 seconds
Quadrilateral  X: 384 Y: 134  171.608 seconds
Quadrilateral  X: 384 Y: 134  171.639 seconds
Quadrilateral  X: 384 Y: 134  171.67 seconds
Quadrilateral  X: 383 Y: 135  171.765 seconds
Quadrilateral  X: 384 Y: 135  171.798 seconds
Quadrilateral  X: 384 Y: 134  171.829 seconds
Quadrilateral  X: 384 Y: 134  171.91 seconds
Quadrilateral  X: 384 Y: 134  171.95 seconds
Quadrilateral  X: 384 Y: 134  171.981 seconds
Quadrilateral  X: 385 Y: 134  172.013 seconds
Quadrilateral  X: 383 Y: 135  172.045 seconds
Quadrilateral  X: 384 Y: 135  172.074 seconds
Quadrilateral  X: 384 Y: 135  172.106 seconds
Quadrilateral  X: 385 Y: 134  172.137 seconds
Quadrilateral  X: 385 Y: 135  172.168 seconds
Quadrilateral  X: 385 Y: 134  172.199 seconds
Quadrilateral  X: 385 Y: 134  172.246 seconds
Quadrilateral  X: 385 Y: 134  172.31 seconds
Quadrilateral  X: 384 Y: 135  172.341 seconds
Quadrilateral  X: 385 Y: 135  172.373 seconds
Quadrilateral  X: 385 Y: 135  172.405 seconds
Quadrilateral  X: 386 Y: 134  172.437 seconds
Quadrilateral  X: 385 Y: 134  172.469 seconds
Quadrilateral  X: 386 Y: 134  172.502 seconds
Quadrilateral  X: 385 Y: 134  172.544 seconds
Quadrilateral  X: 385 Y: 134  172.574 seconds
Quadrilateral  X: 386 Y: 134  172.638 seconds
Quadrilateral  X: 385 Y: 134  172.676 seconds
Quadrilateral  X: 386 Y: 133  172.787 seconds
Quadrilateral  X: 385 Y: 133  172.903 seconds
Quadrilateral  X: 385 Y: 134  172.935 seconds
Quadrilateral  X: 385 Y: 133  173.007 seconds
Quadrilateral  X: 385 Y: 133  173.056 seconds
Quadrilateral  X: 386 Y: 132  173.093 seconds
Quadrilateral  X: 385 Y: 132  173.126 seconds
Quadrilateral  X: 385 Y: 132  173.172 seconds
Quadrilateral  X: 385 Y: 131  173.234 seconds
Quadrilateral  X: 384 Y: 132  173.265 seconds
Quadrilateral  X: 384 Y: 132  173.295 seconds
Quadrilateral  X: 384 Y: 132  173.327 seconds
Quadrilateral  X: 383 Y: 131  173.359 seconds
Quadrilateral  X: 382 Y: 131  173.408 seconds
Quadrilateral  X: 380 Y: 131  173.449 seconds
Quadrilateral  X: 379 Y: 131  173.481 seconds
Quadrilateral  X: 378 Y: 130  173.512 seconds
Quadrilateral  X: 376 Y: 134  173.606 seconds
Quadrilateral  X: 377 Y: 133  173.638 seconds
Quadrilateral  X: 377 Y: 134  173.672 seconds

1 个答案:

答案 0 :(得分:0)

要加快文件写入,请尝试使用boost内存映射文件(根据此问题:c++ boost write memory mapped file)。

我认为您需要将处理转移到工作线程中(请参阅此http://en.cppreference.com/w/cpp/thread以获取STL,而一个很好的资源是Anthony Williams的C ++ Concurrency in Action一书)

为了优化您需要衡量,Google基准测试程序(https://github.com/google/benchmark)是我见过的最好的基准测试程序之一。您可以在具有虚拟数据的函数上使用它来单独处理它们的优化,然后作为一个组进行处理,直到找到实际的瓶颈。