OpenCV學習筆記(5)在單個窗口中顯示多個視頻子窗口


參考OpenCV中文論壇的一個帖子(http://www.opencv.org.cn/forum/viewtopic.php?f=1&t=7996&start=0)實現了在一個窗口顯示多個視頻子窗口,能夠讀入單個的視頻或攝像頭數據,然后在一個窗口中分別顯示原始幀圖像、反色圖像、灰度圖像以及Canny邊緣檢測圖像。並在每個子窗口左上角顯示系統時間,函數cvShowManyImages是改寫的。

2

代碼如下:

#include "stdafx.h"
#include
<cv.h>
#include
<cxcore.h>
#include
<highgui.h>

#include
<stdio.h>
#include
<stdarg.h>
#include
<time.h>

// 隱藏 console 窗口
#pragma comment( linker, "/subsystem:/"windows/" /entry:/"mainCRTStartup/"" )

// 單窗口顯示多幅圖像的函數
void cvShowMultiImages(char* title, int nArgs, ...)
{

// img - Used for getting the arguments
IplImage* img;

// DispImage - the image in which all the input images are to be copied
IplImage* DispImage;

int size; // size - the size of the images in the window
int ind; // ind - the index of the image shown in the window
int x, y; // x,y - the coordinate of top left coner of input images
int w, h; // w,h - the width and height of the image

// r - Maximum number of images in a column
// c - Maximum number of images in a row
int r, c;

// scale - How much we have to resize the image
float scale;
// max - Max value of the width and height of the image
int max;
// space - the spacing between images
int space;

// If the number of arguments is lesser than 0 or greater than 12
// return without displaying
if(nArgs <= 0) {
printf(
"Number of arguments too small..../n");
return;
}
else if(nArgs > 12) {
printf(
"Number of arguments too large..../n");
return;
}
// Determine the size of the image,
// and the number of rows/cols
// from number of arguments
else if (nArgs == 1) {
r
= c = 1;
size
= 300;
}
else if (nArgs == 2) {
r
= 2; c = 1;
size
= 300;
}
else if (nArgs == 3 || nArgs == 4) {
r
= 2; c = 2;
size
= 300;
}
else if (nArgs == 5 || nArgs == 6) {
r
= 3; c = 2;
size
= 200;
}
else if (nArgs == 7 || nArgs == 8) {
r
= 4; c = 2;
size
= 200;
}
else {
r
= 4; c = 3;
size
= 150;
}

// Create a new 3 channel image to show all the input images
DispImage = cvCreateImage( cvSize(60 + size*r, 20 + size*c), IPL_DEPTH_8U, 3 );

// Used to get the arguments passed
va_list args;
va_start(args, nArgs);

// Loop for nArgs number of arguments
space = 20;
for (ind = 0, x = space, y = space; ind < nArgs; ind++, x += (space + size)) {

// Get the Pointer to the IplImage
img = va_arg(args, IplImage*);

// Check whether it is NULL or not
// If it is NULL, release the image, and return
if(img == 0) {
printf(
"Invalid arguments");
cvReleaseImage(
&DispImage);
return;
}

// Find the width and height of the image
w = img->width;
h
= img->height;

// Find whether height or width is greater in order to resize the image
max = (w > h)? w: h;

// Find the scaling factor to resize the image
scale = (float) ( (float) max / size );

// Used to Align the images
// i.e. Align the image to next row
if( ind % r == 0 && x!= space) {
x
= space;
y
+= space + size;
}

// Set the image ROI to display the current image
cvSetImageROI(DispImage, cvRect(x, y, (int)( w/scale ), (int)( h/scale )));

// Resize the input image and copy the it to the Single Big Image
cvResize(img, DispImage);

// Reset the ROI in order to display the next image
cvResetImageROI(DispImage);
}

// Create a new window, and show the Single Big Image
//cvNamedWindow( title, 1 );
cvShowImage( title, DispImage);


// End the number of arguments
va_end(args);

// Release the Image Memory
cvReleaseImage(&DispImage);
}


int main( int argc, char** argv )
{
CvCapture
* capture;

if (argc == 1)
{
capture
= cvCreateCameraCapture( 0 );
}
else
{
capture
= cvCreateFileCapture( argv[1] );
}

IplImage
* frame;

cvNamedWindow(
"video",1);
cvResizeWindow(
"video",750,750);

CvFont timeFont,timeFont1;
cvInitFont(
&timeFont, CV_FONT_HERSHEY_COMPLEX, 1.0f,1.0f,0,1,8);
cvInitFont(
&timeFont1, CV_FONT_HERSHEY_COMPLEX, 1.0f,1.0f,0,1,8);

// Initialize new applied memory of 'time1'
char timestr[25];
memset(timestr,
0, 25 * sizeof(char));

while (1)
{
frame
= cvQueryFrame( capture );
if (!frame) break;

// Get the systme local time info
time_t rawtime;
struct tm* timeinfo;
//time( &rawtime );

rawtime
= time( NULL );
timeinfo
= localtime( &rawtime );
char* p = asctime( timeinfo );

// the 25th character of array 'p' is '/n'
// but it can not be display correctly in the image
// so we just read out the first 24 character of 'p'
for (int i = 0; i < 24; i++)
{
timestr[i]
= *p;
p
++;
}
p
= NULL;

// Bitwise inversion of every element of the current frame
IplImage* frame_not = cvCreateImage(cvGetSize(frame),frame->depth,frame->nChannels);
cvNot(frame,frame_not);

// Get the gray scale image of the current frmae
// and transform the gray image from single channel to three channels
IplImage* frame_gray=cvCreateImage(cvGetSize(frame),frame->depth,1);
IplImage
* frame1=cvCreateImage(cvGetSize(frame),frame->depth,frame->nChannels);
cvCvtColor(frame,frame_gray,CV_RGB2GRAY);
cvCvtColor(frame_gray,frame1,CV_GRAY2BGR);

// Do Canny edge detection
// and transform the result image from single channel to three channels
IplImage* frame_canny=cvCreateImage(cvGetSize(frame),frame->depth,1);
IplImage
* frame2=cvCreateImage(cvGetSize(frame),frame->depth,frame->nChannels);
cvCanny(frame_gray,frame_canny,
20,75,3);
cvCvtColor(frame_canny,frame2,CV_GRAY2BGR);

// Display the local time information in each image
cvPutText( frame, timestr, cvPoint(5,25), &timeFont, CV_RGB(255,0,0) );
cvPutText( frame1, timestr, cvPoint(
5,25), &timeFont, CV_RGB(255,0,0) );
cvPutText( frame2, timestr, cvPoint(
5,25), &timeFont1, CV_RGB(255,0,0) );
cvPutText( frame_not, timestr, cvPoint(
5,25), &timeFont1, CV_RGB(255,0,0) );

cvShowMultiImages(
"video",4,frame,frame_not,frame1,frame2);


//cvWaitKey(33);
int key = cvWaitKey(33);
if( key == 27 ) break;

cvReleaseImage(
&frame_not);
cvReleaseImage(
&frame1);
cvReleaseImage(
&frame_gray);
cvReleaseImage(
&frame2);
cvReleaseImage(
&frame_canny);

}

cvDestroyWindow(
"video");
cvReleaseCapture(
&capture);

return 0;

}

有幾點需要注意:
1、在 while 循環中,處理完的圖像應及時釋放所占用的內存(cvReleaseImage),否則會不斷占用內存空間以致系統當機。
2、圖像數據的指針若是由 cvCreateImage 返回的,則應由 cvReleaseImage 來釋放內存;如果是讀取自視頻或攝像頭的幀圖像,則應用 cvReleaseCapture 來釋放內存,不必再用 cvReleaseImage() ,在 while 循環中使用 cvReleaseImage( &frame )  會導致生成的程序在執行時出錯。
3、有關va_list、va_start、va_arg、va_end的原理與使用,參見 http://www.cppblog.com/qiujian5628/archive/2008/01/21/41562.html


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com