记录使用IplImage* 定义图像,转换摄像头时,出现的错误
//源程序代码---转换图片格式
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;
}
//call via: IplImage* myCVImage = SaveImageWithOpenCV(&rawImage);
//调用转换图片函数 ConvertImageToOpenCV
Mat img = Mat (ConvertImageToOpenCV(&image));
Mat img_to_show;
resize(img, img_to_show, Size(640, 480));
if(!img.data) //判断图片调入是否成功
return -1; //调入图片失败则退出
string windowname;
if (i == 0)
windowname = "Right";
else
windowname = "Left";
namedWindow(windowname, CV_WINDOW_AUTOSIZE); //创建窗口,并确定其为大小不可变类型窗口
imshow(windowname, img_to_show);//显示图片。如果你不介意窗口大小可变,可以直接注释掉上一句。因为imshow可以直接创建窗口
对于CvImage(IplImage* img)的陷阱
假设有下面一个段代码:
IplImage *pIplImg = cvLoadImage("load.tiff");
{
CvImage cvImg(pIplImg);
}
cvSaveImage("save.tiff", pIplImg);
虽然逻辑上好像没有错误,但再执行到cvSaveImage语句的时候却会产生异常!跟踪调试后发现, 原来pIplImg对应的数据在cvImg析构的时候被释放了!
仔细分析后会发现,CvImage将pIplImg对应的数据和它本身的refcount绑定到一起了。pIplImg 对应的数据虽然不属于CvImage,但是它却依据refcount对其进行管理,直到(*refcount)变为0 的时候私自释放了pIplImg影像。
所以对于IpiImage* 的使用方式并且想要保存图像
for ( unsigned int i = 0; i < numCameras; i++ )
{
//a temporary image space to store the camera image
error = ppCameras[i]->RetrieveBuffer( &image );
if (error != PGRERROR_OK)
{
PrintError( error );
throw runtime_error(string("can't retrueve image"));
}
temp = ConvertImageToOpenCV(&image);
if (i == 0)
{
temp.copyTo(frames);
printf("first get picure into frames \n");
if(!frames.data)
throw runtime_error(string("can't change PGR into OpenCV image format"));
}
else
{
temp.copyTo(framel);
printf("first get picure into framel \n");
if(!framel.data)
throw runtime_error(string("can't change PGR into OpenCV image format"));
}
#ifdef SAVE
char filename[512];
sprintf( filename, "PGRCamera-%d.jpg", i );
error = image.Save( filename );
if (error != PGRERROR_OK)
{
PrintError( error );
}
printf( "Grabbed image for camera-%d\n", i );
#endif
}
是每次得到的返回图像都迅速保存到新的Mat类图像中,不会被引用计数的销毁而被遗弃销毁。并且需要copy函数,需要完全复制,而不是指向复制