5

私は Gtk2H で中規模の GUI を構築しようとしていますが、システムを構築する最善の方法が何であるかはよくわかりません。サブコンポーネントを個別に開発し、一般的に後で髪を引っ張らないような構造になる方法を探しています。

主な問題は、API が継続ベースであるカメラなどのコンポーネントによって引き起こされます (つまり、カメラを使用してブロックを でラップする必要がありますwithVideoMode :: Camera Undefined -> (Camera a -> IO ()) -> IO ())。これらも分離したいのですが、これを行うための合理的な方法が見つかりません。

追加する必要があるほとんどのコンポーネントには、カメラ パラメーターの設定やウィジェットの構築などの初期化、他のコンポーネントによってトリガーされるイベントのキャッチ、ハードウェアの切断などのクリーンアップが最後に必要です。

これまでのところ、私はContTcps パーツに使用し、コンポーネントにスナップレットのようなものを使用して、それらをStateどこかに隠すことを考えていました。gtk2hs コールバックでトランスフォーマーをエレガントに使用できないため、1 つ目は非常に重く、2 つ目は厄介に見えます。

(なんらかの理由で、今日は要旨が機能しないため、ここに巨大なコード全体を投稿して申し訳ありません)

{-#LANGUAGE ScopedTypeVariables#-}
{-#LANGUAGE DataKinds #-}

import CV.CVSU
import CV.CVSU.Rectangle
import CV.Image as CV
import CV.Transforms
import CV.ImageOp 
import CV.Drawing as CV
import CVSU.PixelImage
import CVSU.TemporalForest
import Control.Applicative
import Control.Applicative
import Control.Concurrent
import Control.Monad
import Data.Array.MArray
import Data.IORef
import Data.Maybe
import Data.Word
import Utils.Rectangle
import Foreign.Ptr
import Graphics.UI.Gtk

import System.Camera.Firewire.Simple

convertToPixbuf :: CV.Image RGB D8 -> IO Pixbuf
convertToPixbuf cv = withRawImageData cv $ \stride d -> do
    pixbufNewFromData (castPtr d) ColorspaceRgb False 8 w h stride
   where (w,h) = getSize cv


initializeCamera dc e = do 
    putStrLn $ "Initializing camera "++show e
    cam <- cameraFromID dc e
    setOperationMode cam B
    setISOSpeed  cam ISO_800
    setFrameRate cam Rate_30
    setupCamera cam 20 defaultFlags
    return cam

handleFrame tforest image = do
  pimg    <- toPixelImage (rgbToGray8 image)
  uforest <- temporalForestUpdate tforest pimg
  uimg    <- temporalForestVisualize uforest
  --uimage  <- expectByteRGB =<< fromPixelImage uimg
  temporalForestGetSegments uforest

  --mapM (temporalForestGetSegmentBoundary uforest) ss

createThumbnail img = do 
     pb     <- convertToPixbuf $ unsafeImageTo8Bit $ scaleToSize Linear True (95,95) (unsafeImageTo32F img)
     imageNewFromPixbuf pb


main :: IO ()
main = withDC1394 $ \dc -> do
    -- ** CAMERA Setup **
    cids <- getCameras dc
    cams <- mapM (initializeCamera dc) $ cids

    -- ** Initialize GUI ** 
    initGUI
    pp <- pixbufNew ColorspaceRgb False 8 640 480
    window <- windowNew

    -- * Create the image widgets 
    images <- vBoxNew True 3
    image1  <- imageNewFromPixbuf pp
    image2  <- imageNewFromPixbuf pp
    boxPackStart images image1 PackGrow 0 
    boxPackEnd   images image2 PackGrow 0 

    -- * Create the Control & main widgets
    screen     <- hBoxNew True 3
    control    <- vBoxNew True 3
    info       <- labelNew (Just "This is info")
    but        <- buttonNewWithLabel "Add thumbnail"
    thumbnails <- hBoxNew True 2
    boxPackStart screen images PackGrow 0 
    boxPackStart screen control PackGrow 0 
    boxPackStart control info PackGrow 0 
    boxPackStart control but PackRepel 0 
    boxPackStart control thumbnails PackGrow 0 
    but `onClicked` (do
        info<- labelNew (Just "This is info")
        widgetShowNow info
        boxPackStart thumbnails info PackGrow 0)

    set window [ containerBorderWidth := 10
                   , containerChild := screen ]

    -- ** Start video transmission **
    withVideoMode (cams !! 0) $ \(c :: Camera Mode_640x480_RGB8) -> do
--     withVideoMode (cams !! 1) $ \(c2 :: Camera Mode_640x480_RGB8) -> do
        -- ** Start cameras ** --
        startVideoTransmission c
--        startVideoTransmission c2
        -- ** Setup background subtraction ** --
        Just f <- getFrame c 
        pimg <- toPixelImage (rgbToGray8 f)
        tforest <- temporalForestCreate 16 4 10 130 pimg

        -- * Callback for gtk
        let grabFrame = do
            frame <- getFrame c 
--            frame2 <- getFrame c2 
            maybe (return ()) 
                  (\x -> do
                          ss <- handleFrame tforest x
                          let area = sum [ rArea r | r <- (map segToRect ss)]
                          if area > 10000 
                                then return ()
                                 --putStrLn "Acquiring a thumbnail"
                                 --tn <- createThumbnail x
                                 --boxPackStart thumbnails tn PackGrow 0 
                                 --widgetShowNow tn
                                 --containerResizeChildren thumbnails
                                else return ()
                          labelSetText info ("Area: "++show area)
                          pb <- convertToPixbuf
                                    --  =<< CV.drawLines x (1,0,0) 2 (concat segmentBoundary)
                                    (x <## map (rectOp (1,0,0) 2) (map segToRect ss) )
                          pb2 <- convertToPixbuf x
                          imageSetFromPixbuf image1 pb
                          imageSetFromPixbuf image2 pb2
                          )
                  frame
--            maybe (return ()) 
--                  (convertToPixbuf >=> imageSetFromPixbuf image2)
--                  frame2
            flushBuffer c 
--            flushBuffer c2 
            return True

        timeoutAddFull grabFrame priorityDefaultIdle 20

        -- ** Setup finalizers ** 
        window `onDestroy` do
                    stopVideoTransmission c
                    stopCapture c
                    mainQuit

        -- ** Start GUI **
        widgetShowAll window
        mainGUI
4

1 に答える 1

3

したがって、要件は次のとおりです。

  • CPS スタイル API
  • リソースの初期化とファイナライズ
  • おそらくIO用のモナドトランスフォーマー
  • モジュール性と構成可能性

イテレータ ライブラリの 1 つがあなたにぴったりのようです。特にconduitは最も成熟したリソースのファイナライズを備えていますが、 の理論的な優雅さと構成可能pipes性にも興味があるかもしれません。コードがIOベースのみの場合は、新しくリリースされio-streamsたものも良い選択です。

pipes: http://hackage.haskell.org/packages/archive/pipes/3.1.0/doc/html/Control-Proxy-Tutorial.html

conduit: https://www.fpcomplete.com/school/pick-of-the-week/conduit-overview

io-streams: http://hackage.haskell.org/packages/archive/io-streams/1.0.1.0/doc/html/System-IO-Streams-Tutorial.html

あなたが達成しようとしていることの小さなスニペットまたは説明を提供する場合は、pipes(私が最もよく知っているライブラリ)を使用してそれを書くことができます

于 2013-03-13T14:27:52.767 に答える