F#でWPF --- OpenCV連携
下記記事にてOpenCVを.netから利用できるようC++/CLIでラップする方法を紹介しました。
OpenCVをC++/CLIでラップ - 何でもプログラミング
今回はWPFと連携させて画像を表示してみたいと思います。
作成するアプリケーション
ファイルダイアログで画像を選び、表示するアプリケーションを作成します。折角なのでエッジ化した画像も表示してみます。
Canny追加
C++/CLI側のコードは上記記事のものを利用します。
追加してCanny関数を定義します。
[ExtensionAttribute] static Mat8UC1^ Canny(Mat8UC1^ src, double threshold1, double threshold2) { auto dst = gcnew Mat8UC1(src->Cols, src->Rows); cv::Canny(*src->_mat, *dst->_mat, threshold1, threshold2); return dst; }
アプリケーションコード
WPFのImageコントロールはImageSourceクラスを受け取ります。
そのため、BitmapSource.Createを利用してMat8UC1クラスからBitmapSourceを作成しています。
Xaml内のOpenFileDialogActionは下記記事を参照してください。
F#でWPF --- ファイルダイアログCommand - 何でもプログラミング
F#内のDataContextは下記記事を参照してください。
F#でWPF --- Elm Architectureを利用したMVVM - 何でもプログラミング
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:local="clr-namespace:Actions;assembly=OpenCVSample" Title="MainWindow" Height="250" Width="400"> <Grid> <Button Content="画像を開く" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="100"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <local:OpenFileDialogAction Command="{Binding LoadImage}" /> </i:EventTrigger> </i:Interaction.Triggers> </Button> <UniformGrid Margin="10,40,10,10" Columns="2"> <Image Source="{Binding SrcImage}" /> <Image Source="{Binding DstImage}" /> </UniformGrid> </Grid> </Window>
F#
open System open System.Windows open System.Windows.Media open System.Windows.Media.Imaging open CV type Model = { SrcImage : BitmapSource DstImage : BitmapSource } let initialModel = { SrcImage = null DstImage = null } type Msg = LoadImage of string let updateModel model msg = match msg with | LoadImage x -> let mat = Processor.Load(x) let toBitmapSource (x : Mat8UC1) = BitmapSource.Create(x.Cols, x.Rows, 96.0, 96.0, PixelFormats.Gray8, null, x.Data, x.Cols * x.Rows, x.Cols) { model with SrcImage = toBitmapSource mat DstImage = toBitmapSource <| mat.Canny(50.0, 200.0) } [<STAThread>] [<EntryPoint>] let main argv = let window = Application.LoadComponent(Uri("MainWindow.xaml", UriKind.Relative)) :?> Window window.DataContext <- DataContext(initialModel, updateModel, id) Application().Run(window) |> ignore 0