HSV color detection with OpenCV -


the "red" color-detection not working yet. following code supposed detect red bar input-image , return mask-image showing white bar @ corresponding location.

the corresponding hsv-values of "red" bar in inputrgbimage : h = 177, s = 252, v = 244

    cv::mat findcolor(cv::mat inputrgbimage) {      cv::mat imagehsv(inputrgbimage.rows, inputrgbimage.cols, cv_8uc3);     cv::mat imgthreshold(inputrgbimage.rows, inputrgbimage.cols, cv_8uc1);      // convert input-image hsv-image     cvtcolor(inputrgbimage, imagehsv, cv::color_bgr2hsv);      // red: (h < 14)     // cv::inrange(imagehsv, cv::scalar(0, 53, 185, 0), cv::scalar(14, 255, 255, 0), imgthreshold);     // or (h > 165) (...closing hsv-circle)     cv::inrange(imagehsv, cv::scalar(165, 53, 185, 0), cv::scalar(180, 255, 255, 0), imgthreshold);      return imgthreshold; } 

the 2 images below show inputrgbimage (top) , returned imgthreshold (bottom). can see, mask not showing white bar @ expected color "red" shows unknown reason @ "blue" bar. why ????

wrong mask 01

the following change of cv::inrange line of code (i.e. h > 120) , result again illustrates color detection not acting expected :

    // or (h > 120) (...closing hsv-circle)     cv::inrange(imagehsv, cv::scalar(120, 53, 185, 0), cv::scalar(180, 255, 255, 0), imgthreshold); 

wrong mask 02

as third example: (h > 100):

    // or (h > 100) (...closing hsv-circle)     cv::inrange(imagehsv, cv::scalar(100, 53, 185, 0), cv::scalar(180, 255, 255, 0), imgthreshold); 

wrong mask 03

why unexpected order of colors in 3 code-examples (decreasing h-value 165 100) showing mask orders of "blue->violet->red->orange" instead of expected hsv-wheel rough order of "red->violet->blue->green->yellow->orange" ?????

hsv table

hsv in opencv has ranges: 0 <= h <= 180, 0 <= s <= 255, 0 <= v <= 255, (not quite in illustrating graphic above - order of colors should same opencv hsv-colors - or not ???)

make sure image uses channel order b, g, r. also, color red need check 2 ranges of values, 1 around h=0 , other around h=180. try function:

cv::mat findcolor(const cv::mat & inputbgrimage, int rng=15) {     // make sure input image uses channel order b, g, r (check not implemented).     cv::mat input = inputbgrimage.clone();     cv::mat imagehsv;//(input.rows, input.cols, cv_8uc3);     cv::mat imgthreshold, imgthreshold0, imgthreshold1;//(input.rows, input.cols, cv_8uc1);     assert( ! input.empty() );      // convert input-image hsv-image     cv::cvtcolor( input, imagehsv, cv::color_bgr2hsv );      // in hsv-color space color 'red' located around h-value 0 , around     // h-value 180. why need threshold image twice , combine results.     cv::inrange(imagehsv, cv::scalar(      0, 53, 185, 0), cv::scalar(rng, 255, 255, 0), imgthreshold0);      if ( rng > 0 )     {         cv::inrange(imagehsv, cv::scalar(180-rng, 53, 185, 0), cv::scalar(180, 255, 255, 0), imgthreshold1);         cv::bitwise_or( imgthreshold0, imgthreshold1, imgthreshold );     }     else     {         imgthreshold = imgthreshold0;     }      return imgthreshold; } 

good luck! :)


Comments

Popular posts from this blog

angularjs - Showing an empty as first option in select tag -

python - argument 2 to map() must support iteration -

How to wrap some text in a rectangle in QML? -