См. Мой ранее вопрос о составлении операторов 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)».
- Должен ли я вместо этого разделить их на несколько вопросов?