图像二值化库的设计模式

时间:2013-06-04 16:35:49

标签: c++ design-patterns image-processing

我现在正在开发一个图像二值化库,在这个库中将实现经典的二值化方法,如Sauvola和Otsu方法。现在我的问题是如何优雅地设计图书馆。就目前而言,我有两个解决方案:

解决方案1:

    class Binarization
    {
    public:
       BiinterfacePtr interface_;
       enum BinarizationMethods
       {
           Method1, Method2, Method3, Method4
       }
       void set(BinarizationMethods method, Image *p_in, Image *p_out, Binarizationpara &para)
       {
           if (method == Method1)
           {
               BiinterfacePtr interfacetemp(new BinarizationMethod1());
               interface_ = interfacetemp;
            }
           if (method == Method2)
           {
            BiinterfacePtr interfacetemp(new BinarizationMethod2());
               interface_ = interfacetemp;
           } 
           ....
       }
       bool run()
       {  
          interface_->run();
        }
       Image* output()
       {
          return interface->output();
        }
}

如您所见,不同的二值化方法的实现是在Biinterface类中完成的。当我们使用Binarization类时,我们可以通过调用set方法来表示我们想要使用的方法。然而,广告不同的二值化方法可能具有不同的参数设置,Binarizationpara的结构将变得复杂。

解决方案2

class BinarizationMethod1()
{
  public:
    perform_binarization(Image *p_in, Image *p_out, BinarizationMethod1Para &para);
}

class BinarizationMethod2()
{
  public:
    perform_binarization(Image *p_in, Image *p_out, BinarizationMethod2Para &para);
}

我的问题是哪一个更好。关于设计图书馆的想法将受到欢迎。谢谢!

2 个答案:

答案 0 :(得分:2)

我会选择一个简单的strategy pattern,这看起来像是你的第一个解决方案,只有我会使用构造函数注入。我真的不明白为什么要使用枚举,它是紧密耦合的,而不是维护应用程序的最佳方式。您也可以直接将您想要的方法传递给Binarization模块。如果需要将参数传递给方法,只需使用它们的run方法(当然,如果它们都有相同的方法,否则你可以使用方法构造函数)。此外,这使得新方法的创建和维护变得容易。

Strategy pattern for Binarization

例如,您可以这样做:

Binarization binarization(new SauvolaMethod()...);
binarization->run();

免责声明:我不是C ++人

答案 1 :(得分:0)

我知道这是一篇旧文章,但是我会为感兴趣的人更新。 这个问题的答案很容易被误导。如果您打算编写高质量的图像二值化库,但是还没想通,那么在开始之前,还需要计划一些事情。

  1. 在C ++中没有很好的图像读取器/写入器,因此您可能需要创建一个通用的图像概念,该概念可与第三方库一起使用。但是,该图像将保持32b RGBA值还是8b灰度/黑白值?这会对设计产生重大影响。
  2. 一旦您最终可以处理图像,就会发现如果没有整体图像优化,算法将运行得太慢。所有本地自适应阈值算法都可以共享这一点。确保它是您设计的一部分。
  3. 现在使用的是积分图像,对于大图像而言,需要存储在这些结构中的值可能太大。现在,您需要以“平铺”方法进行设计,该方法将按块处理大型图像。
  4. 现在您要平铺,为什么要依次进行?这应该使您质疑所有问题,并想知道为什么不首先将其发送到GPU进行自定义内核处理。
  5. 您终于做到了。您的库看起来很棒,拥有所有的魔力,但是它可能没有它想的那么快,因为您不想走GPU路线,而是选择了面向对象继承的重型设计。许多编译器无法像您希望的那样优化这种结构。除非将它与具有等效功能的单片函数进行比较,否则您将永远不会真正注意到它。

关于第五点,如果您需要提高速度,我有一个建议:模板和奇怪的重复出现的模板模式。

如果您坚持使用OOD方法,那么我还将按照上面的建议使用策略模式,但还要利用外观来提供更干净的体验。

祝你好运!我是根据经验说的:https://github.com/brandonmpetty/Doxa