用于图像处理的overload [] []运算符

use*_*rfi 2 c++ image-processing

我有一个类图像,其中包含一个名为buffer的成员,一个存储图像像素的unsigned char矢量.我想把这个缓冲区作为一个矩阵处理.我想像img [i] [j]那样访问缓冲区,但我不知道怎么做?有谁能建议我一个解决方案?

这是我的试探性的:

unsigned char * &Image::operator[](int i) {

       return buffer[ rows+i  ]
}
Run Code Online (Sandbox Code Playgroud)

我读了这篇文章然后我认为这是可能的.我的课就是这样的:

class Image {


private:

unsigned char * buffer;
int buf_size;
int rows;
int cols;
Phisical_img_manager phisical_img_manager;

const char * in_img_filename;


public:

unsigned char * & operator[](int i);

Image(const char * in_img_filename);

unsigned char * get_buffer();
int get_cols();
int get_rows();

};
Run Code Online (Sandbox Code Playgroud)

101*_*010 6

您可以按行主要顺序执行以下操作:

class Image {
  int rows, cols;
  unsigned char *buffer;
public:
  // ...  
  unsigned char*       operator[](int const i)       { return &(buffer[i * cols]); }
  unsigned char const* operator[](int const i) const { return &(buffer[i * cols]); }
};
Run Code Online (Sandbox Code Playgroud)

现场演示

讨论

您的缓冲区是一个连续的内存块.大小N = rows * cols.

在此输入图像描述

然而,图像的概念是以2D构造/矩阵排列的一组像素:

在此输入图像描述

我们想要的是将这个2D构造安排在计算机内存中的1D缓冲区中.我们可以通过两种方式做到这一点:

  1. 排主要订单.
  2. 列主要订单.

行优先顺序我们店后,其他的像一个的每一行.也就是说,对于以下尺寸的2x2图像

在此输入图像描述

相应的缓冲存储器看起来像:

在此输入图像描述

列主要顺序中,我们一个接一个地存储图像的每一列.也就是说,相同大小的2x2图像的缓冲区存储看起来像: 在此输入图像描述

支持多维数组的编程语言要么为它们实现行主要或列主要存储顺序.在C和C++中,使用行主要顺序.

在上面显示的代码中,我们实现了行主顺序.我们定义了一个重载的下标运算符,它将i我们想要访问的行索引(例如)作为输入.将其i与列数相乘,我们得到ith图像中行的起始索引.我们返回该特定地址中元素的地址.此地址标记原始缓冲区的子数组的开始以及ith行的开头.为了进一步说明,请参阅以下代码示例:

Image I(2, 3);
I[1][2] = 42;
Run Code Online (Sandbox Code Playgroud)

呼叫I[1][2] = 42就像呼叫:

(I.operator[](1))[2];
Run Code Online (Sandbox Code Playgroud)

sub-call I.operator[](1)返回指向图像第二行开始的地址的指针.然后我们将此返回的指针用作普通的动态分配数组.在这个具体的例子中,我们向这个指针添加2(即,这是做什么[2]),因此我们得到行的元素,该行位于行的第一个元素之后的2个位置(即,第二行的第三个元素)图片).

C++ 11的替代解决方案

如果您的编译器支持C++ 11和智能指针,您可以执行以下方案以避免内存管理.此外,我会重载,operator()(std::size_t const, std::size_t const)因为上面的重载你暴露缓冲区,因此你正在伤害封装:

class Image {
  int rows, cols;
  std::unique_ptr<unsigned char[]> buffer;
public:
  Image(int const rows_ = 0, int const cols_ = 0) 
  : rows(rows_), cols(cols_), buffer(new unsigned char[rows * cols]) {}
  Image(Image const &other)
  : rows(other.rows), cols(other.cols), buffer(new unsigned char[rows * cols]) {
    std::copy(other.buffer.get(), other.buffer.get() + (rows * cols), buffer.get());
  }
  Image(Image &&other) 
  : rows(other.rows), cols(other.cols), buffer(std::move(other.buffer)) {
    other.rows = 0;
    other.cols = 0;
  }
  unsigned char&       operator()(std::size_t const i, std::size_t const j) {
    return buffer[cols * i + j];
  }
  unsigned char const& operator()(std::size_t const i, std::size_t const j) const {
    return buffer[cols * i + j];
  }
  Image& operator=(Image const &other) {
    rows = other.rows;
    cols = other.cols;
    buffer.reset(new unsigned char[rows * cols]);
    std::copy(other.buffer.get(), other.buffer.get() + (rows * cols), buffer.get());
    return *this;
  }
  Image& operator=(Image &&other) {
    rows = other.rows;
    cols = other.cols;
    buffer.swap(other.buffer);
    other.rows = 0;
    other.cols = 0;
    return *this;
  }
  // ...
};
Run Code Online (Sandbox Code Playgroud)

现场演示