Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

imho, inRange() on a hsv image will already get you quite far.

some tricks to improve:

  • blur. as much as you can.
  • try to sample as many green spots in the images, as you can, then build your range based on mean/stdev of those:


#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;

Mat im_hsv, dist;
void pick_color(int e, int x, int y, int s, void *)
{
    if (e==1)
    {
        int r = 3;
        int off[9*2] = {0,0, -r,-r, -r,0, -r,r, 0,r, r,r, r,0, r,-r, 0,-r};
        for (int i=0; i<9; i++)
        {
            Vec3b p = im_hsv.at<Vec3b>(y+off[2*i], x+off[2*i+1]);
            cerr << int(p[0]) << " " << int(p[1]) << " " << int(p[2]) << endl;
            dist.push_back(p);
        }
    }
}

int main( int argc, char** argv )
{
    namedWindow("blue");
    setMouseCallback("blue", pick_color);

    String c_in = "."; // check a whole folder.
    if (argc>1) c_in = argv[1]; // or an image
    vector<String> fn;
    glob(c_in, fn, true);
    for(size_t i=0; i<fn.size(); i++)
    {
        Mat im_bgr = imread(fn[i]);
        if (im_bgr.empty()) continue;
        cvtColor(im_bgr, im_hsv, COLOR_BGR2HSV);
        imshow("blue", im_bgr);
        int k = waitKey() & 0xff;
        if (k==27) break; // esc.
    }
    Scalar m,v;
    meanStdDev(dist,m,v);
    cerr << "mean, var: " << endl;
    cerr << m[0] << " " << m[1] << " " << m[2] << " " << v[0] << " " << v[1] << " " << v[2] << endl;
    return 0;
}

i got values, similar to this:

[29.1045 100.815 64.5172] [6.03475 36.778 19.7858]

later, you can build a range from mean and stddev:

Scalar lo(m[0]-v[0], m[1]-v[1], m[2]-v[2]); // mean-var for low
Scalar hi(m[0]+v[0], m[1]+v[1], m[2]+v[2]); // mean + var for high

cvtColor(im_bgr, im_hsv, COLOR_BGR2HSV);
blur(im_hsv, im_hsv, Size(8,8));

Mat mask;
inRange(im_hsv, lo, hi, mask);
im_bgr.setTo(Scalar(0,255,255), mask); // i used yellow, to make it more visible..

image description