Ask Your Question

Detecting objects in OpenCV

asked 2015-11-17 13:45:12 -0500

konradN gravatar image

updated 2015-11-22 13:19:17 -0500

pklab gravatar image

I've got problem with detecting orange ball in OpenCV. In the pictures you see results after function inRange and the second one is thresholding (which is now not in the code). In both ways HoughCirles don't see circle which is seen in front of both pictures. They are not in good quality because of the camera (you can see the noise), but I think that function should have no problem in recognizing circle. Thank you for all help. My code:

  `enter code here`                 
       CvMemStorage *storage = cvCreateMemStorage(0); //storage area for all contours
        VideoCapture cap(0);
        if (!cap.isOpened())// if supposed not success, 
                cout<<" cannot open the videofile"<<endl;// exit program
            return -1;

        bool bSuccess =;
        if (!bSuccess)
                cout<<"cannot read the frame from video file"<<endl;

        Mat hsv_src
        cvtColor(src, hsv_src, COLOR_BGR2HSV );
        inRange(hsv_src, Scalar(0, 120, 120), Scalar(30, 255, 255), hsv_src);

          /// Reduce the noise so we avoid false circle detection
         GaussianBlur( hsv_src, hsv_src, Size(9, 9), 2, 2 );

          vector<Vec3f> circles;

          /// Apply the Hough Transform to find the circles
          HoughCircles( hsv_src, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );

          /// Draw the circles detected
          for( size_t i = 0; i < circles.size(); i++ )
              Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
              int radius = cvRound(circles[i][2]);
              // circle center
              circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );
              // circle outline
              circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 );

          /// Show your results
          cout<<"Circles found: "<<circles.size()<<endl;
          namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
          imshow( "Hough Circle Transform Demo", src );

image description

image description

image description

edit retag flag offensive close merge delete


Providing your original image would help.

LorenaGdL gravatar imageLorenaGdL ( 2015-11-17 13:59:04 -0500 )edit

I've added firts photo. As you can see there is noise stripe on the left side but still ball is visible.

konradN gravatar imagekonradN ( 2015-11-18 09:26:01 -0500 )edit

CvMemStorage *storage = cvCreateMemStorage(0); O please, step away from old deprecated C functionality ... the library has moved on and focusses on C++ now. Your headaches might stop when using the proper functionality :)

StevenPuttemans gravatar imageStevenPuttemans ( 2015-11-19 08:00:43 -0500 )edit

But I even don't use object storage. So what's its impact?

konradN gravatar imagekonradN ( 2015-11-19 08:15:17 -0500 )edit

I just balance settings in HoguhCircles and it's quite okey, but I must test it on robot. Do you have any experience with Blob function?

konradN gravatar imagekonradN ( 2015-11-20 02:46:01 -0500 )edit

I tried with this manual: ,but it's not quite working :(

konradN gravatar imagekonradN ( 2015-11-20 02:49:05 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2015-11-22 13:16:18 -0500

pklab gravatar image
  1. You should adjust your grabbing chain because you have some error, maybe interlaced/progressive or noise, or something else.
  2. HoughCircle doesn't works because your binary image doesn't contains circles
  3. HoughCircle is better with gray images because it can follow a circumference using gradient of its edge. You could try houghCircle using Green channel from RGB (red is dark in green channel). Remember that Hough could be too slow in a real-time system.
  4. With threshold you cut the image upper than a value. You loose gradients, edges and shapes. After a threshold, output shape can be completely different from input shape.
  5. If you are looking for red in HSV you should remember that there are 2 ranges for Red [0..yellow] OR [magenta..180]! Using both ranges your binary will be more complete.

Instead of searching for a circle you could search for a blob with area within a given range. If threshold is well done largest blob should be the ball! You could enforce the filter using circularity too. Below is the code to catch this result:

image description image description

There are trackbars for understand and tune the parameters. Good luck with your robot!

#include "stdafx.h"
#include "Utility.hpp"
#pragma once

const char * winName = "Param";
int minH, minS, minV;
int maxH, maxS, maxV;
int minDiameterPerc, maxDiameterPerc; //relative to img.cols
int minCircularityPerc; // circularity: 0..100%;
cv::Mat src, src_hsv;

bool BlobDetector(const cv::Mat &src_binary, cv::KeyPoint &theBall)
    CV_Assert(src_binary.type() == CV_8UC1);
    cv::Mat dst;
    cv::Point ptTxt =cv::Point(10, 15);
    cv::Scalar clTxt = cv::Scalar(255, 255, 0);

    cv::SimpleBlobDetector::Params blob_params;
    // Set params for binary image 
    blob_params.filterByColor = true;
    blob_params.blobColor = 255; //blobs are white
    blob_params.minThreshold = 127;
    blob_params.thresholdStep = 1;
    blob_params.maxThreshold = blob_params.minThreshold + blob_params.thresholdStep;
    blob_params.minRepeatability = 1;
    // other parameters
    blob_params.filterByInertia = false;
    blob_params.filterByConvexity = false;

    // get values from trackbar variables
    double minRadii = minDiameterPerc * src_binary.cols / 100.0 / 2.0;
    double maxRadii = maxDiameterPerc * src_binary.cols / 100.0 / 2.0;
    double minArea = CV_PI * pow(minRadii, 2);
    double maxArea = CV_PI * pow(maxRadii, 2);
    double minCircularity = 1.0 * minCircularityPerc / 100; // circularity: 0..1;

    // set filters as required
    blob_params.filterByCircularity = (minCircularity>0);
    if (blob_params.filterByCircularity)
        blob_params.minCircularity = minCircularity;
        blob_params.maxCircularity = 1.0;
        cv::putText(dst, "Min Circularity:" + to_string(minCircularity), ptTxt,
            cv::FONT_HERSHEY_PLAIN, 1, clTxt);
        ptTxt.y += 15;
    blob_params.filterByArea = ((minArea + maxArea)>0);
    if (blob_params.filterByArea)
        blob_params.minArea = max(1, minArea); //pix
        blob_params.maxArea = max(1, maxArea); //pix
        cv::putText(dst, "Min Diam[px]:" + to_string(cvRound(minRadii * 2)), ptTxt,
            cv::FONT_HERSHEY_PLAIN, 1, clTxt);
        ptTxt.y += 15;
        cv::putText(dst, "Max Diam[px]:" + to_string(cvRound(maxRadii * 2)), ptTxt,
            cv::FONT_HERSHEY_PLAIN, 1, clTxt);
        ptTxt.y += 15;

    //detects blobs
    cv::SimpleBlobDetector detector(blob_params);
    std::vector<cv::KeyPoint> keypoints;
    detector.detect(src_binary, keypoints);

    // draw all blobs in RED
    double maxRadius = 0;
    int radius;
    cv::Point center;
    int idx=-1;
    for (int i = 0; i < keypoints.size(); i++)
        radius = cvRound(keypoints[i].size);
        center = cv::Point(cvRound(keypoints[i].pt.x), cvRound(keypoints[i].pt.y));
        cv::circle(dst, center, radius, cv ...
edit flag offensive delete link more


Thank you for your code. Everything is working. I don't know how but I tested it before and can not do it. You solved my big problem. Thank you very much !!!

konradN gravatar imagekonradN ( 2015-11-23 13:27:36 -0500 )edit

i think you are good person that write program for people widout getting mony :-)

a123q89 gravatar imagea123q89 ( 2016-09-08 02:51:36 -0500 )edit

@a123q89 thank you for the good feeling. BTW my effort is nothing if compared to OpenCV authors ;-)

pklab gravatar imagepklab ( 2016-09-09 09:22:09 -0500 )edit

Question Tools

1 follower


Asked: 2015-11-17 13:45:12 -0500

Seen: 1,189 times

Last updated: Nov 22 '15