Ask Your Question

Revision history [back]

opencv two algorithms running in parallel

Thanks for reading this post. My program is written in c++ run in visual studio 2017, opencv version 4.0.1 build with tbb and mkl. I am trying to run two instances of similar combination of opencv functions resize, thresholding, morphology open and close and lastly a findcontour. my application scenario is that I capture two frames from two cameras and trying to process them in parallel. One frame when run individually takes about 9 ms to finish the processing, two frames when run sequentially takes 17 ms to process. but i implement this code in parallel using std::thread, processing time doesn't improves but actually adds 1ms of thread creating overhead to it, so it takes 18ms to finish. i have tried the boost library but the results were similar to the std::thread. When i implement tbb task groups, while there is no task creating overhead but the processing time still stays 17ms. I have provided the codes below. I am wondering if there is something i am doing wrong or if this behavior is normal, this kind of processing. Because my expectations where that the process time will decrease to somewhat 9-12 ms while running the code in parallel. but this doesn't work that way.

using std:: thread

    void find_c(const Mat &im, Mat &im_c)
 {  
    Mat imm0;
    resize(im, imm0, Size(), 0.3, 0.3, INTER_NEAREST); // downscale 2x on both x and y
    Mat d1 = Mat::zeros(Size(imm0.cols, imm0.rows), CV_8UC1);
    int pic_width = imm0.cols; // width of the resized image for further calculation
    d1(Range(470, 470 + 100), Range(0, d1.cols)) = 255;
    im_c = imm0.clone();
    Mat imm1;
    bitwise_and(imm0, d1, imm1);
    Mat imm2;
    threshold(imm1, imm2, 100, 255, THRESH_BINARY);
    Mat imm3;
    morphologyEx(imm2, imm3, MORPH_CLOSE, Mat(), Point(-1, -1), 2);
    Mat imm4;
    morphologyEx(imm3, imm4, MORPH_OPEN, Mat(), Point(-1, -1), 2);
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(imm4, contours, hierarchy, RETR_LIST, CHAIN_APPROX_SIMPLE, Point(0, 0));
    // for the circle rectangle and other info
    vector<vector<Point> > contours_poly(contours.size());
    vector<Rect> boundRect(contours.size());
    vector<Point2f>center(contours.size());
    vector<float>radius(contours.size());

    for (int i = 0; i < contours.size(); i++)
    {
        approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);
        //boundRect[i] = boundingRect(Mat(contours_poly[i]));
        minEnclosingCircle((Mat)contours_poly[i], center[i], radius[i]);
    }

    /// Draw contours
    //Mat drawing = Mat::zeros(gray.size(), CV_8UC3);
    for (int i = 0; i < contours.size(); i++)
    {
        circle(im_c, center[i], (int)radius[i] * 1.5, Scalar(255, 255, 255), 2, 8, 0);
        cout << "center of the contour No." << i + 1 << "=" << center[i] << endl;
    }

  }

    void find_cx(const Mat &immc, Mat &im_x)
   {


Mat imp0;
resize(immc, imp0, Size(), 0.3, 0.3, INTER_NEAREST);

Mat d2 = Mat::zeros(Size(imp0.cols, imp0.rows), CV_8UC1);
int pic_width = imp0.cols; // width of the resized image for further calculation
d2(Range(270, 270 + 200), Range(0, d2.cols)) = 255;

im_x = imp0.clone();

Mat imp1;
bitwise_and(imp0, d2, imp1);
Mat imp2;
threshold(imp1, imp2, 100, 255, THRESH_BINARY);
Mat imp3;
morphologyEx(imp2, imp3, MORPH_CLOSE, Mat(), Point(-1, -1), 2);
Mat imp4;
morphologyEx(imp3, imp4, MORPH_OPEN, Mat(), Point(-1, -1), 2);

vector<vector<Point> > contours1;
vector<Vec4i> hierarchy1;
RNG rng(12345);
findContours(imp4, contours1, hierarchy1, RETR_LIST, CHAIN_APPROX_SIMPLE, Point(0, 0));
// for the circle rectangle and other info
vector<vector<Point> > contours1_poly(contours1.size());
vector<Rect> boundRect1(contours1.size());
vector<Point2f>center1(contours1.size());
vector<float>radius1(contours1.size());
for (int i = 0; i < contours1.size(); i++)
{
    approxPolyDP(Mat(contours1[i]), contours1_poly[i], 3, true);
    //boundRect[i] = boundingRect(Mat(contours_poly[i]));
    minEnclosingCircle((Mat)contours1_poly[i], center1[i], radius1[i]);
}
/// Draw contours
//Mat drawing = Mat::zeros(gray.size(), CV_8UC3);
for (int i = 0; i < contours1.size(); i++)
{
    //Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    //drawContours(im_c, contours, i, color, 2, 8, hierarchy, 0, Point());
    circle(im_x, center1[i], (int)radius1[i] * 1.5, Scalar(255, 255, 255), 2, 8, 0);
    cout << "center of the contour2 No." << i + 1 << "=" << center1[i] << endl;

}
}

  void Test()
 {
  return;
 }

 int main()
{
Mat im,im22;

VideoCapture cap;
VideoCapture cap1;
int fps = 40;
    cap.open(0);
cap.set(CAP_PROP_FRAME_WIDTH, 2952);
cap.set(CAP_PROP_FRAME_HEIGHT, 2048);
cap.set(CAP_PROP_FPS, fps);
cap1.open(1);
cap1.set(CAP_PROP_FRAME_WIDTH, 2952);
cap1.set(CAP_PROP_FRAME_HEIGHT, 2048);
cap1.set(CAP_PROP_FPS, fps);

clock_t capture = 0, squential=0, parallel=0, testsq=0, testpr=0;
clock_t start, stop;


while (1)
{ 

Mat dis1, dis2, dis3, dis4;

start = clock();
cap.read(im);
cap1.read(im22);
if (im.empty()||im22.empty())
{
    cout << "src is empty" << endl;
    //messagebox
    break;
}
stop = clock();
capture = stop - start; 


//sequential
start = clock();
find_c(im, dis1);
find_cx(im22, dis2);
stop = clock();
squential = stop - start;

//imshow("seq1", dis1);
//imshow("seq2", dis2);

//parallel
start = clock();
thread th1(&find_c, ref(im), ref(dis3));
thread th2(&find_cx, ref(im22), ref(dis4));

th1.join();
th2.join();

stop = clock();
parallel = stop - start;

//imshow("parallel1", dis3);
//imshow("parallel2", dis4);


start = clock();
Test();
Test();
stop = clock();
testsq = stop - start;

start = clock();
thread test1(&Test);
thread test2(&Test);

test1.join();
test2.join();

stop = clock();
testpr = stop - start;


cout << "capture : " << capture << " ms" << endl;
cout << "sequential : " << squential << " ms" << endl;
cout << "parallel : " << parallel  << " ms" << endl;
cout << "parallel performance : " << (squential - parallel) << " ms" << endl;
cout << "threading overhead : " << (testpr - testsq) << " ms" << endl;
waitKey(1);
 }
}
#

using intel_tbb

Mat find_c(const Mat &im)
 {  
    Mat im_c;

    Mat imm0;

    resize(im, imm0, Size(), 0.3, 0.3, INTER_NEAREST); // downscale 2x on both x and y

    Mat d1 = Mat::zeros(Size(imm0.cols, imm0.rows), CV_8UC1);

    int pic_width = imm0.cols; // width of the resized image for further calculation


    d1(Range(470, 470 + 100), Range(0, d1.cols)) = 255;
    im_c = imm0.clone();
    Mat imm1;
    bitwise_and(imm0, d1, imm1);
    Mat imm2;
    threshold(imm1, imm2, 130, 255, THRESH_BINARY);
    Mat imm3;
    morphologyEx(imm2, imm3, MORPH_CLOSE, Mat(), Point(-1, -1), 2);
    Mat imm4;
    morphologyEx(imm3, imm4, MORPH_OPEN, Mat(), Point(-1, -1), 2);

    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    findContours(imm4, contours, hierarchy, RETR_LIST, CHAIN_APPROX_SIMPLE, Point(0, 0));
    // for the circle rectangle and other info
    vector<vector<Point> > contours_poly(contours.size());
    vector<Rect> boundRect(contours.size());
    vector<Point2f>center(contours.size());
    vector<float>radius(contours.size());

    for (int i = 0; i < contours.size(); i++)
    {
        approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);
        //boundRect[i] = boundingRect(Mat(contours_poly[i]));
        minEnclosingCircle((Mat)contours_poly[i], center[i], radius[i]);
    }


    /// Draw contours
    //Mat drawing = Mat::zeros(gray.size(), CV_8UC3);
    for (int i = 0; i < contours.size(); i++)
    {

        circle(im_c, center[i], (int)radius[i] * 1.5, Scalar(255, 255, 255), 2, 8, 0);
        cout << "center of the contour No." << i + 1 << "=" << center[i] << endl;

    }
    cout << "sup" << endl;
    return im_c;
  }

 Mat find_cx(const Mat &immc)
 {

Mat im_x;
Mat imp0;
resize(immc, imp0, Size(), 0.3, 0.3, INTER_NEAREST);
Mat d2 = Mat::zeros(Size(imp0.cols, imp0.rows), CV_8UC1);
int pic_width = imp0.cols; // width of the resized image for further calculation
d2(Range(270, 270 + 200), Range(0, d2.cols)) = 255;
im_x = imp0.clone();
Mat imp1;
bitwise_and(imp0, d2, imp1);
Mat imp2;
threshold(imp1, imp2, 140, 255, THRESH_BINARY);
Mat imp3;
morphologyEx(imp2, imp3, MORPH_CLOSE, Mat(), Point(-1, -1), 2);
Mat imp4;
morphologyEx(imp3, imp4, MORPH_OPEN, Mat(), Point(-1, -1), 2);
vector<vector<Point> > contours1;
vector<Vec4i> hierarchy1;
RNG rng(12345);
findContours(imp4, contours1, hierarchy1, RETR_LIST, CHAIN_APPROX_SIMPLE, Point(0, 0));
// for the circle rectangle and other info
vector<vector<Point> > contours1_poly(contours1.size());
vector<Rect> boundRect1(contours1.size());
vector<Point2f>center1(contours1.size());
vector<float>radius1(contours1.size());
for (int i = 0; i < contours1.size(); i++)
{
    approxPolyDP(Mat(contours1[i]), contours1_poly[i], 3, true);
    //boundRect[i] = boundingRect(Mat(contours_poly[i]));
    minEnclosingCircle((Mat)contours1_poly[i], center1[i], radius1[i]);
}
/// Draw contours
//Mat drawing = Mat::zeros(gray.size(), CV_8UC3);
for (int i = 0; i < contours1.size(); i++)
{
    //Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    //drawContours(im_c, contours, i, color, 2, 8, hierarchy, 0, Point());
    circle(im_x, center1[i], (int)radius1[i] * 1.5, Scalar(255, 255, 255), 2, 8, 0);
    cout << "center of the contour2 No." << i + 1 << "=" << center1[i] << endl;
}


return im_x;
}

 int Test()
{
 int i = 1;
  return i;
}



  int main()
 {
Mat im,im22;

VideoCapture cap;
VideoCapture cap1;

int fps = 40;

cap.open(0);
cap.set(CAP_PROP_FRAME_WIDTH, 2952);
cap.set(CAP_PROP_FRAME_HEIGHT, 2048);
cap.set(CAP_PROP_FPS, fps);

cap1.open(1);
cap1.set(CAP_PROP_FRAME_WIDTH, 2952);
cap1.set(CAP_PROP_FRAME_HEIGHT, 2048);
cap1.set(CAP_PROP_FPS, fps);

clock_t capture = 0, squential=0, parallel=0, testsq=0, testpr=0;
clock_t start, stop;


while (1)
{ 

Mat dis1, dis2, dis3, dis4;

start = clock();
cap.read(im);
cap1.read(im22);
if (im.empty()||im22.empty())
{
    cout << "src is empty" << endl;
    //messagebox
    break;
}
stop = clock();
capture = stop - start; 


//sequential
start = clock();
//dis1 = find_c(im);
//dis2 = find_cx(im22);
stop = clock();
squential = stop - start;

//imshow("seq1", dis1);
//imshow("seq2", dis2);

//parallel
start = clock();
task_group find;
find.run([&] {dis3 = find_c(im); });
find.run([&] {dis4 = find_cx(im22); });
find.wait();

stop = clock();
parallel = stop - start;

//imshow("parallel1", dis3);
//imshow("parallel2", dis4);


start = clock();
Test();
Test();
stop = clock();
testsq = stop - start;

start = clock();

int b, c;
task_group g;
g.run([&] {b = Test(); });
g.run([&] {c = Test(); });
g.wait();
int d = b + c;

stop = clock();
testpr = stop - start;
cout << "grun = " << d << endl;

cout << "capture : " << capture << " ms" << endl;
cout << "sequential : " << squential << " ms" << endl;
cout << "parallel : " << parallel  << " ms" << endl;
cout << "parallel performance : " << (squential - parallel) << " ms" << endl;
cout << "threading overhead : " << (testpr - testsq) << " ms" << endl;
waitKey(1);
    }
 }