有关正在发生的事情的解释,请参阅我之前关于编写 opencv 运算符的问题。
我想出了一个新的接口,它允许以一种可组合的方式组合破坏性的二进制操作:
newtype IOP a b = IOP (a -> IO b)
instance Category IOP where
id = IOP return
(IOP f) . (IOP g) = IOP $ g >=> f
(&#&) :: IOP (Image c d) e -> IOP (Image c d) f
-> IOP (Image c d) (Image c d,Image c d)
(IOP f) &#& (IOP g) = IOP $ op
where
op i = withClone i $ \cl -> (f i >> g cl >> return (i,cl))
runIOP (IOP f) img = withClone img f
有了这个,我可以很容易地表达“减去高斯算子”:
subtract :: IOP (Image c d, Image c1 d1) (Image c d)
mulScalar :: d -> IOP (Image c d) (Image c d)
subtractScalar :: d -> IOP (Image c d) (Image c d)
gaussian :: (Int, Int) -> IOP (Image GrayScale D32) (Image GrayScale D32)
(gaussian (11,11) &#& id) >>> subtract >>> mulScalar 5
对我来说,这似乎是一个非常安全的选择,尽管它在某种意义上并不是最佳的,如果减法后的某些操作需要它,它可能也可以重新使用克隆的图像。但它似乎仍然是完全纯且未优化的版本的可接受替代方案:
mulScalar 5 $ gaussian (11,11) img `subtract` img
-- Or with nicer names for the operators
5 * gaussian (11,11) img - img
问题
- 这首先是一个合理的结构吗?
- 是否有理由更喜欢上一个问题中的结构?
- 你将如何扩展它来实现一个操作“找到图像中的最小值,从图像中减去它,然后将图像乘以它的范围(即 max-min)。”
- 我应该把这些分成多个问题吗?