0

我现在正在开发一个图像二值化库,在这个库中将实现经典的二值化方法,如 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);
}

我的问题是哪个更好。欢迎提出有关设计图书馆的想法。谢谢!

4

2 回答 2

2

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

二值化的策略模式

例如,您可以这样做:

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

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

于 2013-06-04T21:17:30.687 回答
0

我知道这是一个旧帖子,但我会为有兴趣的人更新。这个问题的答案很容易被误导。如果你要编写一个高质量的图像二值化库,但还没有考虑清楚,那么在你开始之前,这里有一些事情你必须计划好。

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

对于第五点,如果您需要更快的速度,我有一个建议:模板和奇怪重复的模板模式。

如果您坚持使用 OOD 方法,我也会使用上面推荐的策略模式,但也会利用Facade来提供更清洁的体验。

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

于 2018-09-22T05:53:10.453 回答