.Net MAUIでOCRを実装する方法について紹介していきます。
紹介環境
当記事は以下の環境で作成しています。
開発環境
- Visual Studio 2022
- .Net 9
対象プラットフォーム
- Android 5.0以上
- iOS 16以上
OCRとは?
OCR(Optical Character Recognition)は、画像データや印刷物などのテキストを文字データに変換する技術になります。
OCRを実装する方法について
OCRの実装方法を手順に沿って紹介していきます。
ファイル構造は以下で作成しています。良ければ参考にしてください。

手順1:インターフェイスを準備します
DIで利用するためのインターフェイスを準備します。画像データにはMicrosoft.Maui.Graphics.IImageを利用して文字列を取得するようにします。
using IImage = Microsoft.Maui.Graphics.IImage;
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp.DI;
/// <summary>
/// OCRに関することを定義します。
/// </summary>
public interface IOcrServiceDI
{
/// <summary>
/// 文字列を取得します。
/// </summary>
/// <param name="image"></param>
/// <returns></returns>
public Task<string?> GetTextAsync(IImage image);
}
今回はAndroid・iOSのみの実装になるため、それ以外のプラットフォームではnullを返却するようにします。
#if !ANDROID && !IOS
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp.DI;
public class OcrServiceDI : IOcrServiceDI
{
public async Task<string?> GetTextAsync(Microsoft.Maui.Graphics.IImage image)
{
await Task.CompletedTask;
return null;
}
}
#endif
手順2:Xamarin.Google.MLKit.TextRecognition.Japaneseをインストールします
Xamarin.Google.MLKit.TextRecognition.JapaneseのパッケージをNuGetから取得します。Xamarin.Google.MLKit.TextRecognition.Japaneseの詳細は以下を確認してください。
パッケージをNuGetから取得する方法は以下のようになります。
手順A:ソリューション エクスプローラーの「依存関係」を右クリックし、メニューから「NuGet パッケージの管理(N)」をクリックします。

手順B:NuGet パッケージ マネージャーの検索欄に「Xamarin.Google.MLKit.TextRecognition.Japanese」と入力し、以下のようにインストールします。※この手順は参照タブで行います。

手順C:ライセンスの同意が表示されますので「同意する(A)」をクリックします。これでパッケージのインストールは完了します。

手順3:【Android】OCRを実装します
AndroidのOCRは以下のように実装します。
using Microsoft.Maui.Graphics.Platform;
using SampleApp.DI;
using Xamarin.Google.Android.Odml.Image;
using Xamarin.Google.MLKit.Vision.Text;
using Xamarin.Google.MLKit.Vision.Text.Japanese;
using IImage = Microsoft.Maui.Graphics.IImage;
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp.Platforms.Android.DI;
public class OcrServiceDI : IOcrServiceDI
{
/// <inheritdoc />
public async Task<string?> GetTextAsync(IImage image)
{
TaskCompletionSource<string?> tcs = new();
ITextRecognizer recognizer = TextRecognition.GetClient(new JapaneseTextRecognizerOptions.Builder().Build());
MlImage mlImage = new BitmapMlImageBuilder(image.AsBitmap()).Build();
recognizer.Process(mlImage).AddOnSuccessListener(new OnSuccessListener<Text>(
text =>
{
tcs.TrySetResult(text.GetText());
}));
return await tcs.Task;
}
}
手順3:【iOS】OCRを実装します
iOSのOCRは以下のように実装します。日本語に特化させるためにRecognitionLanguagesに「ja-JP」を指定しています。
using CoreGraphics;
using Foundation;
using Microsoft.Maui.Graphics.Platform;
using SampleApp.DI;
using System.Text;
using Vision;
using IImage = Microsoft.Maui.Graphics.IImage;
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp.Platforms.iOS.DI;
public class OcrServiceDI : IOcrServiceDI
{
/// <inheritdoc/>
public async Task<string?> GetTextAsync(IImage image)
{
TaskCompletionSource<string?> tcs = new();
VNRecognizeTextRequest textRequest = new(new((request, error) =>
{
StringBuilder stringBuilder = new();
VNRecognizedTextObservation[] results = request.GetResults<VNRecognizedTextObservation>();
foreach (VNRecognizedTextObservation result in results)
{
VNRecognizedText[] recognizedTexts = result.TopCandidates(1);
foreach (VNRecognizedText recognizedText in recognizedTexts)
{
stringBuilder.AppendLine(recognizedText.String);
}
}
tcs.TrySetResult(stringBuilder.ToString());
}))
{
RecognitionLevel = VNRequestTextRecognitionLevel.Accurate,
RecognitionLanguages = ["ja-JP"],
};
if (image.AsUIImage().CGImage is CGImage cgImage)
{
VNImageRequestHandler requestHandler = new(cgImage, new VNImageOptions());
requestHandler.Perform([textRequest], out NSError _);
return await tcs.Task;
}
return null;
}
}
VNRecognizeTextRequestのサポートしている言語はiOSのバージョンによって異なります。iOS16以上の場合、サポートしている言語は以下で確認できます。
string[] supportedLanguages = VNRecognizeTextRequest.GetSupportedRecognitionLanguages(VNRequestTextRecognitionLevel.Accurate, VNRecognizeTextRequestRevision.Three, out NSError error);
// サポートしている言語
// en-US,fr-FR,it-IT,de-DE,es-ES
// pt-BR,zh-Hans,zh-Hant,yue-Hans,yue-Hant
// ko-KR,ja-JP,ru-RU,uk-UA,th-TH
// vi-VT,ar-SA,ars-SA
手順4:DIを登録します
作成したDIを以下のように登録していきます。
using SampleApp.DI;
#if ANDROID
using SampleApp.Platforms.Android.DI;
#elif IOS
using SampleApp.Platforms.iOS.DI;
#endif
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
MauiAppBuilder builder = MauiApp.CreateBuilder();
builder.UseMauiApp<App>();
builder.Services.AddSingleton<IOcrServiceDI, OcrServiceDI>();
return builder.Build();
}
}
手順5:実装します
実装例は以下のようになります。実装例ではメディアピッカーで選択された画像データから文字列を取得します。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SampleApp.MainPage">
<ScrollView>
<VerticalStackLayout Padding="10" Spacing="20">
<Image
x:Name="img"
HeightRequest="300"
Aspect="AspectFit" />
<Label x:Name="lblText" />
<Button
Clicked="Button_Clicked"
Text="開始" />
</VerticalStackLayout>
</ScrollView>
</ContentPage>
using Microsoft.Maui.Graphics.Platform;
using SampleApp.DI;
using IImage = Microsoft.Maui.Graphics.IImage;
// 名前空間はプロジェクトに合わせてください。
namespace SampleApp;
public partial class MainPage : ContentPage
{
private IOcrServiceDI _ocrServiceDI;
public MainPage(IOcrServiceDI ocrServiceDI)
{
InitializeComponent();
_ocrServiceDI = ocrServiceDI;
}
private async void Button_Clicked(object sender, EventArgs e)
{
FileResult? fileResult = await MediaPicker.Default.PickPhotoAsync();
if (fileResult is null) return;
IImage image;
using (Stream stream = await fileResult.OpenReadAsync())
{
image = PlatformImage.FromStream(stream);
}
img.Source = fileResult.FullPath;
lblText.Text = await _ocrServiceDI.GetTextAsync(image);
}
}
動作イメージ
動作イメージは以下のようになります。


終わりに
OCRの実装は有料だと思っていましたが、無料で実装できましたので紹介してみました。良ければ参考にしてみてください。