# อ่านลายมือจากรูปเป็นตัวอักษร (OCR)

![](/files/-M1lfxiObTWyIy8COEG7)

ในรอบนี้เราจะลองเขียนโค้ดให้มัน**แปลงข้อความที่อยู่ในรูปให้ออกมาเป็นตัวหนังสือ** หรือที่เราเรียกกันติดปากว่า **`OCR`** `Optical Character Recognition` ดูบ้างนะ ซึ่งการที่จะทำแบบนี้ได้ผมจะใช้ AI สำเร็จรูปของ Microsoft Azure ที่ชื่อว่า **Cognitive Services** ครับ

{% hint style="success" %}
**แนะนำให้อ่าน**\
บทความนี้เป็นหนึ่งในซีรี่ AI ดังนั้นถ้าเพื่อนสนใจของสนุกๆ เช่น [**Login ด้วยใบหน้า**](https://saladpuk.gitbook.io/learn/cloud/azure-cognitive-services/faceauth) หรือ **ยืนยันตัวตนด้วยเสียง** [**แปลงภาพเป็นข้อความ**](https://saladpuk.gitbook.io/learn/cloud/azure-cognitive-services/ocr) และอื่นๆ สามารถดูเนื้อหาทั้งหมดได้จาก side menu ในหมวดของ **Cognitive Services** ครับ กำลังทำเรื่อยๆอยู่ ส่วนถ้าอยากรู้ว่า AI สำเร็จรูปตัวอื่นๆของ Microsoft Azure มีอะไรน่าเล่นบ้าง ไปอ่านกันได้จากลิงค์นี้เลยครัช [👶 Azure Cognitive Services](https://saladpuk.gitbook.io/learn/cloud/azure-cognitive-services) เชื่อผมเต๊อะ AI ไม่ได้ยากแบบที่คิด
{% endhint %}

\*\*\*\*

## 😗 ทำความเข้าใจกันก่อน

ตัวโปรแกรมของเราจะทำการส่งรูปไปให้ AI ดู แล้วเจ้า AI จะส่งกลับมาว่าข้อความในรูปมันเขียนว่าอะไรบ้าง ซึ่งตัวอย่างนี้ผมจะไม่ทำ UI เลยเพราะเน้นไปที่เรื่องการใช้ AI อย่างเดียวเท่านั้นครับ

ตัวอย่างนี้ผมจะใช้ภาษา C# เขียน ดังนั้นใครที่จะทำตามด้วย C# ให้ลง `Visual Studio Code` และ `.NET Core SDK` ในลิงค์ด้านล่างด้วยถ้ายังไม่มี **ส่วนภาษาอื่นๆก็สามารถทำตามได้เหมือนกัน** เพราะขั้นตอนทั้งหมดเราเรียกใช้ **REST API** เพียงอย่างเดียวเลยครับ

* [Download Visual Studio Code](https://code.visualstudio.com/)
* [Download .NET Core SDK](https://dotnet.microsoft.com/download)

## 🤔 เริ่มยังไงดี ?

ก่อนที่จะเริ่มทำอะไรผมอยากให้เข้าใจตรงกันก่อนว่า ในตัวอย่างนี้เราจะต้องทำอะไรกันบ้างตามนี้เลย

1. ขั้นตอนแรกเราต้องสร้าง **Cognitive Services** เสียก่อน เพื่อที่จะใช้งาน AI สำเร็จรูปได้
2. เข้าไปใน Cognitive Services ที่สร้างไว้ เพื่อ**เอา Key กับ Endpoint มา** ซึ่งเจ้าสองตัวนี้จะเป็นเหมือนรหัสลับในการเข้าใช้งาน AI ของเรานั่นเอง
3. เขียนโค้ดเพื่อเรียกใช้งาน Cognitive Services ในขั้นตอนนี้เราจะต้องส่งรหัสลับเพื่อยืนยันว่าเราสามารถใช้งาน AI ตัวนี้ได้
4. ส่งรูปให้ AI อ่านข้อความกลับมาก็เป็นอันจบ

## 🔥 (1) สร้าง Cognitive Services กัน

{% hint style="info" %}
**Azure Portal**\
เนื้อหาตรงจุดนี้จะต้องเข้าไปที่ทำที่เว็บ <https://portal.azure.com> นี้นะครับ ซึ่งเราต้องสมัครสมาชิกก่อน แต่ถ้าใครยังไม่ได้สมัครก็ไปสมัครให้เรียบร้อยแซ๊ร [(วิธีสมัครจิ้มตรงนี้)](https://saladpuk.gitbook.io/learn/cloud/azure101/register)
{% endhint %}

1.หลังจากที่ Login เข้ามาละ ที่เมนูด้านซ้ายมือให้กดที่ **`+ Create a resource`** ซะ ส่วนช่องค้นหาให้พิมพ์คำว่า **`Cognitive Services`** ลงไปแล้วกด Enter ได้เบย

![](/files/-LoEZFYPD1FRwHTzbiiH)

2.ถัดมาเขาก็จะบอกรายละเอียดเกี่ยวกับ Cognitive Services ว่ามันคืออะไร จะไปศึกษาลองเล่นต่อได้ยังไง ราคาที่ต้องจ่ายต่อเดือนคิดยังไง บลาๆ ก็ถ้าอ่านจนหนำใจแล้วก็จิ้มปุ่ม **Create** เบาๆไป 1 ทีงับ

![](/files/-LoEZeo_KZ7mRWKqQem5)

3.ถัดมาก็ใส่รายละเอียดของ Cognitive Services ให้เรียบร้อยซะ แล้วก็กดปุ่ม **`Create`** ได้เลย

| ชื่อ | รายละเอียด |
| ---- | ---------- |

| **Name** | ชื่อ Cognitive Services ที่จะสร้าง |
| -------- | ---------------------------------- |

| **Location** | <p>ตัว service นี้จะสร้างไว้ภูมิภาคไหน</p><p>ในตัวอย่างผมเล่นในไทยก็เลือกเป็น Southeast Asia</p> |
| ------------ | ------------------------------------------------------------------------------------------------ |

| **Pricing tier** | <p>จะให้เขาเก็บเงินเราแบบไหน ในตอนนี้ยังไม่มีตัวฟรีให้เล่น</p><p>แต่ถ้าเราลองเสร็จแล้วลบเลยสิ้นเดือนก็จ่ายไม่ถึง 1 บาทครับ</p> |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------ |

| **Resource group** | <p>จะสร้าง service นี้ไว้ใน Resource Group ไหน</p><p>ถ้ายังไม่มีให้กดปุ่ม <strong><code>Create new</code></strong> เลยก็ได้ครับ</p> |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |

3.เรียบร้อยครับ ที่เหลือก็แค่รอให้มันสร้าง Cognitive Services จนเสร็จ

![](/files/-LnNDWdnC_ChnvlxLvlE)

## 🔥 (2) เอา Key กับ Endpoint กัน

โดยปรกติเวลาที่เราจะเรียกใช้ **REST API** ของ Cognitive Services เราจะต้องส่งรหัสลับเพื่อยืนยันว่าเราเป็นคนที่มีสิทธิ์ในการใช้งาน AI ตัวนี้จริงๆนะ ซึ่งเจ้ารหัสลับก็คือ **Key** นั่นเอง ส่วนเจ้า **Endpoint** ก็คือตัว API ที่เราจะเรียกไป ดังนั้นหลังจากทำขั้นตอนที่ 1 เสร็จแล้ว เราก็ไปเอาของพวกนั้นกันเลย

1.ที่เมนูด้านซ้ายให้กด **`Resource groups`** แล้วเขาเลือก Resource group ที่เราสร้างไว้จากขั้นตอนที่ 1 ครับ

![](/files/-LoEby2fCVLIWSclLcBM)

2.พอเข้ามาใน Resource group แล้วถัดไปเราก็จะเห็น **`Cognitive Services`** ที่เราสร้างไว้ ให้จิ้มมันอย่างอ่อนโยน

![](/files/-M0hyjzVev285ifWKpx1)

3.พอเข้ามาเราก็จะเห็น **`Key`** กับ **`Endpoint`** ที่เราตามหาเลย แล้วทำการกด copy ทั้ง 2 ตัวไปเก็บไว้ก่อนครับ

![](/files/-LoEdUxm4rUMaGaNEHSm)

## 🔥 (3) เขียนโค้ดกัน

ในขั้นตอนนี้ผมจะสร้างโปรเจคของ C# ขึ้นมา เพื่อเขียนโค้ดในการสร้างเรียกใช้ Cognitive Services ล่ะนะ ดังนั้นขอแบ่งเป็นหัวข้อย่อยๆนิดหน่อย

### 2.1.สร้างโปรเจค

เริ่มต้นก็เปิด command prompt หรือ terminal ขึ้นมาเลย แล้วใช้คำสั่งด้านล่างในการสร้างโปรเจคได้เลย

```
dotnet new console -n saladpuk-handwritten-text
```

> `saladpuk-handwritten-text` คือชื่อโปรเจคนะครับ อยากได้ชื่ออื่นก็เปลี่ยนได้เลย

ตอนนี้เราก็จะได้โปรเจคมา 1 ตัวละ ถัดไปก็เข้าไปที่โปรเจคนั้นครับด้วยคำสั่งด้านล่างนี้ (ใครที่เปลี่ยนชื่อโปรเจคก็ใส่ชื่อเป็นชื่อโปรเจคที่ตัวเองตั้งไว้นะ)

```
cd saladpuk-handwritten-text
```

ในตัวอย่างนี้การที่เราจะเรียกใช้ Cognitive Service เราจะต้องทำงานผ่าน REST API ธรรมดานี่แหละ ดังนั้นเพื่อความง่ายผมจะลง library เสริม 2 ตัวเพื่อให้ทำงานกับ REST API และ Json ได้ง่ายขึ้นครับ โดยใช้คำสั่งด้านล่างก็เป็นอันเสร็จสิ้นพิธี

```
dotnet add package RestSharp --version 106.6.10
dotnet add package Newtonsoft.Json
```

ทดสอบว่าโปรเจคไม่มีปัญหาอะไรด้วยคำสั่งด้านล่าง

```
dotnet build
```

ซึ่งถ้าไม่มีปัญหาอะไรก็น่าจะได้ผลลัพท์ออกมาแบบนี้

```
Build succeeded.
    0 Warning(s)
    0 Error(s)
```

คราวนี้ให้เราเปิด **Visual Studio Code** ขึ้นมา โดยใช้คำสั่ง `code .` ภายใน command prompt หรือ terminal หรือจะเปิด Visual Studio Code แล้วเปิด folder มาที่ตัวโปรเจคนี้ก็ได้เหมือนกัน

หลังจากที่ Visual Studio Code เปิดขึ้นมาแล้ว ให้ทำการเปิดไฟล์ `Program.cs` ขึ้นมารอเลยครับ

![](/files/-LoBgFycPKLXxAQ3yDhG)

{% hint style="info" %}
**Visual Studio Code: C# Extension**\
ในตัวอย่างที่เป็นสีสวยงาม เพราะผมลง extension 2 ตัวให้กับ Visual Studio Code นะครับ ถ้าสนใจก็กดติดตั้งได้จากลิงค์ด้านล่างเลย

* [C#](https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp)
* [C# Extensions](https://marketplace.visualstudio.com/items?itemName=jchannon.csharpextensions)
  {% endhint %}

### 2.2.เขียนโค้ดติดต่อ Cognitive Services

ตอนนี้ให้เอาโค้ดด้านล่างไปทับใน `Program.cs` ทั้งหมดเลย ซึ่งเจ้าโค้ดด้านล่างจะเป็นแค่โครงคร่าวๆเท่านั้น

{% code title="Program.cs" %}

```csharp
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using Newtonsoft.Json;
using RestSharp;

namespace saladpuk_handwritten_text
{
    class Program
    {
        static string SubscriptionKey = "FACE_SUBSCRIPTION_KEY";
        static string Endpoint = "FACE_ENDPOINT";

        static void Main(string[] args)
        {
            var client = new RestClient(Endpoint);

            // เขียนโค้ดต่อที่นี่
        }

        static RestRequest CreateRestRequest(string resource, object requestBody)
        {
            var request = new RestRequest(resource);
            request.AddHeader("ocp-apim-subscription-key", SubscriptionKey);
            if (requestBody != null)
            {
                request.AddHeader("content-type", "application/json");
                request.AddJsonBody(requestBody);
            }
            return request;
        }
    }
}
```

{% endcode %}

จากโค้ดด้านบนเราจะต้องเอา `Key` กับ `Endpoint` ที่ได้มาจากขั้นตอนที่ 2 เอามาใส่ไว้ในบรรทัดที่ 13 กับ 14 เพื่อเตรียมให้เราสามารถเรียก Cognitive Services ได้นั่นเอง ดังนั้นก็ใส่ลงไปครับ

{% code title="Program.cs" %}

```csharp
static string SubscriptionKey = "be6b8fd9fe2a48b5a050f1016b571170";
static string Endpoint = "https://southeastasia.api.cognitive.microsoft.com/";
```

{% endcode %}

{% hint style="danger" %}
**คำเตือน**\
ถ้าใช้ **Key** กับ **Endpoint** จากตัวอย่างของผมมันจะทำงานไม่ได้นะครับ เพราะผมลบของพวกนี้ไปแล้ว ให้ไปสร้างมาเล่นเองนะ
{% endhint %}

## 🔥 (4) ส่งรูปให้ AI เปลี่ยนเป็น Text

ถัดมาเราก็จะส่งรูปภาพของเราไปให้กับ **Cognitive Services API** แล้วนะครับ โดยรูปที่จะส่งไปคือรูปนี้

![](/files/-LwnNe0-Uwgry8a0Ne6w)

คราวนี้ API ที่เราต้องใช้ตัวแรกคือนี้ครัช

```javascript
POST https://southeastasia.api.cognitive.microsoft.com/vision/v2.1/read/core/asyncBatchAnalyze HTTP/1.1
Host: southeastasia.api.cognitive.microsoft.com
Content-Type: application/json
Ocp-Apim-Subscription-Key: ••••

{"url":"https://jooinn.com/images/handwritten-text-1.jpg"}
```

ดังนั้นเราก็ลงมือแก้โค้ด C# กันเบย ก็จะได้โค้ดออกมาหน้าตาราวๆนี้

{% code title="Program.cs" %}

```csharp
static void Main(string[] args)
{
    var client = new RestClient(Endpoint);

    // เรียกใช้ Batch Read File
    Console.WriteLine("Running Batch read file.");
    var operationlocation = string.Empty;
    var batchReadFileRequest = CreateRestRequest("vision/v2.1/read/core/asyncBatchAnalyze", new
    {
        url = "https://jooinn.com/images/handwritten-text-1.jpg"
    });
    var batchReadFileResult = client.Execute(batchReadFileRequest, Method.POST);
    if (batchReadFileResult.StatusCode == HttpStatusCode.Accepted)
    {
        var operationlocationUrl = batchReadFileResult.Headers.FirstOrDefault(it => it.Name == "Operation-Location").Value.ToString();
        operationlocation = Path.GetFileName(operationlocationUrl);
        Console.WriteLine($"-> Done. Operation-Location: {operationlocation}");
    }
    else
    {
        Console.WriteLine($"Error: {batchReadFileResult.Content}");
        return;
    }

    // โค้ดตัวต่อไปเอามาใส่ตรงนี้
}
```

{% endcode %}

จากโค้ดด้านบนมันก็จะเรียก REST API ไปตามที่ผมได้บอกไป ซึ่งสิ่งที่เราจะได้กลับมามันจะอยู่ใน Header ที่ชื่อ **`Operation-Location`** นะครับมีหน้าตาตามด้านล่างเลย ดังนั้นโค้ดเราก็จะอ่านค่า header แล้วเอามาเก็บไว้ในตัวแปรที่ชื่อ `operationlocation` ที่อยู่ในโค้ดด้านบนตรงบรรทัดที่ 16 ครับ

```
Pragma: no-cache
Operation-Location: https://southeastasia.api.cognitive.microsoft.com/vision/v2.1/read/operations/dcb2e8df-a7d6-4527-b656-c3f6c87d53bc
apim-request-id: 523b53fb-aef3-41c9-9a66-de29313cda86
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
x-content-type-options: nosniff
Cache-Control: no-cache
Date: Sun, 08 Sep 2019 10:07:04 GMT
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 0
Expires: -1
```

ถัดไปเราก็จะไปเอาผลลัพท์ของเรากลับมาครับ ว่าเจ้ารู้ที่ส่งไปให้มันมีตัวหนังสืออะไรอยู่ในนั้นบ้าง ด้วยการเรียก API ตัวนี้ครับ

```javascript
GET https://southeastasia.api.cognitive.microsoft.com/vision/v2.1/read/operations/{operationId} HTTP/1.1
Host: southeastasia.api.cognitive.microsoft.com
Ocp-Apim-Subscription-Key: ••••
```

ซึ่งเจ้า API ตัวนี้ เราจะต้องส่ง **`OperationId`** ที่ได้จากขั้นตอนก่อนหน้าไปให้มันด้วยครับ ดังนั้นผมก็จะเพิ่มโค้ดตัวนี้เข้าไป

{% code title="Program.cs" %}

```csharp
static void Main(string[] args)
{
    ...

    // เรียกใช้ Get Read Operation Result
    Console.WriteLine("Running Get read operation result.");
    while (true)
    {
        var getReadOperationRequest = CreateRestRequest($"vision/v2.1/read/operations/{operationlocation}", null);
        var getReadOperationResult = client.Execute(getReadOperationRequest, Method.GET);
        if (getReadOperationResult.StatusCode == HttpStatusCode.OK)
        {
            const string Succeeded = "Succeeded";
            var result = JsonConvert.DeserializeObject<ReadOperationResultInfo>(getReadOperationResult.Content);
            if (result.Status == Succeeded)
            {
                var linesQry = result.RecognitionResults.SelectMany(it => it.Lines).Select(it => it.Text);
                var message = string.Join(Environment.NewLine, linesQry);
                Console.WriteLine($"-> Done. the message is{Environment.NewLine}{message}");
                break;
            }
        }
        else
        {
            Console.WriteLine($"Incomplete or error, retrying in 1 second.");
            System.Threading.Thread.Sleep(1000);
        }
    }
}

class ReadOperationResultInfo
{
    public string Status { get; set; }
    public IEnumerable<RecognitionInfo> RecognitionResults { get; set; }
}
class RecognitionInfo
{
    public IEnumerable<LineInfo> Lines { get; set; }
}
class LineInfo
{
    public string Text { get; set; }
}
```

{% endcode %}

เจ้า API ตัวนี้มันจะตอบผลลัพท์ข้อความที่มันอ่านจากรูปกลับมาเป็น Json array ยาวๆแยกตามแต่ละบรรทัดเลยครับ เลยทำให้ผมต้องสร้าง model ในบรรทัดที่ 31-43 มารับมันไม่งั้นโค้ดจะอ่านยากครับ และเจ้า API ตัวนนี้บางทีมันก็อาจจะยังวิเคราะห์รูปไม่เสร็จ เราเลยต้องเขียนติด loop เพื่อหน่วงเวลามันนิดหน่อยครับ ในบรรทัดที่ 7-28

แล้วเราก็ลอง Run โปรแกรมโดยการกด `CTRL + F5` หรือจะใช้คำสั่ง `dotnet run` ใน command prompt หรือ terminal ก็ได้ครับ แล้วเราก็จะเห็นผลลัพท์ตามนี้

```
Running Batch read file.
-> Done. Operation-Location: dbb17070-009a-48fc-8abd-744e75fc9ba0
Running Get read operation result.
-> Done. the message is
We Start With Good
Because all businesses should
be doing something
good.
```

ผลลัพท์อยู่บรรทัดที่ 5-8 ไหนลองเอามาเทียบกับในรูปดูดิ๊

![](/files/-LwnNe0-Uwgry8a0Ne6w)

ตรงกันหมด ก็เป็นอันเรียบร้อยแล้วครับ

## 🤔 ยาวจังของโค้ดทั้งหมดหน่อย

พอดีเนื้อหาค่อนข้างยาวดังนั้นผมขอยก source code ให้ไปดาวโหลดมาลองเล่นเลยดีกว่าครับ

{% file src="/files/-LoFOJYgCmYshuifQhVO" %}
Source code: OCR
{% endfile %}

## 🎯 บทสรุป

ในการทำงานกับ AI จริงๆไม่ใช่เรื่องยากเลยหัวใจหลักของมันจริงๆก็คือการเรียกใช้ **REST API** ให้ถูกตัวเท่านั้น ดังนั้นไม่ว่าเราจะเขียนภาษาไหนก็ตาม เราก็สามารถเรียกใช้ **Cognitive Services** เพื่อทำของประมาณนี้ได้เลย

{% hint style="success" %}
**Cognitive Services API**\
หากใครสนใจอยากดู API ทั้งหมดที่ Microsoft เตรียมไว้ให้เราเรียกใช้ AI สำเร็จรูป ก็สามารถเข้าไปดูได้จากลิงค์ด้านล่างนี้เลยครับ

* [Microsoft Cognitive Services: Computer Vision v.2.1](https://southeastasia.dev.cognitive.microsoft.com/docs/services/5cd27ec07268f6c679a3e641/operations/56f91f2e778daf14a499f21b)
* [Microsoft Cognitive Services APIs](https://southeastasia.dev.cognitive.microsoft.com/docs/services/)
  {% endhint %}

{% hint style="success" %}
**Cognitive Services Library**\
สำหรับคนที่ต้องการเขียนทำงานกับ Cognitive Services จริงๆไม่ต้องไปนั่งเขียนเชื่อม API ทีละตัวก็ได้นะ เพราะทาง Microsoft นั้นได้มี Library ให้เราสามารถเรียกใช้ได้เลยครับ เช่นในฝั่ง .NET ก็จะมีตัวนี้ **Microsoft.Azure.CognitiveServices.Vision.ComputerVision** ที่สามารถติดตั้งแล้วใช้งานได้เลย
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.saladpuk.com/cloud/azure-cognitive-services/ocr.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
