opencv - 在 haskell-opencv 中为 coreceMatM 定义正确的类型

标签 opencv haskell image-processing

我试着理解haskell-opencv图书馆。

我移植了 orb-detection example对于我的图片:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad
import Linear.V4
import Linear.V2
import OpenCV as CV
import OpenCV.Internal.Mutable
import qualified Data.ByteString as B


main = do
    img <- imdecode ImreadColor <$> B.readFile "input.jpg"
    let orb = mkOrb defaultOrbParams
    let imgData = exceptError $ do
            (kpts, _descs) <- orbDetectAndCompute orb img Nothing
            let mi = matInfo img
                clr = (toScalar $ V4 (255::Double) 255 255 0)::(Scalar)
                shape = toShape $ miShape mi
                chan = toChannels $ miChannels mi
                depth = toDepth $ miDepth mi
            resImg <- withMatM shape chan depth clr $ \imgM -> do
                let img' = exceptError $ coerceMatM imgM
                    img'' = (unMut img'')::CV.Mat ('S ['D, 'D]) 'D 'D
                    img''' = Mut img''
                -- let img''' = (exceptError $ coerceMatM imgM)::(CV.Mut (CV.Mat ('S ['D, 'D]) 'D 'D) (PrimState (ST s)))
                void $ matCopyToM img''' (V2 0 0) img Nothing
                forM_ kpts $ \kpt -> do
                    let kptRec = keyPointAsRec kpt
                    circle img''' (round <$> kptPoint kptRec) 5 (V4 (255::Double) 0 0 255) 1 LineType_AA 0
                    return ()
            imencode OutputBmp resImg
    B.writeFile "output.bmp" imgData

Ufff,在阅读了两个小时的文档之后,它成功了!

但我不明白,如何正确编写 Mat 的核心并键入它,我的代码非常难看:

let img' = exceptError $ coerceMatM imgM
    img'' = (unMut img')::CV.Mat ('S ['D, 'D]) 'D 'D
    img''' = Mut img'

我用 unMut 解包,然后再打包回去。

我尝试指定 Mut (Mat ...) 的类型(参见上面的注释行):

let img''' = (exceptError $ coerceMatM imgM)
   ::(CV.Mut (CV.Mat ('S ['D, 'D]) 'D 'D) (PrimState (ST s)))

但是编译器发誓:

src/exmpl.hs:29:60: error:
    • Couldn't match type ‘s’ with ‘s2’
      ‘s’ is a rigid type variable bound by
        a type expected by the context:
          forall s.
          Mut
            (Mat
               (ShapeT (Data.Vector.Vector GHC.Int.Int32))
               (ChannelsT GHC.Int.Int32)
               (DepthT Depth))
            (PrimState (ST s))
          -> CvExceptT (ST s) ()
        at src/exmpl.hs:23:27
      ‘s2’ is a rigid type variable bound by
        an expression type signature:
          forall s2. Mut (Mat ('S '['D, 'D]) 'D 'D) (PrimState (ST s2))
        at src/exmpl.hs:29:67
      Expected type: Mut (Mat 'D (ChannelsT GHC.Int.Int32) 'D) s2
        Actual type: Mut
                       (Mat
                          (ShapeT (Data.Vector.Vector GHC.Int.Int32))
                          (ChannelsT GHC.Int.Int32)
                          (DepthT Depth))
                       (PrimState (ST s))

那么,如何为 img''' 确定正确的类型??

最佳答案

我想通了。它需要使用 pureExcept 和作用域类型变量:

(imgM''':: Mut (Mat (S [D, D]) D D) s) <- pureExcept $ coerceMatM imgM

完整的程序是:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad
import Linear.V2
import Linear.V4
import OpenCV as CV
import qualified Data.ByteString as B


main = do
    img <- imdecode ImreadColor <$> B.readFile "input.jpg"
    let orb = mkOrb defaultOrbParams
    let imgData = exceptError $ do
            (kpts, _descs) <- orbDetectAndCompute orb img Nothing
            let mi = matInfo img
                clr = (toScalar $ V4 (255::Double) 255 255 0)::(Scalar)
                shape = toShape $ miShape mi
                chan = toChannels $ miChannels mi
                depth = toDepth $ miDepth mi
            resImg <- withMatM shape chan depth clr $ \imgM -> do
                (imgM':: Mut (Mat (S [D, D]) D D) s) <- pureExcept $ coerceMatM imgM
                void $ matCopyToM imgM' (V2 0 0) img Nothing
                forM_ kpts $ \kpt -> do
                    let kptRec = keyPointAsRec kpt
                    circle imgM' (round <$> kptPoint kptRec)
                                 5
                                 (V4 (255::Double) 0 0 255)
                                 1
                                 LineType_AA
                                 0
                    return ()
            imencode OutputBmp resImg
    B.writeFile "output.bmp" imgData

关于opencv - 在 haskell-opencv 中为 coreceMatM 定义正确的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43269710/

相关文章:

python - OpenCV - 获取所有 Blob 像素

python - 使用Python在OpenCV中检测MultiScale的参数

c++ - 使用 FLANN 匹配从 OpenCV SIFT 列表中识别图像

haskell - 简单的 Liquidhaskell 示例未能达到预期的行为

haskell - 什么是在 Haskell 中生成所有整数的无限列表的好方法

c++ - 我如何使用 OpenCV 重写这个 warp-affine?

javascript - 查找一个二维数组在另一个二维数组中出现的所有位置

opencv - Linux 上是否有用于 .net 核心的 OpenCV 的包装器

haskell - 应该如何使用forever函数呢?

c++ - FFmpeg 中 RGB 到 YUV 的转换错误