Can't find countours

asked 2017-01-19 00:36:19 -0600

balloman gravatar image

updated 2017-02-12 18:47:03 -0600

(bump)

I have some code that finds contours on the Nvidia Jetson. I recently transferred most of the work to the GPU, except for inRange, as there is no GPU function for it, disappointingly. The only problem is that after using the inRange function, when I upload back to the GPU, process, and download, the contours don't show.

Here is my code

Mat imgOriginal;

    cap.read(imgOriginal); // read a new frame from video

    imshow("Stream", imgOriginal);

    GpuMat g_imgOriginal;
    g_imgOriginal.upload(imgOriginal);
    GpuMat g_imgHSV;
    Mat imgHSV;
    cvtColor(g_imgOriginal, g_imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV

    g_imgHSV.download(imgHSV);
    Mat imgThresholded;
    GpuMat g_imgThresholded;

    inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded); //Threshold the image
    g_imgThresholded.upload(imgThresholded);
    //morphological opening (removes small objects from the foreground)
    gpu::erode(g_imgThresholded, g_imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
    gpu::dilate(g_imgThresholded, g_imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));

    //morphological closing (removes small holes from the foreground)
    gpu::dilate(g_imgThresholded, g_imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
    gpu::erode(g_imgThresholded, g_imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));

    int thresh = 100;
    GpuMat g_canny_output;
    vector<Vec4i> hierarchy;
    vector<vector<Point> > contours;
    RNG rng(12345);

    gpu::Canny(g_imgThresholded, g_canny_output, thresh, thresh * 2, 3);
    /// Find contours
    Mat canny_output;
    g_canny_output.download(canny_output);
    findContours(canny_output, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

    /// Draw contours
    Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
    for (int i = 0; i < contours.size(); i++)
    {
        Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
        drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
    }

    /*This function finds if there are any contours, and if there are
    Then we will first find the center, then add that to a vector(array); This is because there can be more
    than one contours */
    if (contours.size() > 0) {
        for (int i = 0; i < contours.size(); i++) {
            if (cv::contourArea(contours[i]) > 1) {
                cv::Point2f c;
                float r;
                cv::minEnclosingCircle(contours[i], c, r);

                if (r >= minTargetRadius)
                {
                    center.push_back(c);
                    radius.push_back(r);
                }
            }
        }
        size_t count = center.size();
    }

    imshow("contours", drawing);
edit retag flag offensive close merge delete

Comments

How about using simply a double threshold to mimic the inRange and put it on GPU also?

StevenPuttemans gravatar imageStevenPuttemans ( 2017-01-19 09:52:08 -0600 )edit

StevenPuttemans How would one do that?

balloman gravatar imageballoman ( 2017-01-19 12:26:47 -0600 )edit