2015-03-29 5 views
1

«Красный» датчик цвета еще не работает. Следующий код должен обнаруживать красную полосу от входного изображения и возвращать изображение маски с белой полосой в соответствующем месте.Обнаружение цвета HSV с помощью OpenCV

Соответствующие HSV-значений "красного" бара в inputRGBimage являются: Н = 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 to HSV-image 
    cvtColor(inputRGBimage, imageHSV, cv::COLOR_BGR2HSV); 

    // for 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; 
} 

Два изображения ниже показывают inputRGBimage (вверху) и возвращен imgThreshold (внизу). Как вы можете видеть, маска не показывает белую полосу с ожидаемым цветом «красный», но показывает ее по неизвестной причине на «синей» полосе. Зачем ????

wrong mask 01

Следующая смена сорта :: InRange строка кода (т.е. H> 120) и его результат еще раз показывает, что обнаружение цвета фактически не действует, как ожидалось:

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

в качестве третьего примера: (Н> 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

Почему неожиданный заказ цветов в моих 3 кодовых примерах (уменьшение H-значение от 165 до 100), показывающая маски приказов «сине> violet-> красно-> оранжевого» вместо того, чтобы фактически ожидаемый HSV-колесный грубый порядок «красный-> фиолетовый-> синий-> зеленый-> желтый-> оранжевый" ?????

HSV table

ВПГ в OpenCV имеет диапазоны: = H < = 180, = S < = 255, = V < = 255, (не совсем, как в иллюстрирующего графике выше, но порядок цветов должен быть одинаковым для цветов OpenSCV HSV - или нет)

+1

2 вещи: 1-й оттенок разделен на две области: от 0 до x и x до 180, поэтому вам нужно два inRange или вам нужно «сдвинуть» ваш оттенок. 2nd: возможно увеличение насыщенности и диапазон значений до 0..255 или n..255 – Micka

+0

ваши результаты теста странные. проверит завтра – Micka

+2

Ваш вход называется 'inputRGBimage', но вы конвертируете его в HSV, используя флаг' cv :: COLOR_BGR2HSV'. Итак, какой канал вы используете, RGB или BGR? Если вы используете первое, это объяснит, почему обнаружены синие области. – nils

ответ

2

Убедитесь, что изображение использует порядок каналов B, G, R. Также для красного цвета вам нужно проверьте два диапазона значений, один вокруг H=0 a d другой около H=180. Вы можете попробовать эту функцию:

cv::Mat findColor(const cv::Mat & inputBGRimage, int rng=15) 
{ 
    // Make sure that your input image uses the 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 to HSV-image 
    cv::cvtColor(input, imageHSV, cv::COLOR_BGR2HSV); 

    // In the HSV-color space the color 'red' is located around the H-value 0 and also around the 
    // H-value 180. That is why you need to threshold your image twice and the combine the 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; 
} 

Удачи вам! :)