日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】OpenCV里IplImage数据结构极易出错的问题,IplImage和单字节char*的相互转换

發(fā)布時(shí)間:2025/5/22 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】OpenCV里IplImage数据结构极易出错的问题,IplImage和单字节char*的相互转换 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。