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 ????

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); 
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); 
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 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
Post a Comment