我试着理解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/