문제

내 이전 내용을 참조하세요 질문 무슨 일이 일어나고 있는지 설명하기 위해 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. 대신 여러 질문으로 나누어야 합니까?
도움이 되었습니까?

해결책

hammar의 의견에 이어 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))

내 생각에 이것은 이 스타일이 꽤 표현력이 풍부하다는 좋은 논거입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top