Emgu的Image(Of Gray,Byte)轉OpenCV的IplImage

最近在做VB.Net和C++進程間用內存映射文件通信的項目。

VB.NET和C++之間的通信就需要傳送統一的文件格式,讓VB和C++都能解析。

就會遇到這樣地問題:VB.NET中Emgu的Image(Of Gray,Byte)怎麼才能轉爲C++中OpenCV的IplImage格式呢?


進程間通信,我用的是內存映射文件的方式,在本文中就不多做討論了。主要討論兩種格式之間的轉換。

首先VB端創建內存映射文件,把Image(Of Gray,Byte).MIplImage.imageDataOrigin指針指向的內存寫入內存映射文件中

因爲本文的研究對象都是灰度圖,所以MIplImage.imageDataOrigin中存放的都是0-255的灰度值。方向是以左上角爲起點,橫向掃描。

'imgbytes是Byte()類型的圖片文件
Dim img As Image(Of Gray, Byte) = New Image(Of Gray, Byte)(Image.FromStream(New MemoryStream(imgbytes)))
'圖片的寬度需是4字節的倍數
Dim mmfImgSize As Integer = Int((img.Width + 3) / 4) * 4 * img.Height
Dim mmfPaper As MemoryMappedFile = MemoryMappedFile.CreateNew("test1", mmfImgSize)
Using Stream As MemoryMappedViewStream = mmfPaper.CreateViewStream()
	'把需要通信的圖片寫入內存映射文件中。寬高通過C++可執行文件的參數傳遞
	Dim writer As BinaryWriter = New BinaryWriter(Stream)
	Dim byteSize As Integer = Int((img.Width + 3) / 4) * 4 * img.Height
	Dim imageDataByte(byteSize - 1) As Byte
	'讀取指針中的內容
	Marshal.Copy(img.MIplImage.imageDataOrigin, imageDataByte, 0, byteSize)
	writer.Write(imageDataByte)
End Using
這一部分包含了圖片中每個像素點的灰度值。但是並不包含圖像的頭文件。C++端想新建IplImage的話,還需知道圖片的寬高以及通道數。

因爲是灰度圖,所以通道數我們默認設爲1.圖片的寬和高,我用的是調用C++命令行可執行文件的參數的形式傳遞的。

以下是C++端的代碼:

char *mmfName是內存映射文件的文件名

char *imgWidth是圖片的寬度

char *imgHeight是圖片的高

int mmfImgSize = (atoi(imgWidth) + 3)/4 * 4 *atoi(imgHeight);
bmpWidth = atoi(imgWidth);
bmpHeight = atoi(imgHeight);
//需要將char轉爲LPCWSTR
WCHAR wszClassName[100] = {0};		
memset(wszClassName,0,sizeof(wszClassName));  
MultiByteToWideChar(CP_ACP,0,mmfName,strlen(mmfName)+1,wszClassName,sizeof(wszClassName)/sizeof(wszClassName[0]));  

//打開共享的文件對象。 
HANDLE m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, wszClassName); 
//獲得映射視圖
char* mmfm_base_address = (char*)MapViewOfFile(m_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, mmfImgSize);
DWORD error_code;
if(mmfm_base_address == NULL){
	/*error_code = GetLastError();
	if(error_code != SUCCESS){
		cout<<"error code "<<error_code<<endl;
	}*/
	return false;
}else{
	IplImage  *srcBitmap = cvCreateImageHeader(cvSize(bmpWidth,bmpHeight),IPL_DEPTH_8U,1);
	cvSetData(srcBitmap,mmfm_base_address,(bmpWidth + 3)/4*4);	//第3個參數是行字節數
	return true;
}


以上就完成了Emgu的Image(Of Gray,Byte)轉OpenCV的IplImage。

但是還需注意,如果圖片是由cvCreateImage初始化的,那麼用cvReleaseImage來釋放;

如果圖片是由cvCreateImageHeader初始化的文件頭,那麼用cvReleaseImageheader(&iplImage)來釋放。


初始化後的imageDataOrigin和imageData指向的是同一個地址。

openCV論壇上的大神解釋的是:“預留數據接口吧!上面有這麼一句話:IplImage結構來自於Intel Image Processing Libray(是其本身所具有的)。OpenCV只支持期中的一個子集。”


部分內容參考了這位同學的博客~:http://blog.chinaunix.net/uid-22682903-id-1771421.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章