Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
406 lines (313 sloc) 26.4 KB
description
เขียนแอพถ่ายรูปแล้วแปลงเป็นข้อความกัน ใช้ได้ทุกภาษา

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

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

{% hint style="success" %} แนะนำให้อ่าน
บทความนี้เป็นหนึ่งในซีรี่ AI ดังนั้นถ้าเพื่อนสนใจของสนุกๆ เช่น Login ด้วยใบหน้า หรือ ยืนยันตัวตนด้วยเสียง แปลงภาพเป็นข้อความ และอื่นๆ สามารถดูเนื้อหาทั้งหมดได้จาก side menu ในหมวดของ Cognitive Services ครับ กำลังทำเรื่อยๆอยู่ ส่วนถ้าอยากรู้ว่า AI สำเร็จรูปตัวอื่นๆของ Microsoft Azure มีอะไรน่าเล่นบ้าง ไปอ่านกันได้จากลิงค์นี้เลยครัช 👶 Azure Cognitive Services เชื่อผมเต๊อะ AI ไม่ได้ยากแบบที่คิด {% endhint %}

****

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

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

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

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

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

  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 นี้นะครับ ซึ่งเราต้องสมัครสมาชิกก่อน แต่ถ้าใครยังไม่ได้สมัครก็ไปสมัครให้เรียบร้อยแซ๊ร (วิธีสมัครจิ้มตรงนี้) {% endhint %}

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

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

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

ชื่อ รายละเอียด
Name ชื่อ Cognitive Services ที่จะสร้าง
Location

ตัว service นี้จะสร้างไว้ภูมิภาคไหน

ในตัวอย่างผมเล่นในไทยก็เลือกเป็น Southeast Asia

Pricing tier

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

แต่ถ้าเราลองเสร็จแล้วลบเลยสิ้นเดือนก็จ่ายไม่ถึง 1 บาทครับ

Resource group

จะสร้าง service นี้ไว้ใน Resource Group ไหน

ถ้ายังไม่มีให้กดปุ่ม Create new เลยก็ได้ครับ

![](../../.gitbook/assets/image%20%2855%29.png)

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

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

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

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

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

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

🔥 (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 ขึ้นมารอเลยครับ

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

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

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

{% code-tabs %} {% code-tabs-item title="Program.cs" %}

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-tabs-item %} {% endcode-tabs %}

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

{% code-tabs %} {% code-tabs-item title="Program.cs" %}

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

{% endcode-tabs-item %} {% endcode-tabs %}

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

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

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

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

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-tabs %} {% code-tabs-item title="Program.cs" %}

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-tabs-item %} {% endcode-tabs %}

จากโค้ดด้านบนมันก็จะเรียก 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 ตัวนี้ครับ

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-tabs %} {% code-tabs-item title="Program.cs" %}

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-tabs-item %} {% endcode-tabs %}

เจ้า 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 ไหนลองเอามาเทียบกับในรูปดูดิ๊

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

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

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

{% file src="../../.gitbook/assets/saladpuk-handwritten-text.zip" caption="Source code: OCR" %}

🎯 บทสรุป

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

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

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

You can’t perform that action at this time.