LoginSignup
2
5

More than 1 year has passed since last update.

C#/WinRT で OCR やってみた

Last updated at Posted at 2020-06-24

試してみたが、精度は微妙・・・?

環境について

WinRTはデフォルトだと入ってないので、インストールが必要です。
Windows8以上が必要で Visual Studioのオプションだったはず。。(忘れました。。。)

実行結果

入力画像

無題.png

出力結果

image.png

コンパイルバッチ

ダブルクオートつかった行は 「^」 で改行つなげないようなので1行にまとめた。

compile.bat

csc /r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime.WindowsRuntime\v4.0_4.0.0.0__b77a5c561934e089\system.runtime.windowsruntime.dll ^
/r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime.InteropServices.WindowsRuntime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.InteropServices.WindowsRuntime.dll ^
/r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.dll ^
/r:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\WindowsBase\v4.0_4.0.0.0__31bf3856ad364e35\WindowsBase.dll ^
/r:C:\Windows\Microsoft.NET\assembly\GAC_64\PresentationCore\v4.0_4.0.0.0__31bf3856ad364e35\PresentationCore.dll ^
"/r:C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.winmd" "/r:C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd" %*

ソースコード

コマンドライン引数で渡された画像ファイルから文字列を認識してコンソールに出力します。


using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Media.Ocr;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.Foundation;


class OcrTest
{
    [System.STAThread]
    static void Main(string[] args)
    {
        if(args.Length==0){return;}
        Task<string> ret = LoadImageAndOcr(args[0]);
        Console.WriteLine(ret.Result);
    }

    static async Task<OcrResult> detect(SoftwareBitmap bitmap)
    {
        var ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages();
        var ocrResult = await MyWaitUtil<OcrResult>.GetResultWithWaiting( ocrEngine.RecognizeAsync(bitmap) );
        // https://docs.microsoft.com/ja-jp/uwp/api/windows.media.ocr.ocrresult.lines?view=winrt-19041
        return ocrResult;
    }

    static async Task<string> LoadImageAndOcr(string path)
    {
        var inputFile = await MyWaitUtil<StorageFile>.GetResultWithWaiting(
            StorageFile.GetFileFromPathAsync( Path.GetFullPath(path) )
        );

        SoftwareBitmap softwareBitmap;
        // https://docs.microsoft.com/ja-jp/windows/uwp/audio-video-camera/imaging
        using (var stream = await MyWaitUtil<IRandomAccessStream>.GetResultWithWaiting(inputFile.OpenAsync(Windows.Storage.FileAccessMode.Read)))
        {
            // Create the decoder from the stream
            var decoder = await MyWaitUtil<BitmapDecoder>.GetResultWithWaiting(
                BitmapDecoder.CreateAsync(stream)
            );

            // Get the SoftwareBitmap representation of the file
            softwareBitmap = await MyWaitUtil<SoftwareBitmap>.GetResultWithWaiting((decoder.GetSoftwareBitmapAsync()));
        }

        OcrResult t = await detect(softwareBitmap);

        return t.Text;
    }
}

// IAsyncOperationのGetAwaiterがないとか謎のコンパイルエラーがでたので、その対策として実装した
public static class MyWaitUtil<T>
{
    public static async Task<T> GetResultWithWaiting(IAsyncOperation<T> task)
    {
        while(task.Status != AsyncStatus.Completed){
            if (task.Status == AsyncStatus.Error || task.Status == AsyncStatus.Canceled){
                Console.WriteLine("Error or Canceled");
                return default(T);
            }
            await Task.Delay(1);
        };
        return task.GetResults();
    }
}

参考サイト

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5