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

来源:互联网 发布:渠道网络可靠吗 编辑:程序博客网 时间:2024/05/17 08:13

记录使用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 channelscvImage->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";elsewindowname = "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 imageerror = 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 SAVEchar 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函数,需要完全复制,而不是指向复制



原创粉丝点击