Results 1 to 13 of 13

Thread: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

  1. #1
    Join Date
    May 2007
    Posts
    6
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Question Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    Hello everyone,
    First of all, I'm new member on here, so let me say HELLO loudly.

    I try to search previous threads, but wasn't successful to find the solution so, I'm end up here to post my question.

    I'm using QT to developing real time colour recognisation system and it was so far fine, until I got little performance issue here.

    Here, I'm using QMainWindow, QGraphicsView and QGraphicsScene to layout my interface, and I'm having 640*480 colour image from camera interface, then this image converted to QImage for display purpose only.

    I tried convert this QImage to QPixmap and addItem to Scene(so it displays) then delete it when my next frame is arrived, it was working but very slow.
    Like :
    scene->addPixmap(QPixmap::fromImage(capture_frame));

    So, I tried use QImage as Scene's background, it was much faster than previous method but background is displaying in tile mode, and some what slow still.
    scene->setBackgroundBrush(QBrush::QBrush(capture_frame)) ;

    So, now I wonder, is there any better way to display QImage into (or under) QGraphicsScene without adding it as item(because it will only good for every 30ms)

    Also I need to display some indication marks over this QImage, so I don't want this QImage overlap existing contents of QGraphicsScene.

    Hope to read some good ideas from you guys.

    Cheers

    KiwiRider

  2. #2
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    Try overriding QGraphicsView::drawBackground(). It might be faster.

    Using setBackgroundBrush was drawing tiles because it was considered as a pattern.

    Regards

  3. The following user says thank you to marcel for this useful post:

    KiwiRider (10th May 2007)

  4. #3
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    I did this with Qt3, but Qt4 is so different that its not aplicable any more.
    The general rule is that you should try to minimize Qt's conversion functions as much as possible.
    I would try something along the lines of:
    - load the buffer to a QImage
    - Set QBrush as texture with the QImage
    - use QPainter::fillRect() with the texture brush.

    I didn't try this, but I'd expect it to be fast enough.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  5. The following user says thank you to high_flyer for this useful post:

    KiwiRider (10th May 2007)

  6. #4
    Join Date
    May 2007
    Posts
    6
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Question Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    Quote Originally Posted by marcel View Post
    Try overriding QGraphicsView::drawBackground(). It might be faster.

    Using setBackgroundBrush was drawing tiles because it was considered as a pattern.

    Regards
    Hi Marcel,

    Thank you for your reply,

    Is this what you mean?

    Qt Code:
    1. QPainter *painter;
    2. QImage *capture_frame_ptr = &capture_frame;
    3. painter = new QPainter(capture_frame_ptr);
    4. scene->drawBackground(painter,rect());
    To copy to clipboard, switch view to plain text mode 

    I got access violation error because drawBackground() is protected member either view and scene.

    I think I should learn more about c++ before coding with QT, please let me know how to get around this problem.. or am I misunderstanding it completely?
    Last edited by jacek; 10th May 2007 at 02:05. Reason: changed [qtclass] to [code]

  7. #5
    Join Date
    May 2007
    Posts
    6
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Question Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    Quote Originally Posted by high_flyer View Post
    I did this with Qt3, but Qt4 is so different that its not aplicable any more.
    The general rule is that you should try to minimize Qt's conversion functions as much as possible.
    I would try something along the lines of:
    - load the buffer to a QImage
    - Set QBrush as texture with the QImage
    - use QPainter::fillRect() with the texture brush.

    I didn't try this, but I'd expect it to be fast enough.
    Hi, high_flyer,

    Thank you for your reply

    I tried this way,

    Qt Code:
    1. QPainter *painter;
    2. painter = new QPainter();
    3. painter->fillRect(QRect(0,0,width,height),QBrush::QBrush(capture_frame));
    To copy to clipboard, switch view to plain text mode 

    where capture_frame is QImage object,

    there was no error in compile but no result neither.

    Am I doing it right way?
    Last edited by jacek; 10th May 2007 at 02:06. Reason: changed [qtclass] to [code]

  8. #6
    Join Date
    Jun 2008
    Posts
    11
    Thanks
    1
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    Quote Originally Posted by KiwiRider View Post
    Hello everyone,
    First of all, I'm new member on here, so let me say HELLO loudly.

    I try to search previous threads, but wasn't successful to find the solution so, I'm end up here to post my question.

    I'm using QT to developing real time colour recognisation system and it was so far fine, until I got little performance issue here.

    Here, I'm using QMainWindow, QGraphicsView and QGraphicsScene to layout my interface, and I'm having 640*480 colour image from camera interface, then this image converted to QImage for display purpose only.

    I tried convert this QImage to QPixmap and addItem to Scene(so it displays) then delete it when my next frame is arrived, it was working but very slow.
    Like :
    scene->addPixmap(QPixmap::fromImage(capture_frame));

    So, I tried use QImage as Scene's background, it was much faster than previous method but background is displaying in tile mode, and some what slow still.
    scene->setBackgroundBrush(QBrush::QBrush(capture_frame)) ;

    So, now I wonder, is there any better way to display QImage into (or under) QGraphicsScene without adding it as item(because it will only good for every 30ms)

    Also I need to display some indication marks over this QImage, so I don't want this QImage overlap existing contents of QGraphicsScene.

    Hope to read some good ideas from you guys.

    Cheers

    KiwiRider



    Hello KiwiRider...
    first of all... welcome... i'm new in this forum too...

    I'm working on an object tracking system and i think i can help you... I use QImage object to get pixel access (required for tracking algorithm) and then paint the image using QPainter an QPixmap, i use 640x480 images sequence too...

    Here's the way i get good results (speed in show and refresh)...


    In header file declare the pixmap, qimage and things you will need:


    Qt Code:
    1. #ifndef GUI_TRACKING_H
    2. #define GUI_TRACKING_H
    3.  
    4. //here need to include all the classes you need to use
    5.  
    6. class paintManager;
    7. class gui_tracking;
    8.  
    9. class thread : public QThread//neede to create a thread for load images
    10. {
    11. public:
    12. gui_tracking *parent;
    13.  
    14. thread(gui_tracking *p);
    15. virtual void run();
    16. };
    17.  
    18. QPixmap *pixmapImagen;
    19. QImage *imageImagen;
    20. paintManager *painter;
    21. bool needToUpdate;
    22. int imageHeight, imageWidth;
    23.  
    24. thread *myThread;
    25. ...
    26.  
    27. public:
    28.  
    29. void paintEvent(QPaintEvent *);
    30. void customEvent (QCustomEvent *e);
    31. ...
    32. #endif
    To copy to clipboard, switch view to plain text mode 


    In the gui_tracking implementation file the constructor look something like this:

    Qt Code:
    1. imageHeight= 480;
    2. imageWidth = 640;
    3.  
    4. imageImagen = new QImage(imageWidth, imageHeight, 32);
    5.  
    6. pixmapImagen = new QPixmap();
    7.  
    8. painter = new paintManager(pixmapImagen, imageHeight, imageWidth, imageHeight, imageWidth);
    9.  
    10. myThread = new thread(this);
    11.  
    12. needToUpdate = TRUE;
    To copy to clipboard, switch view to plain text mode 


    My paintEvent looks like this:

    Qt Code:
    1. void gui_tracking::paintEvent(QPaintEvent *)
    2. {
    3. QPainter p(frame_Image);
    4. p.drawPixmap(1,1,*pixmapImagen ,0,0,-1,-1);
    5. }
    To copy to clipboard, switch view to plain text mode 


    I use a QThread with a while loop inside that open an image file and show it, so i need to tell "update my pic!!!" to the main thread...I use an event function for that job... this is (needed below)...

    Qt Code:
    1. void gui_tracking::customEvent (QCustomEvent * e)
    2. {
    3. if ( e->type() == QEvent::User )
    4. {
    5. painter->paintImage(imageImagen);
    6. repaint(FALSE);
    7. needToUpdate = TRUE;
    8. }
    9. }
    To copy to clipboard, switch view to plain text mode 


    In the thread's while loop i do:

    void

    Qt Code:
    1. parent->imageImagen->load(parent->fileName);
    2. //filename is changing every loop with the name of the next image of the sequence
    3. ...
    4.  
    5. void thread::run()
    6. {
    7. while(condition)
    8. {
    9. ...
    10. parent->imageImagen->load(parent->fileName);
    11.  
    12. if(parent->needToUpdate)
    13. {
    14. QCustomEvent *evento = new QCustomEvent(QEvent::User);
    15. parent->needToUpdate = FALSE;
    16. QApplication::postEvent(parent, evento);
    17. }
    18. }
    19.  
    20. cout<<"FINISHED"<<endl;
    21.  
    22. }
    To copy to clipboard, switch view to plain text mode 


    For the paintManager class... the header file is something like this:

    Qt Code:
    1. #ifndef PAINTMANAGER_H
    2. #define PAINTMANAGER_H
    3.  
    4. class QPainter;
    5. class QPixmap;
    6. class QPen;
    7.  
    8. class paintManager
    9. {
    10. public:
    11. paintManager(QPixmap *pixmap,int rowsImage,int colsImage,int rowsPixmap,int colsPixmap);
    12.  
    13. ~paintManager();
    14.  
    15. void paintImage( QImage *imagen );
    16.  
    17. private:
    18. int widthImagen;
    19. int HeightImagen;
    20. int widthPixmap;
    21. int heightPixmap;
    22.  
    23. QPixmap *pixmap;
    24. QPainter *pixmapPainter;
    25. QPen *penUsed;
    26. };
    27. #endif
    To copy to clipboard, switch view to plain text mode 

    and the implementation file:

    Qt Code:
    1. #include <qpainter.h>
    2. #include <qpixmap.h>
    3. #include <qpen.h>
    4. #include "paintmanager.h"
    5.  
    6. paintManager(QPixmap *pixmap,int rowsImage,int colsImage,int rowsPixmap,int colsPixmap)
    7. {
    8. pixmap=pixmap;
    9. widthImagen =colsImagen;
    10. heightImagen=rowsImagen;
    11. widthPixmap=colsPixmap;
    12. heightPixmap=rowsPixmap;
    13.  
    14. pixmapPainter= new QPainter();
    15. penUsed=new QPen();
    16.  
    17. pixmap->resize(widthPixmap, HeightPixmap);
    18. pixmap->fill("white");
    19. pixmapPainter->begin(pixmap);
    20. }
    21.  
    22. paintManager::~paintManager()
    23. {
    24. pixmapPainter->end();
    25. delete pixmapPainter;
    26. delete penUsed;
    27. }
    28.  
    29. void paintManager::paintImagen(QImage *imagen)
    30. {
    31. pixmapPainter->drawImage(0,0,*imagen,0,0,-1,-1,0);
    32. }
    To copy to clipboard, switch view to plain text mode 


    And thats all... that works for me... sorry if there is something wrong... (like a spanish name) my original code is in spanish... but this is the basic idea...
    Hope help you... if not... sorry...
    Any question contact me...

    Salu2!!!


    PS: I dont recommend convert QImage to Qpixmap... that's toooooo slow... read the QImage documentation...

  9. #7
    Join Date
    Mar 2011
    Posts
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11

    Default Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    JoseTlaseca,

    First, thank you for the great reply.

    1. How fast are you running this, i.e. how many images are you loading and displaying per second? This will give the rest of us an idea of its performance
    2. Would using a QGraphicsView be faster than the QPixmap? It was recommended to me in the #QT IRC channel.
    3. Do you have to worry about locking with your needToUpdate and imageImagen?
    4. What's the difference between these techniques?
      scene->addPixmap(QPixmap::fromImage(capture_frame));

      pixmapPainter->drawImage(); p.drawPixmap(1,1,*pixmapImagen ,0,0,-1,-1);

      scene = new QGraphicsScene(0, 0, image.width(), image.height());
      view->setScene(scene);
      view->setBackgroundBrush(image);
    Last edited by sr105; 26th March 2011 at 15:32. Reason: wasn't clear who I was talking to.

  10. #8
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    The only reason why your original approach is so slow, is because your are adding a new item to the scene over and over again. If you only update the QGraphicsPixmapItem your performance should be good enough.

    So save a reference to a QGraphicsPixmapItem and call item->setPixmap(yourNewPixmap) when a new image arrives from your camera.

    To prove my statement I wrote a quick and dirty test application, that pre generates a number of pixmaps and shows them over and over again. Skip the details of the ImageSource class. Its just to have something to draw.

    It schedules around 800 updates per second. That should be fast enough for your purpose?

    Qt Code:
    1. main.h
    2.  
    3. #ifndef MAIN_H
    4. #define MAIN_H
    5.  
    6. #include <QtGui>
    7. //#include <QtOpenGL>
    8.  
    9. class ImageSource : QObject
    10. { Q_OBJECT
    11. public:
    12. ImageSource(QString text = "Hello!",int w = 640,int h = 480) : m_width(w),m_height(h)
    13. {
    14. if (text.length() == 0) text = "Hello!";
    15. // Create pixmaps for each character
    16. for (int i=0;i<text.length();++i)
    17. {
    18. QString imageText(text.length(),' ');
    19. imageText[i] = text.at(i);
    20. QPixmap* pm = new QPixmap(w,h);
    21. pm->fill(Qt::white);
    22. QPainter p(pm);
    23. p.setFont(QFont("Courier"));
    24. p.setPen(Qt::black);
    25. p.drawText(QRectF(0,0,w,h),Qt::AlignCenter,imageText);
    26. dummies.append(pm);
    27. }
    28. current = dummies.length();
    29. }
    30. QPixmap* nextImage()
    31. {
    32. --current;
    33. if (current < 0)
    34. current = dummies.length()-1;
    35. //return dummies.at(3);
    36. return dummies.at(current);
    37. }
    38. int width() {return m_width;}
    39. int height() {return m_height;}
    40. private:
    41. QList<QPixmap* > dummies;
    42. int current;
    43. int m_width;
    44. int m_height;
    45. };
    46.  
    47. class MainWindow : public QMainWindow
    48. { Q_OBJECT
    49. public:
    50. MainWindow()
    51. {
    52. scene = new QGraphicsScene(this);
    53.  
    54. imageSrc = new ImageSource();
    55.  
    56. pixmapItem = new QGraphicsPixmapItem();
    57. scene->addItem(pixmapItem);
    58.  
    59. view = new QGraphicsView();
    60. //view->setViewport(new QGLWidget(QGLFormat()));
    61. view->setScene(scene);
    62.  
    63. setCentralWidget(view);
    64.  
    65. QTimer* updateTimer = new QTimer(this);
    66. QObject::connect(updateTimer,SIGNAL(timeout()),this,SLOT(doUpdate()));
    67. updateTimer->start(1);
    68.  
    69. QTimer* fpsTimer = new QTimer(this);
    70. QObject::connect(fpsTimer,SIGNAL(timeout()),this,SLOT(showFPS()));
    71. fpsTimer->start(1000);
    72. }
    73. ~MainWindow() {}
    74. protected slots:
    75. void doUpdate()
    76. {
    77. pixmapItem->setPixmap(*imageSrc->nextImage());
    78. ++frameCounter;
    79. }
    80. void showFPS()
    81. {
    82. setWindowTitle(QString("FPS: %1").arg(frameCounter));
    83. frameCounter = 0;
    84. }
    85.  
    86. private:
    87. ImageSource* imageSrc;
    88. QGraphicsPixmapItem* pixmapItem;
    89. int frameCounter;
    90. };
    91.  
    92. #endif // MAIN_H
    93.  
    94.  
    95. main.cpp:
    96.  
    97. #include <QtCore>
    98. #include <QtGui>
    99.  
    100. #include "main.h"
    101.  
    102. int main(int argc, char *argv[])
    103. {
    104. QApplication a(argc, argv);
    105.  
    106. MainWindow mw;
    107. mw.show();
    108.  
    109. return a.exec();
    110. }
    111.  
    112. pro-file:
    113.  
    114. //QT += opengl
    115. TARGET = FastImages
    116. TEMPLATE = app
    117. SOURCES += main.cpp
    118. HEADERS += \
    119. main.h
    To copy to clipboard, switch view to plain text mode 

  11. #9
    Join Date
    May 2007
    Posts
    6
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    Thank you JohannesMunk,

    It improves alot

    I also found the pixmap set previously deleted from memory gracefully.

    Cheers

  12. #10
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    869
    Thanks
    70
    Thanked 59 Times in 57 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    Hi,

    Of course, you can use the advantage of using OpenGL to display the images that will increase the performance.
    Òscar Llarch i Galán

  13. #11
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    That's right. I've shown how in my minimal example - just uncomment the setViewPort line. In this case it greatly reduces the CPU-load and the FPS goes as high as the timer schedules ~ 1000 FPS. Its a special situation though, as the same pixmaps are drawn all the time. If a texture object needs to be created for every frame the opengl performance could suffer. I've seen situations with big textures where the opengl engine was slower than the raster engine.

    Joh

  14. #12
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    869
    Thanks
    70
    Thanked 59 Times in 57 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    Hi,

    I've been working with a little project that uses two cameras capturing 640x480 images and displaying the images into a openGL widget at 30fps each. Also there was image processing with the captured images. The CPU was arround 14%.
    Òscar Llarch i Galán

  15. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Any fast way(<10ms) to display 640*480 QImage on QGraphicsScene?

    Quote Originally Posted by JohannesMunk View Post
    If a texture object needs to be created for every frame the opengl performance could suffer. I've seen situations with big textures where the opengl engine was slower than the raster engine.
    There are two possible optimizations:
    1. use the raw OpenGL call which updates an existing texture (glUpdateTex... something something) and render the texture in the item
    2. divide one big surface into more smaller ones
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.