实现了在一个窗口显示多个视频子窗口,能够读入单个的视频或摄像头数据,然后在一个窗口中分别显示原始帧图像、反色图像、灰度图像以及Canny边缘检测图像。并在每个子窗口左上角显示系统时间,函数cvShowManyImages是改写的。
代码如下:
#include "stdafx.h" #include#include #include #include #include #include // 隐藏 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 ) //见博文
有几点需要注意:
1、在 while 循环中,处理完的图像应及时释放所占用的内存(cvReleaseImage),否则会不断占用内存空间以致系统当机。
2、图像数据的指针若是由 cvCreateImage 返回的,则应由 cvReleaseImage 来释放内存;如果是读取自视频或摄像头的帧图像,则应用 cvReleaseCapture 来释放内存,不必再用 cvReleaseImage() ,在 while 循环中使用 cvReleaseImage( &frame ) 会导致生成的程序在执行时出错。
3,有关va_list、va_start、va_arg、va_end有详述见博客相关博文