windows

Azure Ocr C#

Azure Ocr C#

Azure Document Intelligence を利用したOCRソフト。基本は、画像ファイルを処理します。PDFファイルを利用した場合は、[ PdfToImage ] クリックでいったんPDFからJPEGへ変換してから、JPEGファイルを選択します。契約形態がフリー(F0)の場合は、ファイルサイズ4MB未満、1枚のみです。4MB以上の場合は、画像の選択範囲を設定して部分的にOCR処理します。日本語の縦書き文章は、何故か左から右に処理するので認識後、行を逆順に並び替えることができます。部分的にOCR処理ができるので細かく認識できます。[ Cut_Image ]をクリックすると選択範囲をZOOMします。この範囲を [ Part Ocr ] で認識します。[ Reverse ]をクリックすると逆順になります。

Document Intelligence モデルを使用する

Foundry Tools の Azure ドキュメント インテリジェンスは、機械学習を使用してドキュメントから主要なテキストと構造要素を抽出するクラウドベースの Foundry Tools サービスです。 テクノロジを学習するときに、無料サービスを使用することをお勧めします。 無料のページは 1 か月あたり 500 ページに制限されていることに注意してください。

前提条件

Azure サブスクリプション。無料で作成できます

Visual Studio IDE

Foundry Tools またはドキュメント インテリジェンス リソース。 単一サービスまたはマルチサービス。 Free 価格レベル (F0) を使用してサービスを試用し、後から運用環境用の有料レベルにアップグレードすることができます。

アプリケーションを Azure ドキュメント インテリジェンスに接続するために作成するリソースのキーとエンドポイント。

  1. Azure アカウントと音声リソース:
    • 有効な Azure サブスクリプションが必要です。無料で作成できます。
    • Azure ポータルで、新しい「Document Intelligence」サービス リソースを作成します。
    • 作成したら、リソースの「キーとエンドポイント」セクションに移動し、キー 1 またはキー 2 とエンドポイントをコピーします。
  2. 開発環境:
    • 適切な Microsoft Visual C++ 再頒布可能パッケージがインストールされたVisual Studio (2015、2017、2019、または 2022) 。
    • 互換性のある .NET プラットフォーム (.NET Core、.NET 5+、.NET Standard 2.0 など) を対象とする C# プロジェクト。
    • Azure.AI.FormRecognizer  NuGet パッケージをインストールします。NuGet パッケージ マネージャー コンソールからインストールできます。

Form1

Form2

「 Azure.AI.FormRecognizer 」 FreeSpire.PDF 」 を導入。

Form1.cs

using Azure;
//using Azure.AI.DocumentIntelligence;
using Azure.AI.FormRecognizer.DocumentAnalysis;
using Microsoft.Extensions.Azure;
using Spire.Pdf;
using Spire.Pdf.Graphics;
using Spire.Pdf.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ImageToTextAz
{
    public partial class Form1 : Form
    {
        //control clsResize 画面表示を拡大縮小します。
        clsResize _form_resize;

        //Form1オブジェクトを保持するためのフィールド
        private static Form1 _form1Instance;
        //

        private static string endpoint = "your endpoint";
        private static string apiKey = "your key";
        private static string selectfile = "";

        //解像度
        private int IMG_DPI = 300;
        private long JPEG_QUALITY = 100;
             
        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool AllocConsole();

        public Form1()
        {

            InitializeComponent();

            Form1.Form1Instance = this;

            //clsResize
            _form_resize = new clsResize(this); //I put this after the initialize event to be sure that all controls are initialized properly

            this.Load += new EventHandler(_Load); //This will be called after the initialization // form_load
            this.Resize += new EventHandler(_Resize); //form_resize
            //

            AllocConsole();
            string filePath = System.IO.Directory.GetCurrentDirectory() + @"\KeyText.txt";

            if (File.Exists(filePath))
            {
                StreamReader sr = new StreamReader(filePath, Encoding.GetEncoding("UTF-8"));

                int i = 0;
                string linetext = "";
                while (sr.Peek() != -1)
                {
                    linetext = sr.ReadLine();
                    i += 1;
                    if (i == 1)
                    {
                        apiKey = linetext;
                    }
                    else if (i == 2)
                    {
                        endpoint = linetext;
                    }
                    Console.WriteLine(linetext);
                }

                sr.Close();

            }
            else
            {
                //Console.WriteLine("ファイルが存在しません");
            }
            textBox2.Text = apiKey;
            textBox3.Text = endpoint;
            textBox10.Text =IMG_DPI.ToString();
            
            File.WriteAllText(System.IO.Directory.GetCurrentDirectory() + @"\Text.txt", "");

        }

        //clsResize _Load 
        private void _Load(object sender, EventArgs e)
        {
            _form_resize._get_initial_size();

        }

        //clsResize _Resize
        private void _Resize(object sender, EventArgs e)
        {
            _form_resize._resize();
        }


        private void Form1_Load(object sender, EventArgs e)
        {

        }

        
        async static Task<string> ToText()
        {
            var client = new DocumentAnalysisClient(new Uri(endpoint), new AzureKeyCredential(apiKey));
            
            var sb = new StringBuilder();

            // F0の制限 2ページ 4MB以下
            var fileStream = File.OpenRead(selectfile);

            var stopRecognition = new TaskCompletionSource<int>();

            // ローカルファイルまたは URL から解析
            var operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, "prebuilt-read", fileStream);
            
            var result = operation.Value;

            foreach (var page in result.Pages)
            {
                foreach (var line in page.Lines)
                {
                    Console.WriteLine(line.Content);
                    sb.Append(line.Content + "\n\r" + "\n\r");
                    File.AppendAllText(System.IO.Directory.GetCurrentDirectory() + @"\Text.txt", line.Content + "\n");

                }
            }

            stopRecognition.TrySetResult(0);

            return sb.ToString();

        }

       
        private void button2_Click_1(object sender, EventArgs e)
        {
            this.Close();
        }

        private async void button1_Click_1(object sender, EventArgs e)
        {
            apiKey = textBox2.Text;
            endpoint = textBox3.Text;
            selectfile = textBox4.Text;
            if (File.Exists(selectfile))
            {
                button1.Enabled = false;

                textBox1.Text = await ToText();

                button1.Enabled = true;
            }
            else
            {
                MessageBox.Show("選択ファイルがありません。", "選択ファイルエラー"); ;
            }
        }

        private void button3_Click_1(object sender, EventArgs e)
        {
            textBox1.Text = "";
        }

        private void button4_Click_1(object sender, EventArgs e)
        {
            //OpenFileDialogクラスのインスタンスを作成
            OpenFileDialog ofd = new OpenFileDialog();

            //はじめのファイル名を指定する
            //はじめに「ファイル名」で表示される文字列を指定する
            ofd.FileName = ""; // "default.pdf";
            //はじめに表示されるフォルダを指定する
            //指定しない(空の文字列)の時は、現在のディレクトリが表示される
            ofd.InitialDirectory = System.Environment.CurrentDirectory + @"\";
            //[ファイルの種類]に表示される選択肢を指定する
            //指定しないとすべてのファイルが表示される
            ofd.Filter = "BMPファイル(*.bmp)|*.bmp|JPEGファイル(*.jpg)|*.jpg|PNGファイル(*.png)|*.png|すべてのファイル(*.*)|*.*";
            //[ファイルの種類]ではじめに選択されるものを指定する
            //2番目の「すべてのファイル」が選択されているようにする
            ofd.FilterIndex = 2;
            //タイトルを設定する
            ofd.Title = "開くファイルを選択してください";
            //ダイアログボックスを閉じる前に現在のディレクトリを復元するようにする
            ofd.RestoreDirectory = true;
            //存在しないファイルの名前が指定されたとき警告を表示する
            //デフォルトでTrueなので指定する必要はない
            ofd.CheckFileExists = true;
            //存在しないパスが指定されたとき警告を表示する
            //デフォルトでTrueなので指定する必要はない
            ofd.CheckPathExists = true;

            //ダイアログを表示する
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                //OKボタンがクリックされたとき、選択されたファイル名を表示する
                Console.WriteLine(ofd.FileName);

                FileInfo file = new FileInfo(ofd.FileName);
                long size = file.Length;
                size = size / 1024;  //KB

                if (size >= 4000)
                {
                    MessageBox.Show("ファイルサイズは、" + size + "KBです。全選択不可です。", "ファイルサイズエラー");
                    pictureBox1.Image = System.Drawing.Image.FromFile(ofd.FileName);
                    textBox4.Text = ofd.FileName;
                    button1.Enabled = false;
                }
                else if (size < 4000)
                {
                    pictureBox1.Image = System.Drawing.Image.FromFile(ofd.FileName);
                    textBox4.Text = ofd.FileName;
                    button1.Enabled = true;
                }

            }
        }

        private void button5_Click(object sender, EventArgs e)
        {

            // LINQを使用して逆順にし、配列に変換して戻す
            textBox1.Lines = textBox1.Lines.Reverse().ToArray();
            // テキストボックスの内容から空行とスペースのみの行を削除
            textBox1.Text = string.Join(Environment.NewLine,
                textBox1.Lines.Where(line => !string.IsNullOrWhiteSpace(line)));

        }
                
        //画像クリック
        private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
        {
            try
            {
                System.Drawing.Image img = pictureBox1.Image;
                Point pos = new Point(0, 0);
                pos.X = e.Location.X * img.Width / pictureBox1.Width;
                pos.Y = e.Location.Y * img.Height / pictureBox1.Height;

                textBox5.Text += textBox5.Text + pos.X + "," + pos.Y + ",";

                string[] xy = textBox5.Text.Split(',');
                if (xy.Length > 4)
                {

                    textBox6.Text = xy[xy.Length - 5];
                    textBox7.Text = xy[xy.Length - 4];
                    textBox8.Text = xy[xy.Length - 3];
                    textBox9.Text = xy[xy.Length - 2];

                    textBox5.Text = xy[xy.Length - 5] + ",";
                    textBox5.Text += xy[xy.Length - 4] + ",";
                    textBox5.Text += xy[xy.Length - 3] + ",";
                    textBox5.Text += xy[xy.Length - 2] + ",";

                }
            }
            catch (Exception)
            {

                ;
            }

        }

        //Form1オブジェクトを取得、設定するためのプロパティ
        public static Form1 Form1Instance
        {
            get
            {
                return _form1Instance;
            }
            set
            {
                _form1Instance = value;
            }
        }
        //TextBox4.Textを取得、設定するためのプロパティ
        public string TextBox4
        {
            get
            {
                return textBox4.Text;
            }
            set
            {
                textBox4.Text = value;
            }
        }
        //TextBox6.Textを取得、設定するためのプロパティ
        public string TextBox6
        {
            get
            {
                return textBox6.Text;
            }
            set
            {
                textBox3.Text = value;
            }
        }
        //TextBox7.Textを取得、設定するためのプロパティ
        public string TextBox7
        {
            get
            {
                return textBox7.Text;
            }
            set
            {
                textBox7.Text = value;
            }
        }
        //TextBox8.Textを取得、設定するためのプロパティ
        public string TextBox8
        {
            get
            {
                return textBox8.Text;
            }
            set
            {
                textBox8.Text = value;
            }
        }
        //TextBox9.Textを取得、設定するためのプロパティ
        public string TextBox9
        {
            get
            {
                return textBox9.Text;
            }
            set
            {
                textBox9.Text = value;
            }
        }

        private async void button6_Click(object sender, EventArgs e)
        {
            
            if (textBox6.Text == "" || textBox7.Text == ""|| textBox8.Text == ""|| textBox9.Text == "")
            {
                MessageBox.Show("画像ポジションエラー。選択不可です。", "画像ポジションエラー");
                return;
            }
            if (Int32.Parse(textBox6.Text) > Int32.Parse(textBox8.Text)|| Int32.Parse(textBox7.Text) > Int32.Parse(textBox9.Text))
            {
                MessageBox.Show("画像ポジションエラー。選択不可です。", "画像ポジションエラー");
                return;
            }

            //元画像
            Bitmap source;
            source = new Bitmap(textBox4.Text);

            //切り取るサイズ
            int x1 = Int32.Parse(textBox6.Text);
            int y1 = Int32.Parse(textBox7.Text);
            int x2 = Int32.Parse(textBox8.Text);
            int y2 = Int32.Parse(textBox9.Text);
            Console.WriteLine(x1 + "," + y1 + "," + x2 + "," + y2);
            System.Drawing.Rectangle rect;
            rect = new System.Drawing.Rectangle(x1, y1, x2 - x1 + 5, y2 - y1 + 5);

            //切り取り後の画像
            Bitmap trimed;
            trimed = source.Clone(rect, source.PixelFormat);

            //保存
            trimed.Save("trimed.jpg");

            source.Dispose();
            trimed.Dispose();

            string ImagePath = System.Environment.CurrentDirectory + @"\trimed.jpg";
            FileInfo file = new FileInfo(ImagePath);
            long size = file.Length;
            size = size / 1024;  //KB

            if (size >= 4000)
            {
                MessageBox.Show("ファイルサイズは、" + size + "KBです。選択不可です。", "ファイルサイズエラー");
                return;
            }

            apiKey = textBox2.Text;
            endpoint = textBox3.Text;
            selectfile = ImagePath;
            button6.Enabled = false;

            textBox1.Text += await ToText();

            button6.Enabled = true;
        }
               
        private void label6_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.ShowDialog(this);
            form2.Dispose();

        }

        //PdfToImage
        private void button7_Click(object sender, EventArgs e)
        {
            
            //解像度設定
            try
            {
                IMG_DPI = int.Parse(textBox10.Text);
            }
            catch (Exception)
            {
                IMG_DPI = 300;
            }
           
            //OpenFileDialogクラスのインスタンスを作成
            OpenFileDialog ofd = new OpenFileDialog();

            //はじめのファイル名を指定する
            //はじめに「ファイル名」で表示される文字列を指定する
            ofd.FileName = "default.pdf";
            //はじめに表示されるフォルダを指定する
            //指定しない(空の文字列)の時は、現在のディレクトリが表示される
            ofd.InitialDirectory = System.Environment.CurrentDirectory + @"\";
            //[ファイルの種類]に表示される選択肢を指定する
            //指定しないとすべてのファイルが表示される
            ofd.Filter = "PDFファイル(*.pdf)|*.pdf|すべてのファイル(*.*)|*.*";
            //[ファイルの種類]ではじめに選択されるものを指定する
            //2番目の「すべてのファイル」が選択されているようにする
            ofd.FilterIndex = 1;
            //タイトルを設定する
            ofd.Title = "開くファイルを選択してください";
            //ダイアログボックスを閉じる前に現在のディレクトリを復元するようにする
            ofd.RestoreDirectory = true;
            //存在しないファイルの名前が指定されたとき警告を表示する
            //デフォルトでTrueなので指定する必要はない
            ofd.CheckFileExists = true;
            //存在しないパスが指定されたとき警告を表示する
            //デフォルトでTrueなので指定する必要はない
            ofd.CheckPathExists = true;

            //ダイアログを表示する
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                
                //OKボタンがクリックされたとき、選択されたファイル名を表示する
                Console.WriteLine(ofd.FileName);

                
                string pdfpath  = System.IO.Path.GetDirectoryName(ofd.FileName);
                string pdfname = System.IO.Path.GetFileNameWithoutExtension(ofd.FileName);
                //Create a PdfDocument instance
                PdfDocument pdf = new PdfDocument();

                //Load a sample PDF document
                pdf.LoadFromFile(ofd.FileName);

                /*
                //Convert the first page to an image and set the image Dpi
                Image image = pdf.SaveAsImage(0, PdfImageType.Bitmap, 300, 300);

                //Save the image as a JPG file
                image.Save(pdfpath + "\\" + pdfname + ".jpg", ImageFormat.Jpeg);
                */

                //Loop through each page in the PDF
                for (int i = 0; i < pdf.Pages.Count; i++)
                {
                    //Convert all pages to images and set the image Dpi
                    Image image = pdf.SaveAsImage(i, PdfImageType.Bitmap, IMG_DPI,IMG_DPI);

                    //Save images as PNG format to a specified folder
                    String file = String.Format(pdfpath + "\\" + pdfname + "-{0}.jpg", i);
                    image.Save(file, ImageFormat.Jpeg);

                }
            }
        }
        
        /*
        private async void buttonX_Click(object sender, EventArgs e)
        {
            apiKey = textBox2.Text;
            endpoint = textBox3.Text;
            selectfile = textBox4.Text;
            button1.Enabled = false;

            textBox1.Text = await ToText2();

            button1.Enabled = true;
        }
        async static Task<string> ToText2()
        {            
            var client = new DocumentIntelligenceClient(new Uri(endpoint), new AzureKeyCredential(apiKey));

            var sb = new StringBuilder();

            // F0の制限 2ページ 4MB以下
            var fileStream = File.OpenRead(selectfile);
            var file = new FileInfo(selectfile);
            var fileUri = new Uri(file.FullName);
            Console.WriteLine(fileUri);

            var stopRecognition = new TaskCompletionSource<int>();
                       
            // Use the "prebuilt-read" or "prebuilt-layout" model
            string modelId = "prebuilt-read";
                     
            // Start the analysis
            var operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, modelId,fileUri);
            Azure.AI.DocumentIntelligence.AnalyzeResult result = operation.Value;

            // Iterate through pages and lines
            foreach (var page in result.Pages)
            {
                foreach (var line in page.Lines)
                {
                    // For RTL languages, the 'Content' string is already ordered RTL
                    Console.WriteLine($"Detected text: {line.Content}");

                    stopRecognition.TrySetResult(0);
                }
            }
            return sb.ToString();

        }
        */
    }
}

Form2.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ImageToTextAz
{
    public partial class Form2 : Form
    {
        //control clsResize 画面表示を拡大縮小します。
        clsResize _form_resize;

        public Form2()
        {
            InitializeComponent();


            //clsResize
            _form_resize = new clsResize(this); //I put this after the initialize event to be sure that all controls are initialized properly

            this.Load += new EventHandler(_Load); //This will be called after the initialization // form_load
            this.Resize += new EventHandler(_Resize); //form_resize
            //

            //元画像
            Bitmap source;
            source = new Bitmap(Form1.Form1Instance.TextBox4);

            //切り取るサイズ
            int x1 = Int32.Parse(Form1.Form1Instance.TextBox6);
            int y1 = Int32.Parse(Form1.Form1Instance.TextBox7);
            int x2 = Int32.Parse(Form1.Form1Instance.TextBox8);
            int y2 = Int32.Parse(Form1.Form1Instance.TextBox9);

            Rectangle rect;
            rect = new Rectangle(x1, y1, x2 - x1 + 5, y2 - y1 + 5);

            //切り取り後の画像
            Bitmap trimed;
            trimed = source.Clone(rect, source.PixelFormat);

            //画像を表示する
            pictureBox1.Image = trimed;

        }

        //clsResize _Load 
        private void _Load(object sender, EventArgs e)
        {
            _form_resize._get_initial_size();

        }

        //clsResize _Resize
        private void _Resize(object sender, EventArgs e)
        {
            _form_resize._resize();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.Close();
        }

    }
}

clsResize.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

public class clsResize
{
    List<System.Drawing.Rectangle> _arr_control_storage = new List<System.Drawing.Rectangle>();
    private bool showRowHeader = false;
    public clsResize(Form _form_)
    {
        form = _form_; //the calling form
        _formSize = _form_.ClientSize; //Save initial form size
        _fontsize = _form_.Font.Size; //Font size

        //ADD
        var _controls = _get_all_controls(form);//call the enumerator
        FontTable = new Dictionary<string, float>();
        ControlTable = new Dictionary<string, System.Drawing.Rectangle>();
        foreach (Control control in _controls) //Loop through the controls
        {
            FontTable.Add(control.Name, control.Font.Size);
            ControlTable.Add(control.Name, control.Bounds);
        }
        //ADD

    }

    //ADD
    Dictionary<string, float> FontTable;
    Dictionary<string, System.Drawing.Rectangle> ControlTable;
    //ADD

    private float _fontsize { get; set; }

    private System.Drawing.SizeF _formSize { get; set; }

    private Form form { get; set; }

    public void _get_initial_size() //get initial size//
    {
        var _controls = _get_all_controls(form);//call the enumerator
        foreach (Control control in _controls) //Loop through the controls
        {
            _arr_control_storage.Add(control.Bounds); //saves control bounds/dimension            
            //If you have datagridview
            if (control.GetType() == typeof(DataGridView))
                _dgv_Column_Adjust(((DataGridView)control), showRowHeader);
        }
    }

    public void _resize() //Set the resize
    {
        double _form_ratio_width = (double)form.ClientSize.Width / (double)_formSize.Width; //ratio could be greater or less than 1
        double _form_ratio_height = (double)form.ClientSize.Height / (double)_formSize.Height; // this one too
        var _controls = _get_all_controls(form); //reenumerate the control collection
        int _pos = -1;//do not change this value unless you know what you are doing
        foreach (Control control in _controls)
        {

            //ADD
            this._fontsize = FontTable[control.Name]; //<-取得したコントロールのフォントサイズ値で上書きするためにこれを追加
            //ADD

            // do some math calc
            _pos += 1;//increment by 1;
            System.Drawing.Size _controlSize = new System.Drawing.Size((int)(_arr_control_storage[_pos].Width * _form_ratio_width),
                (int)(_arr_control_storage[_pos].Height * _form_ratio_height)); //use for sizing

            System.Drawing.Point _controlposition = new System.Drawing.Point((int)
            (_arr_control_storage[_pos].X * _form_ratio_width), (int)(_arr_control_storage[_pos].Y * _form_ratio_height));//use for location

            //set bounds
            control.Bounds = new System.Drawing.Rectangle(_controlposition, _controlSize); //Put together

            //Assuming you have a datagridview inside a form()
            //if you want to show the row header, replace the false statement of 
            //showRowHeader on top/public declaration to true;
            if (control.GetType() == typeof(DataGridView))
                _dgv_Column_Adjust(((DataGridView)control), showRowHeader);


            //Font AutoSize
            control.Font = new System.Drawing.Font(form.Font.FontFamily,
             (float)(((Convert.ToDouble(_fontsize) * _form_ratio_width) / 2) +
              ((Convert.ToDouble(_fontsize) * _form_ratio_height) / 2)));

        }
    }

    private void _dgv_Column_Adjust(DataGridView dgv, bool _showRowHeader) //if you have Datagridview 
    //and want to resize the column base on its dimension.
    {
        int intRowHeader = 0;
        const int Hscrollbarwidth = 5;
        if (_showRowHeader)
            intRowHeader = dgv.RowHeadersWidth;
        else
            dgv.RowHeadersVisible = false;

        for (int i = 0; i < dgv.ColumnCount; i++)
        {
            if (dgv.Dock == DockStyle.Fill) //in case the datagridview is docked
                dgv.Columns[i].Width = ((dgv.Width - intRowHeader) / dgv.ColumnCount);
            else
                dgv.Columns[i].Width = ((dgv.Width - intRowHeader - Hscrollbarwidth) / dgv.ColumnCount);
        }
    }




    private static IEnumerable<Control> _get_all_controls(Control c)
    {
        return c.Controls.Cast<Control>().SelectMany(item =>
            _get_all_controls(item)).Concat(c.Controls.Cast<Control>()).Where(control =>
            control.Name != string.Empty);
    }
}

-windows

PAGE TOP