返回Iterator与松散耦合

时间:2012-02-28 15:46:32

标签: c++ data-structures iterator

我对我正在编写的数据结构的架构有疑问。我正在写一个图像类,我将在特定的算法中使用它。在此算法中,我需要触摸图像中某个边界内的每个像素。我知道这样做的经典方法是使用两个嵌套的for循环:

for(int i = ROW_BORDER; i < img->height - ROW_BORDER; i++)
    for(int j = COL_BORDER; j < img->width - COL_BORDER; j++)
        WHATEVER 

但是,有人告诉我,在STL的样式中,返回迭代器通常更好,而不是像上面那样使用循环。使用迭代器来查看图像中的每个像素是非常容易的,并且甚至可以很容易地合并边界约束,但我觉得包括边框是从水中吹松耦合。

所以,问题是,如果我返回一个特殊的“border-excluded iterator”,请使用for循环,还是有更好的方法我没有想过?

只是为了避免“好吧,只需使用OpenCV或VXL!” ,我实际上并没有写一个图像类,我正在写一个用于特征检测器的高斯差分金字塔。也就是说,同样的问题适用,并且编写两个for循环比三个或四个更简单。

4 个答案:

答案 0 :(得分:1)

要重复使用某些内容,我会使用map函数。

namespace your_imaging_lib {

    template <typename Fun>
    void transform (Image &img, Fun fun) {
        const size_t width = img.width(), 
                     size  = img.height() * img.width();
        Pixel *p = img.data();
        for (size_t s=0; s!=size; s+=width)
        for (size_t x=0; x!=width; ++x)
            p[x + s] = fun (p[x + s]);

    }

    template <typename Fun>
    void generate (Image &img, Fun fun) {
        const size_t width = img.width(), size = img.height();
        Pixel *p = img.data();
        for (size_t s=0, y=0; s!=size; s+=width, ++y)
        for (size_t x=0; x!=width; ++x)
            p[x + s] = fun (x, y);
    }

}

需要进行一些改进。例如,某些系统如x,y在[0..1]中。

然后您可以使用它:

using namespace your_imaging_lib;
Image i = Image::FromFile ("foobar.png");
map (i, [](Pixel const &p) { return Pixel::Monochrome(p.r()); });

generate (i, [](int x, int y) { return (x^y) & 0xFF; });

如果您需要知道坐标(x和y),我保证与迭代器相比,这将提供更好的性能,迭代器需要对每次迭代进行额外的检查。

另一方面,迭代器会使你的东西可以使用标准算法,例如std::transform,如果不需要像素位置,你可以使它们几乎同样快,而你的间距也不大数据(音调用于对齐,通常在图形硬件表面上找到)。

答案 1 :(得分:0)

我怀疑你应该使用访问者模式 - 而不是返回迭代器或某种项目集合,你应该将每个像素/项目的操作传递给你的数据结构项目和数据结构应该能够将该操作应用于每个项目。您的数据结构是使用for循环还是迭代器遍历像素/隐藏任何集合,并且操作与数据结构分离。

答案 2 :(得分:0)

恕我直言,拥有一个触及每个像素的迭代器听起来是个好主意。但是,在我内部包含边界约束对我来说听起来并不吸引人。也许尝试实现类似的目标:

IConstraint *bc=new BorderConstraint("blue-border");
for(pixel_iterator itr=img.begin(); itr!=img.end(); itr++) {
    if(!bc->check(itr))
       continue;
    // do whatever
}

其中IConstraint是一个基类,可以派生它来制作许多不同的BorderConstraints。 我的理由是迭代器以不同的方式迭代,但我认为他们不需要了解您的业务逻辑。这可以通过上面的约束条件被抽象为另一个设计构造。

答案 3 :(得分:0)

在位图数据的情况下,值得注意的是在流行的图像处理API中通常没有基于迭代器的算法或数据集。这应该是一个很难实现的线索与常规2D阵列一样高效。 (感谢phresnel

如果你真的需要/更喜欢你的图像没有迭代器边框,你应该发明一个新概念来迭代。我的建议就像ImageArea。

class ImageArea: Image
{  int clipXLeft, clipXRight;
   int clipYTop, clipYBottom;
  public:
   ImageArea(Image i, clipXTop ... )

从那里构造你的迭代器。然后,迭代器可以是透明的,以处理图像中的图像或区域。

另一方面,基于x / y索引的常规方法并不是一个坏主意。迭代器对于抽象数据集非常有用,但是当您自己实现它们时会产生成本。