[英]Convert RGB IplImage to 3 arrays
我需要一些C ++ /指針幫助。 當我創建一個RGB IplImage並且我想訪問i時,我使用以下C ++類: http : //www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv- intro.html
template<class T> class Image
{
private:
IplImage* imgp;
public:
Image(IplImage* img=0) {imgp=img;}
~Image(){imgp=0;}
void operator=(IplImage* img) {imgp=img;}
inline T* operator[](const int rowIndx) {
return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));}
};
typedef struct{
unsigned char b,g,r;
} RgbPixel;
typedef struct{
float b,g,r;
} RgbPixelFloat;
typedef Image<RgbPixel> RgbImage;
typedef Image<RgbPixelFloat> RgbImageFloat;
typedef Image<unsigned char> BwImage;
typedef Image<float> BwImageFloat;
我一直在使用CUDA,所以有時我必須將所有數據放入一個數組中,我喜歡將每個通道保存在自己的數組中,這樣看起來更容易處理數據。 所以我通常會這樣做:
IplImage *image = cvLoadImage("whatever.tif");
RgbImageFloat img(image);
for(int i = 0; i < exrIn->height; i++)
{
for(int j = 0; j < exrIn->width; j++)
{
hostr[j*data->height+i] = img[i][j].r;
hostg[j*data->height+i] = img[i][j].g;
hostb[j*data->height+i] = img[i][j].b;
}
}
然后我會將我的數據復制到設備上,用它做一些事情,把它拿回主機然后再循環,然后通過數組將數據分配回IplImage並保存我的結果。
看起來我已經循環到很多,必須有一個更快的方法用指針做這個,但我迷路了,必須有一個更有效的方法來做到這一點。 有沒有辦法可以簡單地為每個頻道使用指針? 我嘗試過這樣的事情,但它不起作用:
float *hostr = &img[0][0].r
float *hostg = &img[0][0].b
float *hostb = &img[0][0].g
有什么建議? 謝謝!
編輯:謝謝大家的回答。 也許我對自己的問題不太清楚。 我熟悉如何訪問頻道及其數據。 我感興趣的是提高從IplImage到標准陣列完全復制數據的性能和效率,更多的是csl到目前為止所說的。 我看到的問題是IplImage中的數據排列方式是“rgbrgbrgbrgb”。
首先,如果你對C ++感到滿意,你應該考慮使用OpenCV 2.0 ,它不使用圖像和矩陣的不同數據類型( IplImage*
和CvMat*
),並使用一個結構( Mat
)來處理它們。 除了自動內存管理和一大堆有用的例程來處理頻道等,以及一些MATLAB特色的,它使用起來真的很有趣。
對於您的特定問題,您可以使用Mat
訪問IplImage*
的通道,如下所示:
IplImage *image = cvLoadImage("lena.bmp");
Mat Lena(image);
vector<Mat> Channels;
split(Lena,Channels);
namedWindow("LR",CV_WINDOW_AUTOSIZE);
imshow("LR",Channels[0]);
waitKey();
現在,你必須在每個通道的副本vector
Channels
。
如果你不希望使用OpenCV2.0
並提取通道,請注意以下幾點。 OpenCV以下列方式訂購多通道圖像:
x(1,1,1) x(1,1,2) x(1,1,3) x(1,2,1) x(1,2,2) x(1,2,3) ...
其中x(i,j,k) = an element in row i of column j in channel k
此外,OpenCV的墊它的圖像..所以不要忘記跳行widthStep
占這些填充空白。 按照csl所說的 ,在外部循環中增加行指針(使用widthStep
)並增加此指針以訪問行中的元素。
注意:
既然您現在使用的是2.0,那么可以使用Mat Lena = imread("Lena.bmp");
繞過IplImage*
Mat Lena = imread("Lena.bmp");
。
這里有很大的改進空間。 這么多,您應該了解人們如何訪問位圖。
首先,盡可能增加內存位置。 這將增加緩存命中和性能。 即,不要為每個顏色通道使用三個單獨的陣列。 將每個存儲在一起,因為您可能主要使用像素。
其次,不要對每個像素進行y *寬度計算。 在內循環中完成時,它會消耗很多周期。
最后,如果你只想要一個完整的圖像副本,那么你可以簡單地做一個memcpy(),這非常快。 我無法推斷你是否從浮點數轉換為整數,但如果沒有,則使用memcpy()表示非重疊區域。
如果你想知道如何使用指針(偽代碼,也沒有測試)來做到這一點:
float *dst = &hostg[0][0];
RgbPixelFloat *src = &img[0][0];
RgbPixelFloat *end = &img[HEIGHT][WIDTH] + 1;
// copy green channel of whole image
while ( src != end ) {
*dst = src->g;
++dst;
++src;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.