簡體   English   中英

將RGB IplImage轉換為3個數組

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM