Форум программистов, компьютерный форум, киберфорум
C++: OpenCV
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.92/39: Рейтинг темы: голосов - 39, средняя оценка - 4.92
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36

Некорректность цветопередачи QImage, полученного из IplImage (OpenCV)

25.02.2013, 20:08. Показов 9274. Ответов 39
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Проблема заключается в некорректной конвертации изображения из формата IplImage (OpenCV) в формат QImage (Qt). Передачу данных осуществляю следующим путем (получаю изображение в IplImage и передаю его в QImage):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    IplImage* img = cvLoadImage( "E:\\ocv\\example.jpg" );
    QImage* qImg = new QImage(
        (uchar *)img->imageDataOrigin,
        img->width,
        img->height,
                QImage::Format_RGB888
                );
 
    cvShowImage("cvtest5", img);
    
    cvDrawLine(img,cvPoint(260,0),cvPoint(260,10),cvScalar(0xff,0x00,0x00));
 
    QLabel myLab;
    myLab.setPixmap(QPixmap::fromImage(*qImg));
    myLab.show();
Результат следующий:

В Пикаса показан оригинал изображения, в окне "cvtest5" - он же, отображенный с помощью средств OpenCV, в окне "test5" - он же, перегнанный из IplImage в QImage. Если его открыть таким образом:
C++
1
2
3
4
5
6
7
8
9
/*     QImage* qImg = new QImage(
        (uchar *)img->imageDataOrigin,
        img->width,
        img->height,
                QImage::Format_RGB888
                );
*/
        QImage* qImg = new QImage();
        qImg->load("E:\\ocv\\example.jpg" );
то все выглядит красиво:

Вариант, что некорректно отображаются цвета на мониторе не подходит (что доказано последним экспериментом и...), в основном проекте пробывал QImage сохранять в jpeg следующим путем:
C++
1
2
3
4
5
void rgbForm::on_pushButton_saveImage_clicked() {
    QString fName = QFileDialog::getSaveFileName(this, tr("Save File"),"",
                                                 tr("Image File (*.jpeg)"), 0);
    qImg->save(fName, "JPEG");
}
В результате ничего хорошего не получил (далее по порядку - то что "видит" опенсв, то что "видит" КьюТе и сохраненный джпег):

Я вроде создаю 3-канальное изображение (QImage::Format_RGB888), но все же такое ощущение, что вмешивается альфа-канал и "портит" картинку. На тестовом приложении пробывал сравнивать в определенных точках значения каждого канала (красный, зеленый, голубой), вроде как совпадают по значению и не перепутаны ( например, вместо РГБ - находится БГР).
И еще одно изображение:

Хочу обратить внимание, что левая часть изображения (коричневая) не сильно "пострадала", в отличии от более светлых.

Буду рад любой помощи, пока буду дальше копать. Производить копирование данных по каждому каналу отдельно или использую структуру cvMat не очень хочется, но... если не будет других вариантов, а они дадут результат - будем делать так, чтобы было красиво!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
25.02.2013, 20:08
Ответы с готовыми решениями:

OpenCV: конвертация IplImage в серый
Здравствуйте! Работаю с библиотекой OpenCV. Не могу корректно преобразовать IplImage в серый цвет. Изображение становится серым, как и...

OpenCV. IplImage* cvCreateImage в Mat
Здравствуйте! Как написать то что IplImage, но через Mat? IplImage *dd = cvCreateImage(cvGetSize(img), img->depth, 1); в что-то...

Извлечение трёх цветовых компонент из IplImage* rgb (OpenCV)
Данные в переменную заносятся так: IplImage* image; IplImage* rgb = 0; // получаем любую подключённую камеру CvCapture*...

39
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
26.02.2013, 19:57  [ТС]
Студворк — интернет-сервис помощи студентам
Как я и боялся, в основном проекте проблема не решилась (буду возвращаться к своим блюдечкам). Почему-то там избыточности нет (может ширина рисунка в пикселях делиться на 4). А вот пересчетом байтов в виде
C++ (Qt)
1
const int bytes_per_line = width*depth;
добился только того, что по моему мнению должно было бы быть, если была избыточность как в тестовом проекте.
Оригинал:

Результат:


Копаю дальше!
0
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
26.02.2013, 20:00  [ТС]
Цитата Сообщение от dphn Посмотреть сообщение
Наверное, скидывайте код
Какой? с линиями я скинул. основной проект? он у меня немаленький, работает только в "ручном" режиме (прикрепляю "нужные" файлы настроек, "нужное" видео и т.д. и т.п.)...
0
4 / 1 / 0
Регистрация: 26.02.2013
Сообщений: 30
26.02.2013, 20:05
А что говорит QImage::format() ?

Добавлено через 5 минут
Ага, ссори, у меня тут в загрузках небольшой бардак, щас я попробую сам ваши исходники прогнать.
0
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
26.02.2013, 20:14  [ТС]
Цитата Сообщение от dphn Посмотреть сообщение
А что говорит QImage::format() ?
Если Вы о основном проекте, то выводит 13, что соответствует по "qimage.h" как раз Format_RGB888

C++ (Qt)
1
2
3
4
5
6
void rgbForm::watched_Image(unsigned char * a, int b, int c) {
    qImg = new QImage( a, b, c, QImage::Format_RGB888 );
    ui->label->setPixmap(QPixmap::fromImage(*qImg));
    ui->label->show();
    qDebug() << qImg->format();
}
0
4 / 1 / 0
Регистрация: 26.02.2013
Сообщений: 30
26.02.2013, 20:18
Ах ты черт, а ведь вы правы с вычислениями, мало того, эта проблема уже поднималась http://victoropencv.blogspot.c... image.html

Добавлено через 45 секунд
//По неизвестным причинам pImage->bytesPerLine() и im.widthStep могут не совпадать
0
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
26.02.2013, 20:22  [ТС]
Цитата Сообщение от dphn Посмотреть сообщение
мало того, эта проблема уже поднималась
более того! эту ссылку я уже сегодня тут публиковал!
Цитата Сообщение от DEngine Посмотреть сообщение
Есть вариант, конечно, копировать данные по каналам (пока не проверял).
))
Вы, dphn, думаете, я перед тем как на форуме "поднять" тему не проверил наличие решения в инете ( мне даже так быстрей, чем дергать людей и ждать реакции). Поскольку данный вопрос не грозит быстрым решением, я , как можно заметить, пытаюсь и дальше его решить, но и паралельно закинул на форум вопрос!
0
4 / 1 / 0
Регистрация: 26.02.2013
Сообщений: 30
26.02.2013, 20:28
Про негрозит быстрым решением, это вы зря. Ссылку-то я, конечно не заметил, каюсь, но у меня есть смягчающие . Щас попробуем разобраться, причем, очевидно, что копать надо с qt, поскольку при значениях по умолчанию все ок. Вопрос в том, что является значениями по умолчанию.

Добавлено через 1 минуту
имеется ввиду при
QImage* qImg = new QImage();
qImg->load("E:\\ocv\\example.jpg" );
0
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
26.02.2013, 20:36  [ТС]
Цитата Сообщение от dphn Посмотреть сообщение
Про негрозит быстрым решением, это вы зря
Ну у нас о времени разные понятия... я просто вторые сутки над этим бьюсь - а это уже долго.

Проблема возникает в распознавании QImage-ом сырых данных воспринятых.... И пусть это будет некрасиво звучать, но такое ощущение, что у меня появляется маска из голубого цвета, которая портит рисунок (естественно, на коричневых это не так заметно, а на желтых цветах рисунка это очень хорошо проявляется....). Как будто на голубом канале, у Qt и OpenCV различаются битности и в Qt передаются большие значения голубого, чем они есть в реалии...

Я похожий эффект как-то отхватывал пережимая видео в avi и в результате, например KMPlayer "хавал" его нормально,а на VLC media player-e тоже были "засиненные" цвета.... Может, где-то не в той стороне ищем решение? может это как-то связано с платформами (я о осях)...
0
4 / 1 / 0
Регистрация: 26.02.2013
Сообщений: 30
26.02.2013, 20:49
Если вы имеете ввиду ICM - она здесь не важна. Все цветовые преобразования используют один и тот же алгоритм (либо без профиля, либо системный), устройство вывода не меняется (тот же монитор, на котором смотрим исходник, на нем же смотрим и преобразования). В общем, нужно курить маны. Чем я щас и займусь.
0
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
26.02.2013, 21:05  [ТС]
Цитата Сообщение от dphn Посмотреть сообщение
вы имеете ввиду ICM
а можно для чайников (буду очень признателен Вам, а еще лучше с ссылочкой на стандарт или вики хотя бы), ибо гугль выдает очень много мусора? я так это догадываюсь технология/алгоритм цветообразования для вывода (в частности, на монитор).
Если - да, то - нет, наверное. Я плохо знаю теорию компьютерной графики (поэтому тяжело иногда сформулировать мысли). Но (мне так кажется, хДДДД), что это на подобии использования разных алгоритмов или библиотек, zum Beispiel, OpenCV юзает DirectX, a Qt - OpenGL (это я херню, конечно, сморозил, но по другому я никак объяснить не могу свои бредовые мысли). Но, в чем я процентов на 60-70 уверен, так это то, что голубой канал некорректно передается/воспринимается QImage-м/отображается QImage-м (нужное подчеркнуть).

Я склонился к разбору сырцов Qt а вдруг там накопаю свое решение!
0
4 / 1 / 0
Регистрация: 26.02.2013
Сообщений: 30
26.02.2013, 21:40
Ну, вообще-то вот http://en.wikipedia.org/wiki/ColorSync, с учетом, что icm - то же самое, только теоретически более универсальное, а практически - под виндовс ))). Не заморачивайтесь, щас у меня opencv докомпилится, будем искать.
0
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
26.02.2013, 21:44  [ТС]
Цитата Сообщение от dphn Посмотреть сообщение
Не заморачивайтесь
Это для себя, а вдруг когда-то нужно будет, поэтому в общих чертах стоит посмотреть, но, действительно, не сейчас)))

dphn, я честно рад, что Вы так близко приняли мою проблему к сердцу.... Но звиняйте, я дето через полчасика свинчу с работы ... и ужо завтра только вернусь к проблеме (дома есть свои проблемы, которые нужно решать) да и мозги уже "закипают" за целый день штудирования проблемы!
0
4 / 1 / 0
Регистрация: 26.02.2013
Сообщений: 30
26.02.2013, 21:48
Да вы и так подзадержались . Но - респект.
Я попробую решить вопрос. До завтра.
0
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
26.02.2013, 23:28  [ТС]
Кстати, чего еще вычитал из сырцов...

Ребята из Qt при вызове конструктора
C++ (Qt)
1
QImageData * QImageData::create(const QSize &size, QImage::Format format, int numColors)
используют смещение битов (напоминаю как это выглядит):
C++ (Qt)
1
const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4)
а вот когда создают экземпляр QImage с помощью конструктора
C++ (Qt)
1
QImageData *QImageData::create(uchar *data, int width, int height,  int bpl, QImage::Format format, bool readOnly)
все на много проще:
C++ (Qt)
1
const int calc_bytes_per_line = ((width * depth + 31)/32) * 4;
А вот при вызове ф-ции подсчета байтов на линию (, которой я пользовался в более раннем посте), вообще берут общий размер данных:
C++ (Qt)
1
2
3
4
int QImage::bytesPerLine() const
{
    return (d && d->height) ? d->nbytes / d->height : 0;
}
В обоих случаях, nbytes считается как
C++ (Qt)
1
nbytes = bytes_per_line*height;
От так...

dphn, если удастся "решить" вопрос забульбеню специально пост о "подводных камнях" QImage и его работе с сырыми данными (вот уже "нашелся" подсчет размеров)

dphn, до завтра и большое спасибо за участие (+1 спасибо кнопочки у Вас, к сожалению, нет, так бы "наклацал" )

Добавлено через 1 час 23 минуты
Возникла еще одна теория, которая требует подтверждения... (если придумаю как - попробую проверить...)

Идея в чем: при оперировании данными, точно не помню на каком этапе (завтра пересмотрю сырцы), но данные начинают фигурировать в типе quint32 (вот зачем ребята из Qt приводят размер к величине, кратной 4). При этом, как я понял альфа-канал забивается значением 0xff. Если где-то проскакивают "глюки", может где-то он начинает "забиваться" другим значением (хотя я пока слабо это себе представляю) и поэтому картинка меняет свою цветность...

Будем пробовать проверять эту теорию... Ну и, наверное, стоит попробовать поменять каналы (RGB/BGR). Чем черт не шутить))))
0
4 / 1 / 0
Регистрация: 26.02.2013
Сообщений: 30
27.02.2013, 03:56
Должен признаться, opencv закомпилить под kde мне не удалось, к сожалению. Из репозитория тоже не устанавливается, слишком много gtk зависимостей
Пакеты, имеющие неудовлетворённые зависимости:
libhighgui-dev : Зависит: libgtk2.0-dev но он не будет установлен
...
Все, что удалось проверить, это
QImage* qImg = new QImage();
qImg->load("example.jpg" );
qDebug() << qImg->format();

выдает 4, что соответствует формату Format_RGB32
и предполагает наличие альфа-канала, который представлен значением 0xff, то есть полностью непрозрачен.
Но если не заморачиваться, можно попробовать, как здесь: https://www.developer.nokia.co... CV_with_Qt
Тут два метода, конвертация в обе стороны и в QImage, и в IplImage

Добавлено через 11 минут
Хотя ваш метод (и в особенности, процесс) весьма любопытен.
0
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
27.02.2013, 13:30  [ТС]
Цитата Сообщение от dphn Посмотреть сообщение
Но если не заморачиваться, можно попробовать, как здесь: https://www.developer.nokia.co... CV_with_Qt
Спасибо, за ссылку, посмотрю.
То, что 4 канала все-таки используется я вчера тоже подумал, но не уверен, что из-за этого сыр-бор (если это правда, то отсюда вытекает, что где-то сидит "бабайка" и иногда альфа-канал заполняет не значением "0xff", что довольно печально само по себе, как для пользователей библиотеки, так и для самих троллей).

Цитата Сообщение от dphn Посмотреть сообщение
Должен признаться, opencv закомпилить под kde мне не удалось, к сожалению
На работе у меня, к несчастию моему, только седьмые форточки, и даже опенсорсные оси мне запретили ставить (чтоб их *** да им *** ). А дома у меня гномовская федора 17. ОпенСВ 2,2,0 на ней мне собрать не удалолсь, а вот 2,4,1 пашет))) Какую Вы пробовали собрать?

Кстати, раз затронули этот вопрос. Под линем у меня осв чудесно работает (я свой проект не единожды гонял), но в спарке с Qt и QCreator-ом вышла какая-то ахинея (не находит осв библиотек во время запуска). Пока не было времени разбираться, в основном всю работу делаю на работе (вот такая тавтология) и руки не доходят. НО! Всему свое время и до туда руки дойдут(уже попадались похожие статьи) ))

Добавлено через 4 минуты

Не по теме:

dphn, у вас отключены личные сообщения - если не секрет: где Вы территориально находитесь?

0
4 / 1 / 0
Регистрация: 26.02.2013
Сообщений: 30
27.02.2013, 13:42
Я на этом форуме был когда-то давно, а щас заскочил случайно и ненадолго. Отдохну, отдышусь, побегу дальше... Я из Харькова.
0
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
27.02.2013, 14:12  [ТС]
Почти земляк... ))) Харьков привет, уже больше, чем полгода, как не был в этом замечательном городе...

И вот это Вам не лень было сидеть до часу ночи?? ... )))
0
4 / 1 / 0
Регистрация: 26.02.2013
Сообщений: 30
27.02.2013, 14:14
я ненавижу нерешенные задачи. И помню, как сам разбирал исходники Qt, причем задача была в чем-то похожа на вашу...
Удачи
0
1 / 1 / 0
Регистрация: 14.05.2010
Сообщений: 36
27.02.2013, 15:04  [ТС]
Ну, что?
Лёд тронулся, господа присяжные заседатели!
Я признаю за собой звание - упрямого глупца.

Чистый, был прав, идет неправильная передача каналов (перепутаны R и B каналы). Как указано здесь (Огромнейшее спасибо dphn за ссылку), добавляем после передачи каналов функцию:
C++ (Qt)
1
QImage QImage::rgbSwapped () const
и все чудесно начинает работать.

Более того еще раз пересмотрел документацию по OpenCV , где сказано следующее:
int dataOrder
0 = IPL_DATA_ORDER_PIXEL - interleaved color channels, 1 - separate color channels. CreateImage() only creates images with interleaved channels. For example, the usual layout of a color image is: b00g00r00b10g10r10
т.е. используется формат BGR.

Объясняю почему я так упорствовал: данный код:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
        IplImage* img = cvLoadImage( "E:\\ocv\\example.jpg" );
 
    QImage* qImg = new QImage(
        (uchar *)img->imageData,
        img->width,
        img->height,
        QImage::Format_RGB888
                );
 
    qDebug() << "Quantity Bytes per Line:  " << qImg->bytesPerLine() ;
 
        cvShowImage("cvtest5", img);
    
    qDebug() << *((uchar*) (img->imageData + 0 * img->widthStep + 260*img->nChannels + 0)) << " "
        << *((uchar*) (img->imageData + 0 * img->widthStep + 260*img->nChannels + 1)) << " "
        << *((uchar*) (img->imageData + 0 * img->widthStep + 260*img->nChannels + 2));
    
    const QPoint p2(260,0);
    
    qDebug() << qRed(qImg->pixel(p2)) << " "
           << qGreen(qImg->pixel(p2)) << " "
           << qBlue(qImg->pixel(p2));
 
    cvDrawLine(img,cvPoint(260,0),cvPoint(260,10),cvScalar(0xff,0x00,0x00));
 
    qDebug() << qRed(qImg->pixel(p2)) << " "
           << qGreen(qImg->pixel(p2)) << " "
           << qBlue(qImg->pixel(p2));
 
    QLabel myLab;
    myLab.setPixmap(QPixmap::fromImage(qImg->rgbSwapped()));
    myLab.show();
дает следующий вывод результатов:
Bash
1
2
3
4
Quantity Bytes per Line:   1536 
132   123   114 
132   123   114 
255   0   0
где, хочу обратить, первое для Qt число в строчке соответствует красному каналу (это заметно даже по точке на нарисованной красной линии), и значение по каналам изначального изображения совпадают (т.е., вроде как у IplImage данные imageData тоже идут в формате RGB) - вот это мне непонятно.

Если кто дураку объяснить, чего я не могу понять - буду очень благодарен!
И еще раз БОЛЬШОЕ СПАСИБО тем, кто помогал мне в решении этой проблемы.

А с OpenCV вопрос взял себе на заметку (для ОСВ данные очень важны) и чуть позже все-таки постараюсь разобраться с этим вопросом.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
27.02.2013, 15:04

Что использовать Mat или IplImage в OpenCV? Где правда?
В OpenCV есть два стиля С++ и С. В первом случае в примерах используют переменную Mat для описания изображения. Во втором случае -...

Как преобразовать Bitmap (System::Drawing::Image) в IplImage*frame (openCV)?
Как преобразовать Bitmap (System::Drawing::Image) в IplImage*frame (openCV)

Как сохранить QImage (Qt) в lplImage (OpenCV)?
Как сохранить QImage (Qt) в lplImage (OpenCV)?

Как отобразить QImage сложной формы на другом QImage, чтобы фон от 1-го рисунка был прозрачен?
пишу простеньку игрушку в целях осваивания QT. Задача - нарисовать 1 объект QImag поверх другого объекта QImag. Как это сделать ...? ...

Нарушение цветопередачи в видео
Странно работает видеокарта Как это вылечить? Проблема проявляется только при воспроизведении видео (В плеере, и на ютубе в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru