You are on page 1of 70

Leow Wee Kheng

CS3249 User Interface Development


Department of Computer Science, SoC, NUS

Images and Video Capture

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

1
1

A picture speaks a thousand words...

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

2
2

Qt Images

Qt provides 4 classes for handling images

QImage
Optimised for I/O, direct pixel access and manipulation.
QPixmap
Optimised for display on screen.
QBitmap
Inherited from QPixmap for black/white images.
QPicture
Paint device that records and replays QPainter commands.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

3
3

QLabel provides an easy way to display an image.

#include <QApplication>
#include <QPixmap>
#include <QLabel>
int main(int argv, char **args)
{
QApplication app(argv, args);
QPixmap pic("butterfly.jpg"); // read image
QLabel label;
label.setPixmap(pic); // put image in label
label.show();
return app.exec();
}

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

4
4

QLabel with an image

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

5
5

Painting QWidget

For finer control, directly paint QWidget.

Create ImageWidget as subclass of QWidget.

Allow user to zoom image with mouse wheel.


Need to override two event handlers:
paintEvent: paints in the widget.
wheelEvent: processes mouse wheel input.

Programming ImageWidget is rather tricky.


Need to write specification to make requirements clear.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

6
6

Specification of ImageWidget

ImageWidget size

Initial size
Default depends on platform and screen geometry.
Set to (800, 600), width = 800, height = 600.
Minimum size is given by minimumSize().
Default is (0, 0), which causes widget to disappear.
Choose (10, 10).
Client class can change it by calling setMinimumSize().
Maximum size is given by maximumSize().
Default is (16777215, 16777215).
Keep this default.
Client class can change it by calling setMaximumSize().

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

7
7

Displayed image size

Displayed image size = zoom input image size, subject to

minimumSize() displayed image size maximumSize()


ImageWidget size always equals displayed image size.

setImage(fileName)

Loads image with file name fileName.


Initial zoom should be as large as possible but 1.0
such that displayed image size initial widget size.
For image initial widget size, initial zoom = 1.0.
For image > initial widget size, initial zoom < 1.0.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

8
8

Zooming

Zoom factor > 0.


Client class can call setZoom(newZoom) to zoom.
User can zoom in or out using mouse wheel.

Each mouse wheel step increases or decreases zoom by0.1.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

9
9

// ImageWidget.h
#ifndef IMAGEWIDGET_H
#define IMAGEWIDGET_H
#include <QWidget>
#include <QImage>
#include <QPixmap>
class ImageWidget: public QWidget
{
Q_OBJECT
Q_PROPERTY(float zoom READ getZoom WRITE setZoom)

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

10
10

Property

Like class variable but has addition features:


Q_PROPERTY(type name
READ getFunction
[WRITE setFunction]
[RESET resetFunction]
[NOTIFY notifySignal]
...
)

type can be any type supported by QVariant.


READ declares accessor function.
WRITE, RESET declare modifier functions (optional).
NOTIFY declares a signal to be emitted (optional).
Qt's property system is platform-independent.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

11
11

public:
ImageWidget(QWidget *parent = 0);
void setImage(const QString &fileName);
float getZoom() const { return zoom; }
void setZoom(float newZoom);

// inline

protected:
void paintEvent(QPaintEvent *event);
void wheelEvent(QWheelEvent *event);
private:
QPixmap input; // Input image.
QPixmap display; // Displayed image.
float zoom;
};
#endif

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

12
12

// ImageWidget.cpp
#include <QtGui>
#include "ImageWidget.h"
ImageWidget::ImageWidget(QWidget *parent): QWidget(parent)
{
// Set defaults
zoom = 0.0;
setMinimumSize(10, 10); // width, height
}

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

13
13

void ImageWidget::setImage(const QString &fileName)


{
QImage image = QImage(fileName); // Get image
input = QPixmap::fromImage(image); // For display
// Determine appropriate initial zoom
float initWidth = 800;
float initHeight = 600;
float wRatio = (float) initWidth /
(float) input.width();
float hRatio = (float) initHeight /
(float) input.height();
float initZoom = qMin(wRatio, hRatio);
if (initZoom >= 1.0)
initZoom = 1.0; // Use original size if possible.
}

setZoom(initZoom);

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

14
14

void ImageWidget::setZoom(float newZoom)


{
if (newZoom <= 0.0)
return; // no change
QSize newSize = newZoom * input.size();
if (newSize.width() < minimumWidth() ||
newSize.height() < minimumHeight() ||
newSize.width() > maximumWidth() ||
newSize.height() > maximumHeight())
return; // no change
zoom = newZoom;
display = input.scaled(zoom * input.size(),
Qt::KeepAspectRatio);
qDebug("zoom %f", zoom); // for debugging
resize(display.size());
}

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

15
15

input.scaled(...)

resize()

Resizes widget, then sends QResizeEvent to widget.


Widget's resizeEvent() is called.

resizeEvent()

Scales input to zoom * input.size().


Always scales from input to get optimal image resolution.
Don't rescale the scaled displayed image.

Widget already has new size.


At the end of the function, sends QPaintEvent to widget.
Widget's paintEvent() is called.

Window system may send additional resize events.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

16
16

// Event handlers
void ImageWidget::paintEvent(QPaintEvent *event)
{
QRectF rect = QRectF(QPoint(), size());
QPainter painter(this);
painter.drawPixmap(rect, display, rect);
}

QRectF(top-left, size) defines a rectangular region.

QPoint() returns (0, 0).

painter(this) creates a QPainter for ImageWidget.

drawPixmap(target, pixmap, source)


draws source part of pixmap into target part of ImageWidget.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

17
17

Caution

Calling resize() in resizeEvent() may cause infinite


recursion.
Calling update() or repaint() in paintEvent() will cause
infinite recursion.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

18
18

void ImageWidget::wheelEvent(QWheelEvent *event)


{
float step = event->delta() / 1200.0;
float newZoom = zoom + step;
char string[100];
sprintf(string, "%.1f", newZoom);
sscanf(string, "%f", &newZoom); // rounding
setZoom(newZoom);
}

delta() returns integer value in units of 1/8 degree.

Most mouse wheels rotate in steps of 15 degree,


i.e., 15 / (1/8) = 120 units.

Divide by 1200.0 to get zoom step of 0.1.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

19
19

// main.cpp
#include <QApplication>
#include "ImageWidget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ImageWidget widget;
// widget.setMinimumSize(50, 50);
// widget.setMaximumSize(1100, 700);

if (argc > 1)
widget.setImage(argv[1]);
widget.show();
return app.exec();

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

20
20

This example is incomplete:

Doesn't display an image smaller than minimum widget size.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

22
22

This example is incomplete:

Changing widget size has no effect on displayed image.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

23
23

Image is larger than screen?


Two ways to handle large images

Use scroll area

Put widget in scroll area.


Easy to implement.

Let user pan image

ImageWidget displays a part of image.


User uses mouse button to pan image.
More challenging to implement.
See UI Challenge in Assignment 2.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

24
24

Using Scroll Area

QScrollArea

Subclass of QWidget.
Provides scrolling view onto another widget.

Put ImageWidget in QScrollArea

No change to ImageWidget.
Scroll bars appear if ImageWidget is too large.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

25
25

// main.cpp
#include <QApplication>
#include <QScrollArea>
#include "ImageWidget.h"

Really easy!
There's usually
an easy way
to do things in Qt!

int main(int argc, char *argv[])


{
QApplication app(argc, argv);
ImageWidget *widget = new ImageWidget;
if (argc > 1)
widget->setImage(argv[1]);
QScrollArea *scroll = new QScrollArea;
scroll->setWidget(widget);

scroll->show();
return app.exec();

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

26
26

Interfacing Devices

Modern computers support many novel devices.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

29
29

3 basic ways to interface devices:

Wait for framework developers to develop device interface.


e.g., QCamera is available in Qt 5.
How long can you wait?
Integrate existing tools.
e.g., OpenCV has camera interface.
Relatively easy to integrate OpenCV into Qt.
Develop device drivers.
Require detailed knowledge.
Very difficult.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

30
30

Interface Webcam with OpenCV

Cross-platform open source library for computer vision.

OpenCV 1 was written in C.


OpenCV 2 provides C, C++, Python, Java interfaces.
Supports Linux, Windows, Mac OS, iOS, Andriod.
Going to support Parallel Javascript.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

31
31

OpenCV 2 example for video capture with webcam.

// webcam.c
#include <core_c.h>
#include <highgui_c.h>
int main(int argc, char **args)
{
int dev = 0; // 0: default, > 0: other cameras.
cvNamedWindow("webcam", 1); // Create OpenCV window.
CvCapture* capture = cvCaptureFromCAM(dev);
cvSetCaptureProperty(capture,
CV_CAP_PROP_FRAME_WIDTH, 640);
cvSetCaptureProperty(capture,
CV_CAP_PROP_FRAME_HEIGHT, 480);

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

32
32

while(1)
{
IplImage *frame = cvQueryFrame(capture);
cvShowImage("webcam", frame);
char key = cvWaitKey(10);
if (key == 27) // If key is ESC,
break;
// break out of loop.
}

cvReleaseCapture(&capture);
cvDestroyWindow("webcam");
return 0;

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

33
33

Integrating OpenCV in Qt

OpenCV video capture program is sequential.

Qt is event-driven.

To integrate OpenCV in Qt:

Use Qt timer event to generate regularly timed events.


Call OpenCV function upon receiving timer event.
Convert OpenCV image to QImage for display.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

35
35

Integrate OpenCV video capture functions in Qt.

Native
screen
interface

display
output

Webcam
(QWidget)

QTimer
OpenCV
video capture
functions

init
get frame

OpenCV
interface

timer
event

frame

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

36
36

// Webcam.h
#ifndef WEBCAM_H
#define WEBCAM_H
#include
#include
#include
#include

<QWidget>
<QTime>
<core_c.h>
<highgui_c.h>

class Webcam: public QWidget


{
Q_OBJECT
public:
Webcam(int dev, int fps);
~Webcam();

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

37
37

protected:
void showEvent(QShowEvent *event);
void hideEvent(QHideEvent *event);
void timerEvent(QTimerEvent *event);
void paintEvent(QPaintEvent *event);
private:
CvCapture* capture;
int timerId;
int frameRate; // input frame rate
QPixmap pixmap;
int nframes;
// used to calculate actual frame rate
QTime time;
// used to calculate actual frame rate

};

// convert image format


QImage IplImage2QImage(const IplImage *iplImage);

#endif

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

38
38

// Webcam.cpp
#include <QtGui>
#include "Webcam.h"
Webcam::Webcam(int dev, int fps)
{
timerId = 0;
frameRate = fps;
capture = cvCaptureFromCAM(dev);

int width = 640;


int height = 480;
cvSetCaptureProperty(capture,
CV_CAP_PROP_FRAME_WIDTH, width);
cvSetCaptureProperty(capture,
CV_CAP_PROP_FRAME_HEIGHT, height);
setFixedSize(width, height);

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

39
39

Webcam::~Webcam()
{
cvReleaseCapture(&capture);
}
void Webcam::showEvent(QShowEvent *event)
{
nframes = 0; // init
timerId = startTimer(1000 / frameRate);
time.start(); // start time
}

// in msec

void Webcam::hideEvent(QHideEvent *event)


{
killTimer(timerId);
}

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

40
40

void Webcam::timerEvent(QTimerEvent *event)


{
if (event->timerId() == timerId)
{
IplImage *frame = cvQueryFrame(capture);
QImage image = IplImage2QImage(frame); // convert
pixmap = QPixmap::fromImage(image);
// convert
repaint(); // immediate repaint
if (++nframes == 50)
{
qDebug("frame rate: %f", // actual frame rate
(float) nframes * 1000 / time.elapsed());
nframes = 0;
time.restart();
}

}
else
}

QWidget::timerEvent(event);

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

41
41

void Webcam::paintEvent(QPaintEvent *event)


{
QRectF rect = QRectF(QPoint(), size());
QPainter painter(this);
painter.drawPixmap(rect, pixmap, rect);
}

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

42
42

// Convert OpenCV's IplImage to QImage.


QImage Webcam::IplImage2QImage(const IplImage *iplImage)
{
int height = iplImage->height;
int width = iplImage->width;
if(iplImage->depth == IPL_DEPTH_8U &&
iplImage->nChannels == 3) // colour image
{
const uchar *qImageBuffer =
(const uchar*) iplImage->imageData;
QImage img(qImageBuffer, width, height,
QImage::Format_RGB888);
return img.rgbSwapped();
}

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

43
43

else if(iplImage->depth == IPL_DEPTH_8U &&


iplImage->nChannels == 1) // gray image
{
const uchar *qImageBuffer =
(const uchar*) iplImage->imageData;
QImage img(qImageBuffer, width, height,
QImage::Format_Indexed8);
QVector<QRgb> colorTable; // set up colour table
for (int i = 0; i < 256; i++)
colorTable.append(qRgb(i, i, i));
img.setColorTable(colorTable);
return img;

}
else
{
qWarning() << "Image cannot be converted.";
return QImage();
}

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

44
44

// main.cpp
#include <QApplication>
#include "Webcam.h"
#include "stdio.h"
int main(int argc, char **args)
{
QApplication app(argc, args);
int dev = 0; // default device
int fps = 25; // 25 frames per second
if (argc > 1)
sscanf(args[1], "%d", &dev);
if (argc > 2)
sscanf(args[2], "%d", &fps);

Webcam *view = new Webcam(dev, fps);


view->show();
return app.exec();

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

45
45

#
#
#
#

webcam.pro
Run qmake -project to generate file.
Then, add the include line.
Then, run qmake followed by make.

TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
# include additional compiler info for OpenCV
include(opencv.pro)
# Input
HEADERS += Webcam.h
SOURCES += main.cpp Webcam.cpp

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

46
46

# opencv.pro
QMAKE_CXXFLAGS += -Wno-deprecated
INCLUDEPATH += /usr/include/opencv2/core
/usr/include/opencv2/highgui
LIBS += -L/usr/lib -lopencv_core -lopencv_imgproc
-lopencv_highgui

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

47
47

Notes on video capture

Most cameras have a max frame rate, e.g., 30 fps.


When desired frame rate > max frame rate,
program can only run at max frame rate.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

48
48

Real-Time Video Processing


Image
Processor

Native
screen
interface

display
output

Webcam
(QWidget)

processed
image

QTimer
OpenCV
video capture
functions

init
get frame

OpenCV
interface

timer
event

frame
CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

49
49

// ImageProc.h
#ifndef IMAGEPROC_H
#define IMAGEPROC_H
#include <core_c.h>
#include <highgui_c.h>
class ImageProc
{
public:
IplImage *process(IplImage *source, int type);
};
#endif

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

50
50

// ImageProc.cpp
#include "ImageProc.h"
#include <imgproc_c.h>
IplImage *ImageProc::process(IplImage *source, int type)
{
static IplImage *target = NULL;
if (target)
cvReleaseImage(&target);
target = cvCreateImage(
cvSize(source->width, source->height),
source->depth, source->nChannels);

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

51
51

switch(type)
{
case 0: // do nothing
return source;
case 1: // demo fast algo: fast smoothing
cvSmooth(source, target, CV_GAUSSIAN, 5);
return target;

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

52
52

case 2: // demo slow algo: filter with large kernel


{
int size = 100;
CvMat *kernel = cvCreateMat(size, size,
CV_32FC1);
cvSet(kernel, cvScalar(1.0 / size / size));
cvFilter2D(source, target, kernel);
cvReleaseMat(&kernel);

// Filter target is too blurred for display.


// Display the following for demo purpose.
cvSmooth(source, target, CV_GAUSSIAN, 5);
return target;

default: // do nothing
return source;
}

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

53
53

// Webcam.h
class Webcam: public QWidget
{
Q_OBJECT
public:
Webcam(int dev, int fps, int type);
~Webcam();
...
protected:
...
void timerEvent(QTimerEvent *event);
private:
...
ImageProc *imageProc;
int demoType;
};
CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

54
54

// Webcam.cpp
Webcam::Webcam(int dev, int fps, int type)
{
timerId = 0;
frameRate = fps;
demoType = type;
capture = cvCaptureFromCAM(dev);
int width = 640;
int height = 480;
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH,
width);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT,
height);
setFixedSize(width, height);
}

imageProc = new ImageProc;

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

55
55

// Webcam.cpp
Webcam::~Webcam()
{
cvReleaseCapture(&capture);
delete imageProc;
}

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

56
56

void Webcam::timerEvent(QTimerEvent *event)


{
if (event->timerId() == timerId)
{
IplImage *frame = cvQueryFrame(capture);
IplImage *target =
imageProc->process(frame, demoType);
QImage image = IplImage2QImage(target);
pixmap = QPixmap::fromImage(image);
repaint();
...
}

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

57
57

Response Time

Let desired frame rate = 25 fps.

Frame interval = 1 / 25 sec = 40 msec.

Timer event

Video capture

ck : time at which timer event arrives.


fk : time at which video frame k is captured.

Frame processing

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

dk : time at which frame k is displayed after processing.

Images and Video Capture


Images and Video Capture

58
58

Response time

Frame capture time = fk ck.

Frame processing time = dk fk .

Response time rk = dk ck.

Want rk .

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

59
59

Fast processing

Response time r <

Actual frame rate = desired frame rate.

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

60
60

Slower processing

Response time r 2.
Actual frame rate 1/2 desired frame rate.
Slower rate but still responsive.

Question:

Timer events can fire at desired frame rate.


What happen to missing timer events (dotted arrows)?

CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

61
61

General Software Architecture

Better to split input and output modules.


output
Native
screen
interface

display
output

Webcam
(QWidget)

QTimer
OpenCV
video capture
functions

init
get frame

OpenCV
interface

timer
event

frame
input
CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

63
63

Native
screen
interface

Main
Window

display
output

QTimer
generic
camera
functions

init

init

OpenCV
video capture
functions

init
get frame

get
frame

processed
image

Image
Processor
timer
event
frame

Webcam
(camera
interface)

frame
CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

64
64

Main
Window

display
output

QTimer
generic
camera
functions

init
simplified
diagram
init

OpenCV
video capture
functions

init
get frame

get
frame

processed
image

Image
Processor
timer
event
frame

Webcam
(camera
interface)

frame
CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

65
65

Main
Window

display
output

generic
camera
functions

Which pattern
is this?
init

OpenCV
video capture
functions

init
get frame

get
frame

processed
image

Image
Processor

frame

Webcam
(camera
interface)

frame
CS3249 (SoC, NUS)

CS3249 (SoC,
NUS) (SoC, NUS)
CS3249

Images and Video Capture


Images and Video Capture

66
66

Summary

Working with images

Use QImage for input/output.


Use QPixmap for painting on QWidget.
Reimplement event handlers
paintEvent(), wheelEvent(), etc.
Write specification to clarity requirements.

Integrating devices

Use existing tools with hardware interfaces.


Integrate tools into Qt.
Need to convert data to/from Qt format.
Check response time.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

67
67

Further Reading

2D and 3D graphics: [Blan2008], Chap. 8.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

68
68

Exercise

Modify the sample codes into 3 loosely coupled parts:

Main window: displays video frame and interacts with user.


Webcam: captures video frame.
ImageProc: processes images.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

69
69

References

J. Blanchette and M. Summerfield, C++ GUI Programming with


Qt 4, 2nd ed., Prentice Hall, 2008.

OpenCV Reference Manual.

CS3249 (SoC, NUS)

CS3249 (SoC, NUS)

Images and Video Capture


Images and Video Capture

70
70

You might also like