Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: artall64 от Март 26, 2010, 08:27



Название: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: artall64 от Март 26, 2010, 08:27
Здравсвуйте!
Пишу приложение работающее с двумя IP камерами.
Реализовал, потоки приёма, декодирования(из JPEG), обработки, форму GUI.

При этом отрисовка сделана, следующим образом:
Поток обработки загружает сырые данные в QPixmap, и высылает сигнал (QPixmap* img1,QPixmap*img2) в объект формы через Qt::BlockingQueuedConnection
Слот приёма масштабирует Pixmap под размеры QLabel на форме, предназначенного для отрисовки, далее QLabel::setPixmap.

Вопрос насколько корректна такая реализация, в случае если необходимо достичь наиболее быстрой отрисовки(25 fps) из сырых данных ?
Лучше ли будет использовать QGLWidget, или попробовать встроить SDL ?
Приложение ориентировано на Windows. Есть ли смысл и возможность встроить DirectX для отрисовки ?
Возможна какая либо более быстрая отрисовка, с прямым использованием win api в Qt приложении ?
В общем в какую сторону смотреть ?


Название: Re: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: Akaiten от Март 26, 2010, 09:20
А какова скорость отрисовки для текущей реализации?


Название: Re: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: ieroglif от Март 26, 2010, 09:24
немного не понял - почему готовая картинка запихивается  в QLabel?
попробуй сделай свой собственный виджет и отрисовывай в нём на его paintEvent.. можно ещё отпихнуть это в отдельный поток что бы не торзмозила основная программа.
не уверен, но мне кажется что это быстрее будет..
кроме того надо посмотреть где медленная точка - именно в отрисовывании или где-то раньше.
может вообще имеет смысл писать картинки в видео поток и его отображать через "плеер"?


Название: Re: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: GreatSnake от Март 26, 2010, 11:45
Цитировать
Поток обработки загружает сырые данные в QPixmap, и высылает сигнал (QPixmap* img1,QPixmap*img2) в объект формы через Qt::BlockingQueuedConnection
Слот приёма масштабирует Pixmap под размеры QLabel на форме, предназначенного для отрисовки, далее QLabel::setPixmap.
В корне неправильный подход.
Qt любые трансформации изображения делает только через QImage.
Т.е. у вас сначала создается QImage, который вы потом перегоняете в QPixmap в GDI, потом этот QPixmap из GDI перегоняется в QImage, масштабируется и опять перегоняется в QPixmap в GDI. И имейте в виду, что Qt для double buffering держит ещё один QPixmap размером в top-level окно.  В итоге получается довольно-таки не хилый трафик.
Предлагаю просто отказаться от QPixmap, использовать вместо него QImage и уже в paintEvent() через QPainter::drawImage() отрисовывать результирующее изображение.
Ежели после этого скорость не будет устраивать, то наверное стоит смотреть в сторону DirectX.


Название: Re: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: artall64 от Март 26, 2010, 19:18
А какова скорость отрисовки для текущей реализации?
Итоговая скорость отрисовки для двух изображений 6-7 fps.

немного не понял - почему готовая картинка запихивается  в QLabel?
попробуй сделай свой собственный виджет и отрисовывай в нём на его paintEvent.. можно ещё отпихнуть это в отдельный поток что бы не торзмозила основная программа.
не уверен, но мне кажется что это быстрее будет..
кроме того надо посмотреть где медленная точка - именно в отрисовывании или где-то раньше.
может вообще имеет смысл писать картинки в видео поток и его отображать через "плеер"?
Внимательно промерил критические участки кода, проблема действительно не в отрисовке
Критический участок 130-230 ms загрузка из сырых данных - вызов метода  QPixmap::loadFromData( const uchar * data, uint len, "bmp" )
Масштабирование + Отрисовка (в моем понимании вызов QLabel::setPixmap( const QPixmap & ) поправьте если не так )
занимает для двух изображений только 30 - 50 ms.
QLabel использовал в силу собственной глупости  :(

Цитировать
Поток обработки загружает сырые данные в QPixmap, и высылает сигнал (QPixmap* img1,QPixmap*img2) в объект формы через Qt::BlockingQueuedConnection
Слот приёма масштабирует Pixmap под размеры QLabel на форме, предназначенного для отрисовки, далее QLabel::setPixmap.
В корне неправильный подход.
Qt любые трансформации изображения делает только через QImage.
Т.е. у вас сначала создается QImage, который вы потом перегоняете в QPixmap в GDI, потом этот QPixmap из GDI перегоняется в QImage, масштабируется и опять перегоняется в QPixmap в GDI. И имейте в виду, что Qt для double buffering держит ещё один QPixmap размером в top-level окно.  В итоге получается довольно-таки не хилый трафик.
Предлагаю просто отказаться от QPixmap, использовать вместо него QImage и уже в paintEvent() через QPainter::drawImage() отрисовывать результирующее изображение.
Ежели после этого скорость не будет устраивать, то наверное стоит смотреть в сторону DirectX.
Большое спасибо!!! сделаю данную реализацию.

Единственное, беспокоит следующий вопрос:
Планирую использовать QImage::loadFromData ( const uchar * data, int len, "bmp" )
думаю время выполнения будет сравнимо с 130-230 ms для QPixmap::loadFromData( const uchar * data, int len, "bmp" ) см.выше
Из за того, что, как предполагаю, при вызове протормаживает на выделении памяти под новое изображение.
Обязательно проверю, попробую глянуть сорцы. Но хотел бы спросить:
Какой наиболее быстрый способ загрузить QImage из сырых данных ?
т.е. как я понимаю, избежать операции выделения в памяти, использовав раннее выделенный участок в объекте QImage.
P.S. или я, что то перемудрил :) поправьте ;)


Название: Re: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: GreatSnake от Март 26, 2010, 19:26

Код
C++ (Qt)
 
       QImage img;
 
QBuffer b;
b.setData( data, len );
b.open( QIODevice::ReadOnly );
 
       QImageReader ir( &b, "bmp" );
 
       ir.read ( &img );
 
 


Название: Re: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: artall64 от Март 26, 2010, 19:44

Код
C++ (Qt)
 
       QImage img;
 
QBuffer b;
b.setData( data, len );
b.open( QIODevice::ReadOnly );
 
       QImageReader ir( &b, "bmp" );
 
       ir.read ( &img );
 
 

Ок  ;) Большое спасибо, а то я уже хотел пробовать создавать QIODevice, записывать через write, потом в конструктор QImageReader.


Название: Re: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: _govorilka от Март 29, 2010, 08:26
У меня сейчас похожий проект. Для загрузки RAW данных с камеры использую:

Код:
QImage::QImage ( uchar * data, int width, int height, Format format )

при использование этого конструктора QImage не создает нового буфера для хранения данных и не управляет им (не удаляет его в деструкторе).


Название: Re: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: artall64 от Апрель 14, 2010, 11:33
Вобщем, укзанные пероприятия особого прироста в скорости не дали.
В т.ч. использование QImageLoader для RAW изображения 1600х1200 + BMP заоловок занимает от 30 до 80 мс, также как конструктор QImage ( uchar * data, int width, int height, Format format ).

Проблему решил напрямую используя GDI при отрисовке своего виджета, загрузка + отрисовка + маштабирование 5-10 мс, + значительно снизилась нагрузка на ЦП.

Всем спасибо!


Название: Re: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: psgenn от Март 29, 2011, 18:43
Проблему решил напрямую используя GDI при отрисовке своего виджета, загрузка + отрисовка + маштабирование 5-10 мс, + значительно снизилась нагрузка на ЦП.
А можно по подробнее.


Название: Re: Быстрая отрисовка изображений с камер 1600x1200
Отправлено: panAlexey от Март 29, 2011, 23:05
Проблему решил напрямую используя GDI при отрисовке своего виджета, загрузка + отрисовка + маштабирование 5-10 мс, + значительно снизилась нагрузка на ЦП.
не вылетает?
с винапой надо поосторожнее работать...