c++ - 将 RGB IplImage 转换为 3 个数组

标签 c++ performance arrays opencv iplimage

我需要一些 C++/指针帮助。当我创建一个 RGB IplImage 并且我想访问 i,j 时,我使用以下 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,所以有时我必须将所有数据放入一个数组中,我喜欢将每个 channel 都保存在自己的数组中,这样处理数据似乎更容易。所以我通常会这样做:

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 并保存我的结果。

似乎我循环了很多,必须有一种更快的方法来使用指针来执行此操作,但我迷路了,必须有一种更有效的方法来执行此操作。有没有一种方法可以简单地为每个 channel 使用一个指针?我试过做这样的事情,但没有成功:

float *hostr = &img[0][0].r
float *hostg = &img[0][0].b
float *hostb = &img[0][0].g

有什么建议吗?谢谢!

编辑: 谢谢大家的回答。也许我对我的问题不是很清楚。我熟悉如何访问 channel 及其数据。我感兴趣的是提高将数据从 IplImage 完全复制到标准数组的性能和效率,更符合 csl 到目前为止所说的内容。我看到的问题是 IplImage 中数据的排列方式是“rgbrgbrgbrgb”。

最佳答案

首先,如果您熟悉 C++,您应该考虑使用 OpenCV 2.0它消除了图像和矩阵(IplImage*CvMat*)的不同数据类型,并使用一种结构 (Mat) 来处理这两种数据。除了自动内存管理和大量有用的例程来处理 channel 等,还有一些 MATLAB 风格的例程,使用起来真的很有趣。

对于您的特定问题,您可以使用 Mat 访问 IplImage* 的 channel ,如下所示:

 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 中拥有每个 channel 的拷贝。

如果您不想使用OpenCV2.0 和提取 channel ,请注意以下事项。 OpenCV 按以下方式对多 channel 图像进行排序:

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) = channel k 中第 j 行第 i 行中的一个元素

另外,OpenCV pads 它是图像 .. 所以不要忘记使用 widthStep 来跳转行,这说明了这些填充间隙。并按照什么csl said ,增加外循环中的行指针(使用 widthStep)并增加此指针以访问一行中的元素。

注意:

由于您现在使用的是 2.0,因此您可以使用 Mat Lena = imread("Lena.bmp"); 绕过 IplImage*

关于c++ - 将 RGB IplImage 转换为 3 个数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1568377/

相关文章:

c++ - 在返回表达式中奇怪地使用 & 运算符

ruby-on-rails - 如何阻止我的 rails 应用程序被机器人攻击?

javascript - 如何正确使用Array.Splice

c++ - ofstream 两次将所有内容写入我的文件

c++ - 简单迭代器:std::count 错误

c++ - 嵌套的 std::transform 效率低吗?

performance - 优化 app.yaml

python - 传递给线程时求和 numpy.ndarray 失败

c - 为什么不能在 C 中返回固定大小/常量数组?

c++ - 为什么我过滤后的图像(应该是二进制的)仍然包含彩色部分?(OpenCV in C++)