使用OpenCV在同一窗口中显示多个图像

我有三个火线相机可以通过硬件自动同步,我正在尝试捕获帧,将它们保存到我的硬盘中并在窗口中显示它们。

一切正常,但此刻, 我只能同时在三个不同的窗口中显示帧

我想在一个窗口中显示帧,但我不知道如何做到这一点。 在这个链接有cvShowManyImages()函数但你必须同时传递三个帧,但我有一个for()循环,它可以一次考虑一个帧。

这是我正在使用的代码:

for ( int j = 0; j < k_numImages; j++ ) { // Display the timestamps for all cameras to show that the image // capture is synchronized for each image for ( unsigned int i = 0; i RetrieveBuffer( &image ); if (error != PGRERROR_OK) { PrintError( error ); return -1; } IplImage* destImage = ConvertImageToOpenCV(&image); char titolo[50]; sprintf(titolo, "titolo%d", i); cvShowImage(titolo, destImage); waitKey(1); } } 

它运行良好但为每个摄像机创建不同的窗口,而我想在同一窗口中显示所有摄像机帧

你能帮我吗?

编辑:这是ConvertImageToOpenCV()函数。

 IplImage* ConvertImageToOpenCV(Image* pImage) { IplImage* cvImage = NULL; bool bColor = true; CvSize mySize; mySize.height = pImage->GetRows(); mySize.width = pImage->GetCols(); switch ( pImage->GetPixelFormat() ) { case PIXEL_FORMAT_MONO8: cvImage = cvCreateImageHeader(mySize, 8, 1 ); cvImage->depth = IPL_DEPTH_8U; cvImage->nChannels = 1; bColor = false; break; case PIXEL_FORMAT_411YUV8: cvImage = cvCreateImageHeader(mySize, 8, 3 ); cvImage->depth = IPL_DEPTH_8U; cvImage->nChannels = 3; break; case PIXEL_FORMAT_422YUV8: cvImage = cvCreateImageHeader(mySize, 8, 3 ); cvImage->depth = IPL_DEPTH_8U; cvImage->nChannels = 3; break; case PIXEL_FORMAT_444YUV8: cvImage = cvCreateImageHeader(mySize, 8, 3 ); cvImage->depth = IPL_DEPTH_8U; cvImage->nChannels = 3; break; case PIXEL_FORMAT_RGB8: cvImage = cvCreateImageHeader(mySize, 8, 3 ); cvImage->depth = IPL_DEPTH_8U; cvImage->nChannels = 3; break; case PIXEL_FORMAT_MONO16: cvImage = cvCreateImageHeader(mySize, 16, 1 ); cvImage->depth = IPL_DEPTH_16U; cvImage->nChannels = 1; bColor = false; break; case PIXEL_FORMAT_RGB16: cvImage = cvCreateImageHeader(mySize, 16, 3 ); cvImage->depth = IPL_DEPTH_16U; cvImage->nChannels = 3; break; case PIXEL_FORMAT_S_MONO16: cvImage = cvCreateImageHeader(mySize, 16, 1 ); cvImage->depth = IPL_DEPTH_16U; cvImage->nChannels = 1; bColor = false; break; case PIXEL_FORMAT_S_RGB16: cvImage = cvCreateImageHeader(mySize, 16, 3 ); cvImage->depth = IPL_DEPTH_16U; cvImage->nChannels = 3; break; case PIXEL_FORMAT_RAW8: cvImage = cvCreateImageHeader(mySize, 8, 3 ); cvImage->depth = IPL_DEPTH_8U; cvImage->nChannels = 3; break; case PIXEL_FORMAT_RAW16: cvImage = cvCreateImageHeader(mySize, 8, 3 ); cvImage->depth = IPL_DEPTH_8U; cvImage->nChannels = 3; break; case PIXEL_FORMAT_MONO12: printf("Not supported by OpenCV"); bColor = false; break; case PIXEL_FORMAT_RAW12: printf("Not supported by OpenCV"); break; case PIXEL_FORMAT_BGR: cvImage = cvCreateImageHeader(mySize, 8, 3 ); cvImage->depth = IPL_DEPTH_8U; cvImage->nChannels = 3; break; case PIXEL_FORMAT_BGRU: cvImage = cvCreateImageHeader(mySize, 8, 4 ); cvImage->depth = IPL_DEPTH_8U; cvImage->nChannels = 4; break; case PIXEL_FORMAT_RGBU: cvImage = cvCreateImageHeader(mySize, 8, 4 ); cvImage->depth = IPL_DEPTH_8U; cvImage->nChannels = 4; break; default: printf("Some error occured...\n"); return NULL; } if(bColor) { if(!bInitialized) { colorImage.SetData(new unsigned char[pImage->GetCols() * pImage->GetRows()*3], pImage->GetCols() * pImage->GetRows()*3); bInitialized = true; } pImage->Convert(PIXEL_FORMAT_BGR, &colorImage); //needs to be as BGR to be saved cvImage->width = colorImage.GetCols(); cvImage->height = colorImage.GetRows(); cvImage->widthStep = colorImage.GetStride(); cvImage->origin = 0; //interleaved color channels cvImage->imageDataOrigin = (char*)colorImage.GetData(); //DataOrigin and Data same pointer, no ROI cvImage->imageData = (char*)(colorImage.GetData()); cvImage->widthStep = colorImage.GetStride(); cvImage->nSize = sizeof (IplImage); cvImage->imageSize = cvImage->height * cvImage->widthStep; } else { cvImage->imageDataOrigin = (char*)(pImage->GetData()); cvImage->imageData = (char*)(pImage->GetData()); cvImage->widthStep = pImage->GetStride(); cvImage->nSize = sizeof (IplImage); cvImage->imageSize = cvImage->height * cvImage->widthStep; //at this point cvImage contains a valid IplImage } return cvImage; } 

在此处输入图像描述

由于显而易见的原因,我无法测试下面的代码,但它说明了一种方法:

 for ( int j = 0; j < k_numImages; j++ ) { // Display the timestamps for all cameras to show that the image // capture is synchronized for each image IplImage* destImage[3]; // A-ha moment for ( unsigned int i = 0; i < numCameras; i++ ) { Image image; error = ppCameras[i]->RetrieveBuffer( &image ); if (error != PGRERROR_OK) { PrintError( error ); return -1; } /* Since ConvertImageToOpenCV() doesn't copy the image data, * we need to do that ourselves, because when this loop is done Image * is destroyed and the data is lost. */ IplImage* tmp = ConvertImageToOpenCV(&image); destImage[i] = cvCreateImage(cvGetSize(tmp), tmp->depth, tmp->nChannels); cvCopy(tmp, destImage[i], NULL); char titolo[50]; sprintf(titolo, "titolo%d", i); } cvShowManyImages("all", 3, destImage[0], destImage[1], destImage[2]); waitKey(0); // when you finish using them, release the allocated resources to prevent memory leaks cvReleaseImage(&destImage[0]); cvReleaseImage(&destImage[1]); cvReleaseImage(&destImage[2]); } 

我们的想法是创建一个IplImage*数组来存储摄像机检索到的图像,因此在循环之后,您可以访问所有这3个图像,并能够在单个窗口中显示它们。

编辑:

总结私人聊天,问题是cvShowManyImages()采用彩色(3通道)图像,他的相机返回灰度(单通道)图像。 解决方案只是改变cvShowManyImages()的实现,来自:

 DispImage = cvCreateImage( cvSize(100 + size*w, 60 + size*h), 8, 3 ); 

至:

 DispImage = cvCreateImage( cvSize(100 + size*w, 60 + size*h), 8, 1 );