CvImage中的陷阱和BUG----CvImage(IplImage* img)陷阱

记录使用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函数,需要完全复制,而不是指向复制



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值