2016-07-26 3 views
2

текущим решением выглядит следующим образом:Отображение потока изображений с Qt

//paintlabel.h 
class PaintLabel : public QWidget 
{ 
    Q_OBJECT 

public: 
    explicit PaintLabel(QWidget *parent = 0); 

public slots: 
    void setImage(char *img_ptr, QSize img_size, int pitch); 

protected: 
    void paintEvent(QPaintEvent *event) override; 

private: 
    QImage image; 

} 

//paintlabel.cpp 

PaintLabel::PaintLabel(QWidget *parent) : QWidget(parent) 
{ 
    setAttribute(Qt::WA_NoSystemBackground, true); 
} 

void PaintLabel::setImageLive(char *img_ptr, QSize img_size, int pitch) 
{ 
    image = QImage((uchar *)img_ptr, img_size.width(), img_size.height(), pitch, QImage::Format_RGB32).scaled(this->size()); 
    update(); 
} 

void PaintLabel::paintEvent(QPaintEvent *event) 
{ 
    Q_UNUSED(event); 
    QPainter painter; 
    painter.begin(this); 
    if (!image.isNull()) { 
     const QPoint p = QPoint(0,0); 
     painter.drawImage(p, image); 
    } 
    painter.end(); 
} 

Я ожидаю, что 20-40 кадров в секунду. Проблема в том, что производительность очень мала с размером. При размере вокруг fullHD картина занимает 1-2 мс. Но если я изменю его размер до 4k, он становится ужасно лаги (16 мс). Есть ли способ реализовать ту же функциональность, но с меньшим потреблением ресурсов?

Теоретически, если я изменяю родительский класс на QOpenGLWidget, QPainter запускается с аппаратным ускорением. Но, делая это, он работает еще медленнее.

+0

В OpenGL вы можете использовать двойную буферизацию, чтобы избежать этого. Возможно, вы можете иметь 2 PaintLabel и не показывать новое изображение до его загрузки. – JMA

+0

Двойная буферизация на самом деле не изменяет тот факт, что рендеринг очень медленный. Я бы оценил его 3-5 кадров в секунду, в то время как камера производит 25. –

ответ

3

Во-первых, одним из ограничивающих факторов в вашем коде является функция scaled(). Попытайтесь взять его, и вы должны увидеть некоторое ускорение.

Другой проблемой является просто ограничение производительности QImage. См. Этот вопрос для получения дополнительной информации. How can QPainter performance be improved?

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

см. http://doc.qt.io/qt-5/topics-graphics.html для получения дополнительной информации.

Вы не можете перейти на QPixmap, так как весь ваш буфер меняет каждый кадр.

Вы можете попробовать использовать QOpenGLPaintDevice, чтобы использовать аппаратное ускорение QPainter. Другой подход, который вы пробовали, - QOpenGLWidget.

QOpenGLWidget - Живописец также можно открыть на QOpenGLWidget. Это предоставляется в качестве удобства, поскольку технически это ничем не отличается от использования QOpenGLPaintDevice.

см. Ту же ссылку на qt выше.

Так что да, это должно быть технически быстрее, но так как вы изменяете размер Widget, тем самым изменяя размер OpenGL Viewport, буферы нижнего уровня получают повторное изготовление каждый раз. Следовательно, замедление гораздо больше. Обратите внимание, что QOpenGLWidget обрабатывает некоторые функции, такие как glViewport(). Это не полезно, когда вы пытаетесь оптимизировать производительность.

Вот несколько предложений

  1. Я считаю, что главная проблема заключается в обработке QImage. Я предлагаю вам настроить собственную сцену OpenGL, просто с одним квадратом, чтобы отобразить текстуру, и попробуйте написать текстуру каждого кадра. Масштабирование будет выполняться на графическом процессоре, поэтому оно будет быстрее.

  2. В качестве альтернативы вы можете использовать glDrawPixels() для рендеринга изображения из памяти хоста (ОЗУ) в буфер кадра. Хотя это не будет обрабатывать масштабирование для вас. обратитесь к https://www.opengl.org/sdk/docs/man2/xhtml/glDrawPixels.xml за дополнительной информацией.

В настоящее время я использую QGLWidget и пользовательскую текстуру OpenGL и набираю вызовы для быстрого обновления (> 60 FPS). Я заметил, что это примерно на 8x - 10x быстрее, чем метод QImage/Qpixmap.Обратите внимание, что размер моей текстуры никогда не превышает 700x700. Также мое изображение всегда хранится на памяти GPU и обновляется с помощью ядра CUDA.

Вы должны обязательно увидеть ускорение, но я не могу гарантировать, что он удовлетворит ваше требование FPS.

Смежные вопросы