WPFでOCRに挑戦

今回はC#のWPFでOCRのプログラム製作にポンコツ2人組が挑戦してみました。 開発環境はVisualStudio2019でライブラリはMicrosoft.Windows.SDK.Contractsを使用しています。(バージョンは10.0.22621.755) NuGetでインストールしてください。
C#初心者が制作したものなのでいろいろとおかしい部分が多いと思います。プログラムを流用する際は適宜修正してください。

※この記事は2023/09/16時点の情報です。

MainWindow.xaml
ファイルを選択するダイアログを表示するボタンと読み取り結果を表示するテキストボックスをを配置しています。 ファイルを選択したタイミングで読み取り処理が実行されます。

<Window x:Class="Sample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="OCR" Height="350" Width="500">
    <Grid>
        <Button Content="Select Image" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,10,0,0" Height="20" Click="SelectImage_Click" Width="100"/>
        <TextBox x:Name="OCRResult" HorizontalAlignment="Stretch" Margin="10,56,10,10.5" IsReadOnly="True"/>
    </Grid>
</Window>

MainWindow.xaml.cs
ボタンクリックイベント処理とOCRを実行するコードです。 このコードでは、ファイルを選択し、選択した画像ファイルをOCRエンジンに渡してテキストを抽出し、結果をテキストボックスに表示します。

using Microsoft.Win32;
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using System.Windows;
using Windows.Graphics.Imaging;
using Windows.Media.Ocr;
using Windows.Storage.Streams;

namespace Sample
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void SelectImage_Click(object sender, RoutedEventArgs e)
        {
            // Common File Dialogを使用して画像ファイルを選択
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Image Files (*.jpg, *.jpeg, *.png)|*.jpg;*.jpeg;*.png";

            if (openFileDialog.ShowDialog() == true)
            {
                string selectedImagePath = openFileDialog.FileName;

                // 画像ファイルをOCRを実行
                string ocrResult = await PerformOCR(selectedImagePath);

                // 結果を表示
                OCRResult.Text = ocrResult;
            }
        }

        private async Task<string> PerformOCR(string imagePath)
        {
            try
            {
                // 画像ファイルをバイト配列として読み込む
                byte[] imageBytes = File.ReadAllBytes(imagePath);

                // バイト配列をIBufferに変換
                IBuffer buffer = imageBytes.AsBuffer();

                // IBufferからSoftwareBitmapに変換
                SoftwareBitmap softwareBitmap;
                using (var stream = new InMemoryRandomAccessStream())
                {
                    await stream.WriteAsync(buffer);
                    stream.Seek(0);
                    var decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(stream);
                    softwareBitmap = await decoder.GetSoftwareBitmapAsync();
                }

                // OCRエンジンを初期化
                OcrEngine ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages();

                // 画像をOCRにかけ、結果を取得
                OcrResult ocrResult = await ocrEngine.RecognizeAsync(softwareBitmap);

                // 認識結果をテキストに変換
                string recognizedText = ocrResult.Lines.Select(line => line.Text).Aggregate((current, next) => current + Environment.NewLine + next);

                return recognizedText;
            }
            catch (Exception ex)
            {
                return "OCRエラー: " + ex.Message;
            }
        }
    }
}

■読み取った画像ファイル

OCRで読み取った画像ファイル

以下がアプリケーションを実行した画面です。

C#のWPFでOCR読み取りした結果

以上が、WPFアプリケーションでWindows10のOCR機能を使用して画像ファイルの文字を読み取るプログラムです。 精度は思ったよりも低い印象です。ノイズやぼやけた画像は、誤検出を引き起こす可能性が高いようです。 高解像度でクリアな画像を使用すれば精度が向上するかもしれません。

管理人情報