您的位置:首页 > 运维架构

OpenCV学习笔记(5)在单个窗口中显示多个视频子窗口

2014-07-31 13:19 573 查看
参考OpenCV中文论坛的一个帖子(http://www.opencv.org.cn/forum/viewtopic.php?f=1&t=7996&start=0)实现了在一个窗口显示多个视频子窗口,能够读入单个的视频或摄像头数据,然后在一个窗口中分别显示原始帧图像、反色图像、灰度图像以及Canny边缘检测图像。并在每个子窗口左上角显示系统时间,函数cvShowManyImages是改写的。





代码如下:

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐