2015-12-10 3 views
0

На веб-сайте colorizer.org у них есть диапазон HSV H = 0-360, S = 0-100, V = 0-100. Мы также знаем, что диапазон HSV в OpenCV равен H = 0-180, S = 0-255, V = 0-255.Почему функция inRange не обнаруживает синий цвет, когда я дал ему весь возможный диапазон оттенков для синего цвета?

Я хотел выбрать диапазон для любого оттенка (что мы воспринимаем как) синего цвета, поэтому я посмотрел на colorizer.org и увидел, что синий оттенок варьируется примерно от 170 до 270. Поэтому я масштабировал этот диапазон оттенков до OpenCV делением на 2, что дает 85-135.

Теперь я взял следующий скриншот цвета [H=216, S=96, V=67] от просмотра на сайте

enter image description here

Затем я запустить приложение на своем телефоне и захватили следующие кадр камеры с экрана ноутбука. Я понимаю, что значения канала HSV будут отличаться от тех, на веб-сайте, в некоторой степени, потому что существуют и другие условия, как дополнительный свет (V в HSV) в комнате, когда я захваченной кадр камеры и т.д.

enter image description here

Затем я преобразовал это Mat в цветовое пространство HSV на Imgproc.cvtColor(rgbaFrame, hsvImage, Imgproc.COLOR_RGB2HSV_FULL);, что привело к следующему изображению.

enter image description here

Тогда я назвал inRange функцию:

Core.inRange(hsvImage, new Scalar(85, 50, 40), new Scalar(135, 255, 255), maskedImage); 

что привело к следующим maskedImage.

enter image description here

Вопрос заключается в том, что почему он не обнаруживает синий цвет, когда я включил все Hue Range возможно синего цвета на самом деле?


ВАЖНО: За исключением первого исходного изображения, все изображения были сохранены в SDCard с помощью Highgui.imwrite функции, так что я мог бы переместить их на свой компьютер, чтобы загрузить их на Stackoverflow. Вы, должно быть, заметили, что синий цвет в первом исходном скриншоте преобразуется в красный цвет во втором изображении. Причина в том, что кадр, снятый камерой (то есть фото/кадр первого снимка экрана, снятый камерой мобильного телефона), является изображением RGBA. Но OpenCV по умолчанию конвертирует все изображения в BRG, когда он сохраняет их на SD-карте. Поэтому будьте уверены, что исходное изображение RGBA, и оно полностью преобразуется в BGR внутри OpenCV для сохранения в SD-карте. Вот почему красный цвет выглядит синим.

+4

не ваше фото красный и черный .. где синий? –

+0

@HumamHelfawi Исходное фото - синее и черное, это было на моем компьютере. Посмотрите первое изображение. Это фотография. Я открыл его в Windows Photo Viewer на своем компьютере и захватил его с помощью своего телефона (на котором было запущено приложение Android). Захваченное фото - это второе изображение. Я сохранил его в своей SD-карте «Highgui.imwrite («/mnt/sdcard/DCIM/rgbaFrameCaptured.jpg », rgbaFrameCaptured); // check'. В нем синий цвет. Кроме того, вы видите этот беловатый фон, это было окружающее пространство вокруг фотографии, открытое в Windows Photo Viewer. – Solace

+0

@HumamHelfawi Пожалуйста, проигнорируйте преобразование синего в красный во втором изображении, потому что RGBA преобразуется в BGR, когда мы храним изображение, и я сохранил его на SD-карте, чтобы я мог перенести его на свой ноутбук, чтобы загрузить его на SO , Изображение на самом деле является RGBA (я знаю это, потому что этот кадр камеры возвращается функцией rgba() класса OpenCVCameraViewBridge, и согласно документации возвращается изображение rgba) – Solace

ответ

3

используя этот код работает для меня (C++):

cv::Mat input = cv::imread("../inputData/HSV_RGB.jpg"); 

    //assuming your image to be in RGB format after loading: 
    cv::Mat hsv; 
    cv::cvtColor(input,hsv,CV_RGB2HSV); 

    // hue range: 
    cv::Mat mask; 
    inRange(hsv, cv::Scalar(85, 50, 40), cv::Scalar(135, 255, 255), mask); 

    cv::imshow("blue mask", mask); 

Я использовал этот входной файл (сохраненный и загружен в формате BGR, хотя на самом деле является RGB изображения, поэтому мы должны использовать RGB2HSV вместо BGR2HSV):

enter image description here

в результате чего в этой маске:

enter image description here

Разница с вашим кодом заключается в том, что я использовал CV_RGB2HSV вместо CV_RGB2HSV_FULL. Флаг CV_RGB2HSV_FULL использует весь байты для хранения значений цветового тона, поэтому диапазон 0 .. 360 degrees будет отрегулирован 0 .. 255 вместо 0 .. 180 как в CV_RGB2HSV

Я мог убедиться в этом, используя эту часть кода:

// use _FULL flag: 
    cv::cvtColor(input,hsv,CV_RGB2HSV_FULL); 
    // but scale the hue values accordingly: 
    double hueScale = 2.0/1.41176470588; 
    cv::Mat mask; 
    // scale hue values: 
    inRange(hsv, cv::Scalar(hueScale*85, 50, 40), cv::Scalar(hueScale*135, 255, 255), mask); 

дает этот результат:

enter image description here

для тех, кто хочет испытать с «правильной» картинки:

Вот вход, преобразованный в BGR: Если вы хотите использовать это непосредственно, вам нужно переключить преобразование с RGB2HSV на BGR2HSV. Но я подумал, что было бы лучше, чтобы показать версию BGR на входе, тоже ...

enter image description here

+1

Я не могу поблагодарить вас за объяснительные ответы на мой вопрос вчера и сегодня. Большое вам спасибо, да благословит вас Бог =) – Solace