windows

PDFファイルからテキスト化(Azure)C#

PDFファイルからテキスト化(Azure)C#

PDFファイルを Azure Document Intelligence を利用してテキスト化しました。OCR処理後、テキストボックスに表示されます。アプリの実行フォルダーにテキストデータ(ファイル名は、TEXT )が作成されます。契約形態がフリー(F0)の場合は、ファイルサイズ4MB未満、総ページ数の2ページ目迄です。

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# プロジェクト。
    • Microsoft.CognitiveServices.Speech NuGet パッケージをインストールします。NuGet パッケージ マネージャー コンソールからインストールできます。

Form1

Azure.AI.FormRecognizer を導入。

Form1.cs

using Azure;
using Azure.AI.FormRecognizer.DocumentAnalysis;
using PdfiumViewer;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace PdfToTextAz
{
       
    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 = "";

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool AllocConsole();

        public Form1()
        {
            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
            //

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

            if (File.Exists(filePath))
            {
                StreamReader sr = new StreamReader(filePath, Encoding.GetEncoding("Shift_JIS"));
                
                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;

            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 button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }

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

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

            //はじめのファイル名を指定する
            //はじめに「ファイル名」で表示される文字列を指定する
            ofd.FileName = "default.pdf";
            //はじめに表示されるフォルダを指定する
            //指定しない(空の文字列)の時は、現在のディレクトリが表示される
            ofd.InitialDirectory = System.Environment.CurrentDirectory + @"\";
            //[ファイルの種類]に表示される選択肢を指定する
            //指定しないとすべてのファイルが表示される
            ofd.Filter = "PDFファイル(*.pdf)|*.pdf|JPEGファイル(*.jpg)|*.jpg|すべてのファイル(*.*)|*.*";
            //[ファイルの種類]ではじめに選択されるものを指定する
            //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);
                             
                FileInfo file = new FileInfo(ofd.FileName);
                long size = file.Length;
                size = size / 1024 ;  //KB
                
                if (size >= 4000)
                {
                    MessageBox.Show("ファイルサイズは、" + size + "KBです。選択不可です。", "ファイルサイズエラー");
                }else if (size < 4000)
                {
                    webView21.Source = new Uri(ofd.FileName);
                    textBox4.Text = ofd.FileName;
                }
                
            }

        }
        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 async void button1_Click(object sender, EventArgs e)
        {
            apiKey = textBox2.Text;
            endpoint = textBox3.Text;
            selectfile = textBox4.Text;
            button1.Enabled = false;

            textBox1.Text = await ToText();

            button1.Enabled = true;


        }
    }
}

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