【转】OpenCV里IplImage数据结构极易出错的问题,IplImage和单字节char*的相互转换
http://blog.csdn.net/liuyi1985/article/details/2174328
http://blog.csdn.net/liuyi1985/article/details/2195364
?對(duì)OpenCV稍有了解的同學(xué)都知道里邊用于存儲(chǔ)圖像數(shù)據(jù)的IplImage,其中有兩個(gè)屬性非常值得關(guān)注,稍不留神就會(huì)導(dǎo)致錯(cuò)誤(后附錯(cuò)例一則):一是width屬性;二是widthStep屬性。前者是表示圖像的每行像素?cái)?shù),后者指表示存儲(chǔ)一行像素需要的字節(jié)數(shù)。
????? 在OpenCV里邊,widthStep必須是4的倍數(shù),從而實(shí)現(xiàn)字節(jié)對(duì)齊,有利于提高運(yùn)算速度。如果8U單通道圖像寬度為3,那么widthStep是4,加一個(gè)字節(jié)補(bǔ)齊。這個(gè)圖像的一行需要4個(gè)字節(jié),只使用前3個(gè),最后一個(gè)空著。也就是一個(gè)寬3高3的圖像的imageData數(shù)據(jù)大小為4*3=12字節(jié)。
????? 需要注意的是,空著的那個(gè)像素并不是無效的,它仍然可以被操作,這就是導(dǎo)致錯(cuò)誤的根源。
????? 錯(cuò)例:
????? 假如現(xiàn)在有一個(gè)char* data的指針指向一個(gè)15*15的灰度圖像的數(shù)據(jù)起始地址,我們想把圖像數(shù)據(jù)通過cvShowImage函數(shù)顯示出來,比較直觀的一種做法如下:
......IplImage*?image?=?cvCreateImage(cvSize(15,?15),?8,?1);
memcpy(image->imageData,?data,?15*15);
cvNamedWindow("window");
cvShowImage("window",?image);
cvWaitKey();
cvReleaseImage(&image);
cvDestroyWindow("window");
......
????? 你會(huì)發(fā)現(xiàn),顯示的圖像奇怪的往左下角歪過去了。當(dāng)你看完這篇文章后希望不要再因?yàn)檫@個(gè)問題浪費(fèi)你的時(shí)間了(shamed:這個(gè)問題郁悶了我整整一天)。其實(shí)原因就在于,在cvCreateImage的時(shí)候,OpenCV為實(shí)現(xiàn)字節(jié)對(duì)齊,使得每行數(shù)據(jù)實(shí)際有16個(gè)字節(jié)(多出一個(gè)),在使用memcpy的過程中,這些多出的字節(jié)就把對(duì)應(yīng)的數(shù)據(jù)給“吃”了,因?yàn)檫@些數(shù)據(jù)在cvShowImage的時(shí)候并不會(huì)顯示出來,這樣,第二行就少一個(gè)字節(jié),第三行少兩個(gè)字節(jié),……,所以整個(gè)圖像就偏向左下角了!
????? 知道這一點(diǎn)后可以將memcpy語句更改如下:
for(int?i?=?0;?i<15;?i++)...{????memcpy(image->imageData?+?image->widthStep*i,?data + 15*i,?15);
}
????? 這樣,程序才能按我們的設(shè)想運(yùn)行。
OpenCV中IplImage和單字節(jié)char*的相互轉(zhuǎn)換
?IplImage和單字節(jié)char*之間相互轉(zhuǎn)換的正確、簡(jiǎn)潔的方法:
????? 已知 IplImage* image 和 char* data
????? 從 IplImage 到 char* :
data?=?image->imageData?//對(duì)齊的圖像數(shù)據(jù)????? 或者
data?=?image->imageDataOrigin?//未對(duì)齊的原始圖像數(shù)據(jù)????? 從 char* 到 IplImage :
image?=?cvCreateImageHeader(cvSize(width,height),?depth,?channels);cvSetData(image,?data,?step);
????? step指定IplImage圖像每行占的字節(jié)數(shù)。需要注意是,在釋放空間時(shí)不能直接使用cvReleaseImage,而需cvReleaseImageHeader,然后再delete data,這也是OpenCV里邊“自己管理內(nèi)存”的思想。
????? 附《Intel image processing library》文檔中關(guān)IplImage的聲明(非OpenCV版):
typedef?struct?_IplImage?...{????int?nSize?/**//*?size?of?iplImage?struct?*/
????int?ID?/**//*?image?header?version?*/
????int?nChannels;
????int?alphaChannel;
????int?depth;?/**//*?pixel?depth?in?bits?*/
????char?colorModel[4];
????char?channelSeq[4];
????int?dataOrder;
????int?origin;
????int?align;?/**//*?4-?or?8-byte?align?*/
????int?width;
????int?height;
????struct?_IplROI?*roi;?/**//*?pointer?to?ROI?if?any?*/
????struct?_IplImage?*maskROI;?/**//*pointer?to?mask?ROI?if?any?*/
????void?*imageId;?/**//*?use?of?the?application?*/
????struct?_IplTileInfo?*tileInfo;?/**//*?contains?information?on?tiling?*/
????int?imageSize;?/**//*?useful?size?in?bytes?*/
????char?*imageData;?/**//*?pointer?to?aligned?image?*/
????int?widthStep;?/**//*?size?of?aligned?line?in?bytes?*/
????int?BorderMode[4];?/**//*?the?top,?bottom,?left,?and?right?border?mode?*/
????int?BorderConst[4];?/**//*?constants?for?the?top,?bottom,?left,?and?right?border?*/
????char?*imageDataOrigin;?/**//*?ptr?to?full,?nonaligned?image?*/
}?IplImage; 分享到:
轉(zhuǎn)載于:https://www.cnblogs.com/justiner/archive/2011/12/07/2278829.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的【转】OpenCV里IplImage数据结构极易出错的问题,IplImage和单字节char*的相互转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HttpWebRequest WebRe
- 下一篇: windows phone7---MVV