.NET MAUIで日本語OCRアプリを作ってみた(Windows)

.NET MAUIを使ってWindowsで動く無料のOCRアプリを作りました。

.NET MAUIはストアアプリなんですが、プロジェクト設定をいじればデスクトップアプリ(未サポート)にもできるのが良いなと思って使ってみました。

.NET MAUIのテンプレートプロジェクトを修正して、ボタンを押して画像を選択し、画像を表示する部分と、画像からOCRして結果を画面に表示する部分を作ります。

画像選択

画像の選択はメディアピッカーが用意されているのでこれを使います。

選択した画像を表示するために、MainPage.xamlのImageにx:Nameディレクティブを追加します。

<Image
    x:Name="PickedImage" ★ここを追加
    Source="dotnet_bot.png"
    SemanticProperties.Description="Cute dot net bot waving hi to you!"
    HeightRequest="200"
    HorizontalOptions="Center" />

メディアピッカーでFileResultを取得します。
FileResultクラスのFullPathプロパティにアクセスすることで選択した画像のパスが取得できます。
あとはx:Nameディレクティブで指定した値のSourceに選択した画像をセットすると画面上に画像が表示できます。

MainPage.xaml.csのOnCounterClicked内に以下を記載します。

FileResult photo = await MediaPicker.Default.PickPhotoAsync();
if(photo != null)
{
    PickedImage.Source = ImageSource.FromFile(photo.FullPath);
}

OCR

OCRのAPIはWindows.Media.Ocrを使用します。

実はこのAPIを選択した時点でマルチプラットフォームの利点は失われています。名前空間から想像できる通りWindowsでしか動かないAPIです。

OCRした文字列を表示するために、MainPage.xamlのLabelにx:Nameディレクティブを追加します。

<Label
    x:Name="OcrText" ★ここを追加
    Text="Hello, World!"
    SemanticProperties.HeadingLevel="Level1"
    FontSize="32"
    HorizontalOptions="Center" />

画像からOCRするには、画像をSoftwareBitmap形式に変換してあげる必要があります。メディアピッカーで取得したFileResultクラスにはOpenReadAsync()というメソッドがあり、これを使用することで選択した画像をStreamに変換できます。あとはBitmapDecoderからSoftwareBitmapに変換し、OcrEngineクラスのRecognizeAsyncメソッドを呼び出せばOCRできます。

using Stream stream = await photo.OpenReadAsync();
var decoder = await BitmapDecoder.CreateAsync(stream.AsRandomAccessStream());
var softwareBitmap = await decoder.GetSoftwareBitmapAsync();

var ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages();
var result = await ocrEngine.RecognizeAsync(softwareBitmap);
OcrText.Text = result.Text;

たったこれだけで画像からOCRするアプリが完成です。
早速動かしてみましょう。

OCR結果

それなりにOCRできているほうだと思います。正直使った画像が悪いです。
簡単に作れるのでぜひ試してみてください。

コード(MainPage.xaml.cs)

namespace MauiApp1;

#if WINDOWS
using Windows.Graphics.Imaging;
using Windows.Media.Ocr;
#endif

public partial class MainPage : ContentPage
{
	public MainPage()
	{
		InitializeComponent();
	}

	private async void OnCounterClicked(object sender, EventArgs e)
	{
		
		FileResult photo = await MediaPicker.Default.PickPhotoAsync();
		if(photo != null) 
		{
            PickedImage.Source = ImageSource.FromFile(photo.FullPath);

#if WINDOWS
			using Stream stream = await photo.OpenReadAsync();
			var decoder = await BitmapDecoder.CreateAsync(stream.AsRandomAccessStream());
			var softwareBitmap = await decoder.GetSoftwareBitmapAsync();

			var ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages();
			var result = await ocrEngine.RecognizeAsync(softwareBitmap);
			OcrText.Text = result.Text;
#endif
        }
	}
}

Windowsでしか動かない部分は #if WINDOWS ~ #endif で括ってあげるとよいです。


この記事が気に入ったらサポートをしてみませんか?