2013年5月31日 星期五

I made a change on VtkImageViewer / QVtkWidget, but nothing happened until I click on it or do other things

Something like this



Solution :

  • Whenever you make changes to VTK's data objects it's your job to call qvtkWidget->update() or viewer->Render() afterward so the new changes get put onto the screen.

The most convenient way is to call the Render( ) method of VtkImageViewer

  • When you change the vtkImageData which is the VtkImageViewer's Input
  • When you need to change the showing slice( most of time is a 3D Data )  
  • Blah, blah
---------> Call Render( )


2013年5月30日 星期四

A class Inherited from QLabel as a OpenCV cv::Mat Image Viewer

This one is a continuation  of Show OpenCV Image on QLabel( QImage )

Why Need This?

  • If you have a cv::Mat Image, and Qt is your Gui Helper, then How About Showing A cv::Mat Image on YOUR Gui?
  • After Showing a cv::Mat Image on your Gui, Why NOT That let User to interact with it?

What We Need.

  • A Be-Ready OpenCV Library
  • A Already-Can-Use QT Environment

What We're Gonna Do.

  • Inheriting A QLabel Class   ----> QcvMatImageLabel
  • Show the cv::Mat Image Pixel Value and Current Curor location on LineEdits
  • Override the Mouse Move, Press, and Release Events

How???

  • Header File of QcvMatLabel
#ifndef QCVMATLABEL_H
#define QCVMATLABEL_H

#include <QtGui>
#include <cv.h>
#include <highgui.h>

class QcvMatImageLabel : public QLabel
{
    Q_OBJECT

public:
 QcvMatImageLabel (QWidget *parent = 0) : QLabel(parent),
  cursorLocLineEdit( NULL ),
  pixelValLineEdit( NULL ),
  matImage( NULL )
 {
  this->setMouseTracking(true);
 }
 virtual ~QImageLabel( ){
  cursorLocLineEdit = NULL;
  pixelValLineEdit = NULL;
  matImage = NULL;
 }
 void setCvImage( cv::Mat _cvImage ){ matImage = _cvImage; }
 void setCursorLineEdit( QLineEdit *theLineEdit ){ cursorLocLineEdit = theLineEdit; }
 void setPixelValLineEdit( QLineEdit *theLineEdit ){ pixelValLineEdit = theLineEdit; }

 int getPosX() const{ return pos_x; }
 int getPosY() const{ return pos_y; }
protected:
 void mouseMoveEvent( QMouseEvent *ev );
 void mousePressEvent( QMouseEvent *ev );
 void mouseReleaseEvent(QMouseEvent *ev);
 static QImage MatToQImage(const cv::Mat& mat);
 
 QLineEdit *cursorLocLineEdit; // show cursor location, i.e. pixel index
 QLineEdit *pixelValLineEdit; // show cv::Mat Image Gray/RGB value
 cv::Mat matImage;  // current cv::Mat image
 int pos_x;   // current cursor position
 int pos_y;   // current cursor position
};
#endif // QCVMATLABEL_H


this->setMouseTracking(true);

  • Source Code of QcvMatLabel
#include "qcvmatimagelabel.h"
void QcvMatImageLabel::mouseMoveEvent( QMouseEvent *ev ){
 int x = ev->pos( ).x();
 int y = ev->pos( ).y();
 pos_x = x; pos_y = y;
 if( cursorLocLineEdit != NULL && cursorLocLineEdit->isEnabled( ) )
  cursorLocLineEdit->setText( QString( "[ %1 , %2 ]" ).arg( x ).arg( y ) );
 
 if( pixelValLineEdit != NULL && pixelValLineEdit->isEnabled( ) &&  !matImage.empty( ) ){
  pixelValLineEdit->setText( QString( "%1" ).arg( matImage.at<uchar>(y,x) ) );
  if( matImage.channels() == 3 )
   pixelValLineEdit->setText( QString( "%1 %2 %3" ).arg( matImage.at<cv::Vec3b>(y,x)[0] )
   .arg( matImage.at<cv::Vec3b>(y,x)[1] )
   .arg( matImage.at<cv::Vec3b>(y,x)[2] ));
 }

}
void QcvMatImageLabel::mousePressEvent( QMouseEvent *ev ){
 int x = ev->pos( ).x();
 int y = ev->pos( ).y();
 
 // m_mousePressed = true;
 
 // Do Whatever You Want...
 // Maybe draw a circle on this location on cv::Mat image
}
void QcvMatImageLabel::mouseReleaseEvent(QMouseEvent *ev){
 // Usually, this shares a member variable "m_mousePressed"
 // with mousePressEvent() method.
 // If User presses on image then the mousePressEvent( )
 // will be called and set m_mousePressed to be true.
 // Then this method can use a "if" condition to check
 // and do things like this...
 
 /*
 if( m_mousePressed == true ){
  // Do Whatever You Want...
  // ...
  
  m_mousePressed = false;
 }
 */
}
QImage QcvMatImageLabel::MatToQImage(const cv::Mat& mat)
{
 // check Show OpenCV Image on QLabel( QImage )
}

  • Using QcvMatLabel
  1. Creating a Widget On Your Gui

    drag a QLabel to your gui


    change the width and height to your cv::Mat image has


    change the background color( not necessary )


    promote QLabel to QcvMatLabel( very important!!! )


    If thing successes, the widget type will look like this
  2. Coding
1
2
3
4
5
6
7
8
// Declare a cv::Mat image
cv::Mat srcMat = cv::imread( "Source.jpg" );

// setting up the member variables of QcvMatImage goes here.
// ...

// show cv::Mat image on QLabel
theQcvMatImageLabel->setPixmap( QPixmap::fromImage( MatToQImage( srcMat ) ) );


More About Mouse Event...

Sometimes, our target may be 3D image data set. Under this case, we can use mouse wheel to change the current slice to show. The most important thing is overriding this method:

protected:
void wheelEvent
QWheelEvent *event );

And the definition may look like this

void QcvMatImageLabel::wheelEvent( QWheelEvent *event ){
 int wheelDegree = event->delta();
 int sliceOffSet = -( wheelDegree / 120 );
 int newSliceNum = current_slice_number + sliceOffSet;
 if( newSliceNum < 0 ) newSliceNum = 0;
 if( newSliceNum > maximum_slice_number ) newSliceNum = maximum_slice_number;
 // Change-showing-slice code goes here...
 // ...
}

wheelDegree is the degree of wheel scrolled on this wheel event
sliceOffSet used as a offset to be added on current slice number



About Key Event


Have Fun!