1

何が起こっているかの説明については、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

質問

  1. そもそもこれは合理的な構造ですか?
  2. 前の質問の構造を好む理由はありますか?
  3. これをどのように拡張して、「画像内の最小値を見つけ、それを画像から減算し、画像にその範囲 (最大-最小) を掛ける」という操作を実装するにはどうすればよいでしょうか。
  4. 代わりに、これらを複数の質問に分割する必要がありますか?
4

1 に答える 1

2

ハマーのコメントから続けて、IOPを完全に回避して、最初にkleisli構成を使用することができます。わかりやすくするために、ImageOpをタイプの同義語として使用しました。また、常に単位を返すように特化し、それに応じて他の型注釈を変更して、突然変異関数(単位を返す)とクロイン関数(新しい値を返す)の型の違いとapOp、突然変異関数とミューテーションを簡単に連鎖できるように、ミューテーションされた値を返します。

type ImageOp c d -> Image c d -> IO ()

(&#&) :: ImageOp c d -> ImageOp c d -> (Image c d) -> IO (Image c d, Image c d)
f &#& g = \i -> withClone i $ \cl -> f i >> g cl >> return (i,cl)

apOp :: ImageOp c d -> Image c d -> IO (Image c d)
apOp iop x = fmap x (iop x)

subtract  ::  Image c d ->  ImageOp c1 d1
mulScalar :: d -> ImageOp (Image c d)
subtractScalar :: d -> ImageOp (Image c d)
gaussian  :: (Int, Int) -> ImageOp GrayScale D32

myFun = (gaussian (11,11) &#& id) >=> (\(x,y) -> apOp (subtract x) y) >=> apOp (mulScalar 5) 

--pointfree
myFun = (gaussian (11,11) &#& id) >=> uncurry (apOp . subtract) >=> apOp (mulScalar 5) 

編集 気になる場合は&#&、次のようにきれいに書くことができます。

f &#& g = uncurry (liftM2 (,)) . (apOp f &&& withClone (apOp g))

これは、このスタイルがかなり表現力豊かであることの良い議論だと思います。

于 2011-05-20T16:51:28.390 に答える