Преобразование изображений OpenCV из RGB в оттенки серого с использованием imread, дающих плохие результаты

Я загружаю 24-битное RGB-изображение из PNG файла в свое приложение OpenCV.

Однако загрузка изображения в оттенках серого напрямую с помощью imread дает очень плохой результат.

Mat src1 = imread(inputImageFilename1.c_str(), 0);

Загрузка изображения RGB в формате RGB и преобразование его в оттенки серого дает гораздо лучший результат.

Mat src1 = imread(inputImageFilename1.c_str(), 1);
cvtColor(src1, src1Gray, CV_RGB2GRAY);

Мне интересно, правильно ли я использую imread для моего типа изображения. Кто-нибудь испытал подобное поведение?

Изображение, преобразованное в оттенки серого с помощью imread, показано здесь: Bad result

Изображение, преобразованное в оттенки серого с помощью cvtColor, показано здесь: Good result

Ответы

Ответ 1

У меня была такая же проблема сегодня. В конечном счете, я сравнил три метода:

//method 1
cv::Mat gs = cv::imread(filename, CV_LOAD_IMAGE_GRAYSCALE);

//method 2
cv::Mat color = cv::imread(filename, 1); //loads color if it is available
cv::Mat gs_rgb(color.size(), CV_8UC1);
cv::cvtColor(color, gs_rgb, CV_RGB2GRAY);

//method 3
cv::Mat gs_bgr(color.size(), CV_8UC1);
cv::cvtColor(color, gs_bgr, CV_BGR2GRAY);

Методы 1 (загрузка градаций серого) и 3 (CV_BGR2GRAY) дают идентичные результаты, тогда как метод 2 дает другой результат. Для моих целей я начал использовать CV_BGR2GRAY.

Мои входные файлы - это jpg, поэтому могут возникнуть проблемы, связанные с вашим конкретным форматом изображения.

Ответ 2

Простой ответ заключается в том, что функции openCV используют формат BGR. Если вы читаете изображение с imread или VideoCapture, это всегда будет BGR. Если вы используете RGB2GRAY, вы меняете синий канал на зеленый. Формула для получения яркости

y = 0.587*green + 0.299*red + 0.114*blue

поэтому, если вы измените зеленый и синий цвет, это вызовет огромную ошибку вычисления.

Приветствует

Ответ 3

У меня была аналогичная проблема, работая с шейдерами OpenGL. Кажется, что первый контейнер, в котором OpenCV читает ваше изображение, не поддерживает все диапазоны цветов, и, следовательно, вы видите, что изображение плохое преобразование в оттенках серого. Однако, как только вы конвертируете исходное изображение в оттенки серого с помощью cvtColor, контейнер отличается от первого и поддерживает все диапазоны. На мой взгляд, первый использует менее 8 бит для оттенков серого или переход в оттенки серого использует плохой метод. Но второй дает плавное изображение из-за большего количества бит в сером канале.