بناء قارئ أحرف ضوئية (OCR) متقدم باستخدام Angular وخدمة Azure Computer Vision

دقائق القراءة: 15

مقدمة إلى قارئ الأحرف الضوئية (OCR) وخدمة Azure Computer Vision

في هذا المقال التقني، سنخوض رحلة شيقة لإنشاء تطبيق متكامل للتعرف البصري على الأحرف (OCR) باستخدام إطار عمل Angular الشهير لتطوير واجهة المستخدم الأمامية، وبالاستفادة من خدمة Azure Computer Vision Cognitive Service من مايكروسوفت أزور. تُعد Computer Vision إحدى خدمات الذكاء الاصطناعي القوية التي تمكن التطبيقات من تحليل المحتوى داخل الصور وفهمها.

سنركز بشكل خاص على ميزة OCR ضمن Computer Vision لاكتشاف واستخراج النصوص المطبوعة من الصور. لن يقتصر التطبيق على استخراج النص فحسب، بل سيتجاوز ذلك لتحديد اللغة التي كُتب بها النص. تدعم واجهة برمجة تطبيقات OCR حاليًا 25 لغة مختلفة، مما يجعلها أداة مرنة للتعامل مع محتوى متعدد اللغات.

المتطلبات الأساسية لبدء المشروع

لضمان سير عملية التطوير بسلاسة، تأكد من تثبيت المتطلبات التالية على جهازك:

الحصول على الكود المصدري وهيكلة المشروع

يمكنك الحصول على الكود المصدري الكامل للمشروع من مستودع GitHub. في هذا التطبيق، سنعتمد على واجهة خلفية مبنية باستخدام ASP.NET Core. يوفر استخدام ASP.NET Core عملية مصادقة مباشرة وآمنة للوصول إلى خدمات Azure Cognitive Services. وهذا يضمن أيضًا أن المستخدم النهائي لن يتمكن من الوصول المباشر إلى مفاتيح أو تفاصيل خدمات Cognitive Services، مما يعزز أمان التطبيق.

إنشاء مورد خدمة Azure Computer Vision Cognitive Service

للبدء في استخدام خدمة Computer Vision، يجب أولاً إنشاء مورد لها في بوابة Azure:

الخطوة 1: تسجيل الدخول والبحث عن الخدمات المعرفية

سجل الدخول إلى بوابة Azure. في شريط البحث العلوي، ابحث عن cognitive services (الخدمات المعرفية) ثم انقر على النتيجة المطابقة.

شاشة البحث عن الخدمات المعرفية في بوابة Azure

الخطوة 2: إضافة مورد جديد

في الشاشة التالية، انقر على زر Add (إضافة). سيؤدي ذلك إلى فتح صفحة سوق الخدمات المعرفية. ابحث عن Computer Vision في شريط البحث ثم انقر على نتيجة البحث. ستفتح صفحة واجهة برمجة تطبيقات Computer Vision API.

اختيار خدمة Computer Vision من سوق Azure

الخطوة 3: إنشاء مورد Computer Vision

انقر على زر Create (إنشاء) لإنشاء مورد Computer Vision جديد. في صفحة الإنشاء، املأ التفاصيل المطلوبة كما هو موضح أدناه:

  • الاسم (Name): امنح موردك اسمًا فريدًا.
  • الاشتراك (Subscription): حدد نوع الاشتراك الخاص بك من القائمة المنسدلة.
  • طبقة التسعير (Pricing tier): اختر طبقة التسعير المناسبة لاحتياجاتك وميزانيتك.
  • مجموعة الموارد (Resource group): اختر مجموعة موارد موجودة أو أنشئ مجموعة جديدة.

بعد إدخال التفاصيل، انقر على زر Create (إنشاء).

تكوين إعدادات مورد Azure Computer Vision الجديد

الخطوة 4: استعراض المفتاح ونقطة النهاية

بعد نشر المورد بنجاح، انقر على زر “Go to resource” (الانتقال إلى المورد). ستتمكن من رؤية المفتاح (Key) ونقطة النهاية (endpoint) لمورد Computer Vision الذي تم إنشاؤه حديثًا.

عرض مفتاح ونقطة نهاية خدمة Azure Computer Vision

احرص على تدوين المفتاح ونقطة النهاية، حيث سنستخدمهما لاحقًا في هذا المقال لاستدعاء واجهة برمجة تطبيقات Computer Vision OCR API من كود .NET الخاص بنا. القيم في الصورة أعلاه مخفية لأسباب تتعلق بالخصوصية.

إنشاء تطبيق ASP.NET Core

سنقوم الآن بإنشاء مشروع الواجهة الخلفية باستخدام ASP.NET Core:

الخطوة 1: إنشاء مشروع جديد في Visual Studio

افتح Visual Studio 2019 وانقر على “Create a new Project” (إنشاء مشروع جديد). سيتم فتح مربع حوار “Create a new Project”. حدد “ASP.NET Core Web Application” ثم انقر على Next (التالي).

شاشة إنشاء مشروع ASP.NET Core جديد في Visual Studio

الخطوة 2: تكوين المشروع

ستنتقل الآن إلى شاشة “Configure your new project” (تكوين مشروعك الجديد). قم بتوفير اسم لتطبيقك مثل ngComputerVision ثم انقر على Create (إنشاء).

تكوين اسم المشروع واختيار قالب Angular

سيتم توجيهك إلى شاشة “Create a new ASP.NET Core web application” (إنشاء تطبيق ويب جديد لـ ASP.NET Core). حدد “.NET Core” و “ASP.NET Core 3.1” من القوائم المنسدلة في الأعلى. بعد ذلك، حدد قالب مشروع “Angular” وانقر على Create (إنشاء).

الخطوة 3: هيكل مجلدات المشروع

سيؤدي هذا إلى إنشاء مشروعنا. يوضح هيكل المجلدات الخاص بالتطبيق أدناه:

هيكل مجلدات مشروع ASP.NET Core مع Angular

يحتوي مجلد ClientApp على كود Angular لتطبيقنا. بينما تحتوي مجلدات Controllers على وحدات التحكم الخاصة بواجهات برمجة التطبيقات (API controllers). توجد مكونات Angular داخل مجلد ClientApp\src\app.

يحتوي القالب الافتراضي على عدد قليل من مكونات Angular. لن تؤثر هذه المكونات على تطبيقنا، ولكن لتبسيط الأمور، سنقوم بحذف مجلدات fetchdata و counter من مجلد ClientApp/app/components. بالإضافة إلى ذلك، يجب إزالة الإشارة إلى هذين المكونين من ملف app.module.ts لضمان عدم وجود أخطاء.

تثبيت مكتبة Computer Vision API

سنقوم بتثبيت مكتبة Azure Computer Vision API التي ستوفر لنا النماذج الجاهزة للتعامل مع استجابات Computer Vision REST API. لتثبيت الحزمة، انتقل إلى Tools >> NuGet Package Manager >> Package Manager Console (الأدوات >> مدير حزم NuGet >> وحدة تحكم مدير الحزم). ستفتح وحدة تحكم مدير الحزم. قم بتشغيل الأمر كما هو موضح أدناه:

Install-Package Microsoft.Azure.CognitiveServices.Vision.ComputerVision -Version 5.0 .0

يمكنك معرفة المزيد عن هذه الحزمة في معرض NuGet.

إنشاء النماذج (Models)

سنقوم بإنشاء بعض النماذج التي ستساعدنا في تنظيم البيانات داخل التطبيق:

الخطوة 1: إنشاء مجلد النماذج

انقر بزر الماوس الأيمن على مشروع ngComputerVision واختر Add >> New Folder (إضافة >> مجلد جديد). اسم المجلد Models.

الخطوة 2: إضافة فئة LanguageDetails.cs

مرة أخرى، انقر بزر الماوس الأيمن على مجلد Models واختر Add >> Class (إضافة >> فئة) لإضافة ملف فئة جديد. ضع اسم الفئة LanguageDetails.cs وانقر على Add (إضافة). افتح ملف LanguageDetails.cs وضع الكود التالي بداخله:

namespace ngComputerVision.Models
{
    public class LanguageDetails
    {
        public string Name { get; set; }
        public string NativeName { get; set; }
        public string Dir { get; set; }
    }
}

الخطوة 3: إضافة فئة AvailableLanguage.cs

وبالمثل، أضف ملف فئة جديد باسم AvailableLanguage.cs وضع الكود التالي بداخله:

using System.Collections.Generic;

namespace ngComputerVision.Models
{
    public class AvailableLanguage
    {
        public Dictionary<string, LanguageDetails> Translation { get; set; }
    }
}

الخطوة 4: إنشاء نماذج DTO (كائنات نقل البيانات)

سنضيف أيضًا فئتين ككائنات نقل البيانات (DTO - Data Transfer Object) لإرسال البيانات مرة أخرى إلى العميل. أنشئ مجلدًا جديدًا وسمه DTOModels.

إضافة فئة AvailableLanguageDTO.cs

أضف ملف فئة جديد AvailableLanguageDTO.cs في مجلد DTOModels وضع الكود التالي بداخله:

namespace ngComputerVision.DTOModels
{
    public class AvailableLanguageDTO
    {
        public string LanguageID { get; set; }
        public string LanguageName { get; set; }
    }
}

إضافة فئة OcrResultDTO.cs

أضف ملف OcrResultDTO.cs وضع الكود التالي بداخله:

namespace ngComputerVision.DTOModels
{
    public class OcrResultDTO
    {
        public string Language { get; set; }
        public string DetectedText { get; set; }
    }
}

إضافة وحدة التحكم OCR (OCR Controller)

سنضيف وحدة تحكم جديدة لتطبيقنا للتعامل مع طلبات التعرف على الصور:

الخطوة 1: إنشاء وحدة التحكم

انقر بزر الماوس الأيمن على مجلد Controllers واختر Add >> New Item (إضافة >> عنصر جديد). سيتم فتح مربع حوار “Add New Item” (إضافة عنصر جديد). حدد “Visual C#” من اللوحة اليسرى، ثم حدد “API Controller Class” من لوحة القوالب وضع الاسم OCRController.cs. انقر على Add (إضافة).

إضافة فئة وحدة تحكم API جديدة في Visual Studio

ستتولى وحدة التحكم OCRController معالجة طلبات التعرف على الصور الواردة من تطبيق العميل. وستقوم وحدة التحكم هذه أيضًا بإرجاع قائمة بجميع اللغات المدعومة بواسطة واجهة برمجة تطبيقات OCR.

الخطوة 2: كود OCRController.cs

افتح ملف OCRController.cs وضع الكود التالي بداخله:

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json.Linq;
using System.IO;
using Newtonsoft.Json;
using System.Text;
using ngComputerVision.Models;
using System.Collections.Generic;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
using ngComputerVision.DTOModels;

namespace ngComputerVision.Controllers
{
    [Produces("application/json")]
    [Route("api/[controller]")]
    public class OCRController : Controller
    {
        static string subscriptionKey;
        static string endpoint;
        static string uriBase;

        public OCRController()
        {
            subscriptionKey = "b993f3afb4e04119bd8ed37171d4ec71";
            endpoint = "https://ankitocrdemo.cognitiveservices.azure.com/";
            uriBase = endpoint + "vision/v2.1/ocr";
        }

        [HttpPost, DisableRequestSizeLimit]
        public async Task<OcrResultDTO> Post()
        {
            StringBuilder sb = new StringBuilder();
            OcrResultDTO ocrResultDTO = new OcrResultDTO();
            try
            {
                if (Request.Form.Files.Count > 0)
                {
                    var file = Request.Form.Files[Request.Form.Files.Count - 1];
                    if (file.Length > 0)
                    {
                        var memoryStream = new MemoryStream();
                        file.CopyTo(memoryStream);
                        byte[] imageFileBytes = memoryStream.ToArray();
                        memoryStream.Flush();

                        string JSONResult = await ReadTextFromStream(imageFileBytes);
                        OcrResult ocrResult = JsonConvert.DeserializeObject<OcrResult>(JSONResult);

                        if (!ocrResult.Language.Equals("unk"))
                        {
                            foreach (OcrLine ocrLine in ocrResult.Regions[0].Lines)
                            {
                                foreach (OcrWord ocrWord in ocrLine.Words)
                                {
                                    sb.Append(ocrWord.Text);
                                    sb.Append(' ');
                                }
                                sb.AppendLine();
                            }
                        }
                        else
                        {
                            sb.Append("This language is not supported.");
                        }
                        ocrResultDTO.DetectedText = sb.ToString();
                        ocrResultDTO.Language = ocrResult.Language;
                    }
                }
                return ocrResultDTO;
            }
            catch
            {
                ocrResultDTO.DetectedText = "Error occurred. Try again";
                ocrResultDTO.Language = "unk";
                return ocrResultDTO;
            }
        }

        static async Task<string> ReadTextFromStream(byte[] byteData)
        {
            try
            {
                HttpClient client = new HttpClient();
                client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);

                string requestParameters = "language=unk&detectOrientation=true";
                string uri = uriBase + "?" + requestParameters;

                HttpResponseMessage response;
                using (ByteArrayContent content = new ByteArrayContent(byteData))
                {
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                    response = await client.PostAsync(uri, content);
                }

                string contentString = await response.Content.ReadAsStringAsync();
                string result = JToken.Parse(contentString).ToString();
                return result;
            }
            catch (Exception e)
            {
                return e.Message;
            }
        }

        [HttpGet]
        public async Task<List<AvailableLanguageDTO>> GetAvailableLanguages()
        {
            string endpoint = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&scope=translation";
            var client = new HttpClient();

            using (var request = new HttpRequestMessage())
            {
                request.Method = HttpMethod.Get;
                request.RequestUri = new Uri(endpoint);

                var response = await client.SendAsync(request).ConfigureAwait(false);
                string result = await response.Content.ReadAsStringAsync();

                AvailableLanguage deserializedOutput = JsonConvert.DeserializeObject<AvailableLanguage>(result);
                List<AvailableLanguageDTO> availableLanguage = new List<AvailableLanguageDTO>();

                foreach (KeyValuePair<string, LanguageDetails> translation in deserializedOutput.Translation)
                {
                    AvailableLanguageDTO language = new AvailableLanguageDTO();
                    language.LanguageID = translation.Key;
                    language.LanguageName = translation.Value.Name;
                    availableLanguage.Add(language);
                }
                return availableLanguage;
            }
        }
    }
}

فهم وظائف OCRController

في دالة البناء (constructor) للفئة OCRController، قمنا بتهيئة مفتاح الاشتراك (subscriptionKey) وعنوان URL لنقطة النهاية (endpoint URL) الخاصة بواجهة برمجة تطبيقات OCR API. هذه القيم ضرورية للمصادقة والوصول إلى الخدمة.

  • التعامل مع طلبات POST (Post method):
    تستقبل هذه الدالة بيانات الصورة كـ file collection في جسم الطلب (request body) وتُرجع كائنًا من النوع OcrResultDTO. نقوم بتحويل بيانات الصورة إلى مصفوفة بايت (byte array) ثم نستدعي الدالة المساعدة ReadTextFromStream. بعد ذلك، نقوم بتحويل الاستجابة إلى كائن من النوع OcrResult. إذا تم اكتشاف اللغة، نقوم بتشكيل الجملة عن طريق التكرار على كائنات OcrWord المستخرجة.
  • قراءة النص من تيار البيانات (ReadTextFromStream method):
    داخل هذه الدالة، نُنشئ كائن HttpRequestMessage جديدًا. هذا الطلب هو طلب POST. نمرر مفتاح الاشتراك في ترويسة الطلب (header). ستُرجع واجهة برمجة تطبيقات OCR API كائن JSON يحتوي على كل كلمة من الصورة بالإضافة إلى اللغة المكتشفة للنص.
  • الحصول على اللغات المتاحة (GetAvailableLanguages method):
    تُرجع هذه الدالة قائمة بجميع اللغات المدعومة بواسطة واجهة برمجة تطبيقات Translate Text API. نقوم بتعيين URI للطلب وإنشاء HttpRequestMessage، والذي سيكون طلب GET. سيعيد URI هذا طلب JSON يتم تحويله إلى كائن من النوع AvailableLanguage.

لماذا نحتاج إلى جلب قائمة اللغات المدعومة؟

تُرجع واجهة برمجة تطبيقات OCR API رمز اللغة (على سبيل المثال، en للإنجليزية، de للألمانية، إلخ) للغة المكتشفة. ومع ذلك، لا يمكننا عرض رمز اللغة على واجهة المستخدم (UI) لأنه ليس سهل الاستخدام للمستخدمين. لذلك، نحتاج إلى قاموس للبحث عن اسم اللغة المقابل لرمز اللغة.

تدعم واجهة برمجة تطبيقات Azure Computer Vision OCR API عددًا محدودًا من اللغات (25 لغة). لمعرفة جميع اللغات المدعومة بواسطة OCR API، يمكنك الرجوع إلى قائمة اللغات المدعومة. هذه اللغات هي مجموعة فرعية من اللغات المدعومة بواسطة واجهة برمجة تطبيقات Azure Translate Text API.

نظرًا لعدم وجود نقطة نهاية API مخصصة لجلب قائمة اللغات المدعومة بواسطة OCR API، فإننا نستخدم نقطة نهاية Translate Text API لجلب قائمة اللغات. سنقوم بإنشاء قاموس بحث اللغة باستخدام استجابة JSON من استدعاء API هذا وتصفية النتيجة بناءً على رمز اللغة الذي تُرجعه OCR API.

العمل على جانب العميل من التطبيق (Client-side)

يتوفر كود جانب العميل في مجلد ClientApp. سنستخدم Angular CLI للعمل مع كود العميل. استخدام Angular CLI ليس إلزاميًا، ولكنه يسهل العمل ويوفر الوقت. إذا كنت لا ترغب في استخدام CLI، يمكنك إنشاء ملفات المكونات والخدمات يدويًا. انتقل إلى مجلد ngComputerVision\ClientApp في جهازك وافتح نافذة الأوامر. سنقوم بتنفيذ جميع أوامر Angular CLI في هذه النافذة.

إنشاء نماذج جانب العميل (Client-side Models)

أنشئ مجلدًا يسمى models داخل مجلد ClientApp\src\app. الآن سنقوم بإنشاء ملف availablelanguage.ts في مجلد models. ضع الكود التالي فيه:

export class AvailableLanguage {
  languageID: string;
  languageName: string;
}

وبالمثل، أنشئ ملفًا آخر داخل مجلد models يسمى ocrresult.ts. ضع الكود التالي فيه:

export class OcrResult {
  language: string;
  detectedText: string
}

يمكنك ملاحظة أن كلتا هاتين الفئتين لهما نفس التعريف مثل فئات DTO التي أنشأناها على جانب الخادم. سيسمح لنا هذا بربط البيانات التي تُرجعها الخادم مباشرة بنماذجنا.

إنشاء خدمة Computervision (Computervision Service)

سنقوم بإنشاء خدمة Angular التي ستستدعي نقاط نهاية Web API، وتحول استجابة Web API إلى JSON وتمررها إلى مكوننا. قم بتشغيل الأمر التالي:

ng g s services\Computervision

سيؤدي هذا الأمر إلى إنشاء مجلد باسم services ثم إنشاء الملفين التاليين بداخله:

  • computervision.service.ts — ملف فئة الخدمة.
  • computervision.service.spec.ts — ملف اختبار الوحدة للخدمة.

افتح ملف computervision.service.ts وضع الكود التالي بداخله:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ComputervisionService {

  baseURL: string;

  constructor(private http: HttpClient) {
    this.baseURL = '/api/OCR';
  }

  getAvailableLanguage() {
    return this.http.get(this.baseURL)
      .pipe(
        response => {
          return response;
        });
  }

  getTextFromImage(image: FormData) {
    return this.http.post(this.baseURL, image)
      .pipe(
        response => {
          return response;
        });
  }
}

لقد قمنا بتعريف متغير baseURL الذي سيحمل عنوان URL لنقطة نهاية واجهة برمجة التطبيقات الخاصة بنا. سنقوم بتهيئة baseURL في دالة البناء (constructor) وتعيينها لنقطة نهاية OCRController.

  • دالة getAvailableLanguage: سترسل طلب Get إلى دالة GetAvailableLanguages في OCRController لجلب قائمة اللغات المدعومة لـ OCR.
  • دالة getTextFromImage: سترسل طلب Post إلى OCRController وتوفر المعامل من النوع FormData. ستجلب النص المكتشف من الصورة ورمز اللغة للنص.

إنشاء مكون Ocr (Ocr Component)

قم بتشغيل الأمر التالي في موجه الأوامر لإنشاء OcrComponent:

ng g c ocr -- module app

سيضمن علامة --module أن هذا المكون سيتم تسجيله في app.module.ts.

كود ocr.component.html

افتح ملف ocr.component.html وضع الكود التالي فيه:

<h2>Optical Character Recognition (OCR) using Angular and Azure Computer Vision Cognitive Services</h2>
<div class="row">
  <div class="col-md-5">
    <textarea disabled class="form-control" rows="10" cols="15">{{ocrResult?.detectedText}}</textarea>
    <hr />
    <div class="row">
      <div class="col-sm-5">
        <label><strong>Detected Language :</strong></label>
      </div>
      <div class="col-sm-6">
        <input disabled type="text" class="form-control" value={{DetectedTextLanguage}} />
      </div>
    </div>
  </div>
  <div class="col-md-5">
    <div class="image-container">
      <img class="preview-image" src={{imagePreview}}>
    </div>
    <input type="file" (change)="uploadImage($event)" />
    <p>{{status}}</p>
    <hr />
    <button [disabled]="loading" class="btn btn-primary btn-lg" (click)="GetText()">
      <span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
      Extract Text
    </button>
  </div>
</div>

لقد قمنا بتعريف منطقة نص (textarea) لعرض النص المكتشف ومربع نص (text box) لعرض اللغة المكتشفة. كما قمنا بتعريف عنصر تحكم لتحميل الملف (file upload control) والذي سيسمح لنا بتحميل صورة. بعد تحميل الصورة، سيتم عرض معاينة الصورة باستخدام عنصر <img>.

كود ocr.component.ts

افتح ملف ocr.component.ts وضع الكود التالي فيه:

import { Component, OnInit } from '@angular/core';
import { ComputervisionService } from '../services/computervision.service';
import { AvailableLanguage } from '../models/availablelanguage';
import { OcrResult } from '../models/ocrresult';

@Component({
  selector: 'app-ocr',
  templateUrl: './ocr.component.html',
  styleUrls: ['./ocr.component.css']
})
export class OcrComponent implements OnInit {

  loading = false;
  imageFile;
  imagePreview;
  imageData = new FormData();
  availableLanguage: AvailableLanguage[];
  DetectedTextLanguage: string;
  ocrResult: OcrResult;
  DefaultStatus: string;
  status: string;
  maxFileSize: number;
  isValidFile = true;

  constructor(private computervisionService: ComputervisionService) {
    this.DefaultStatus = "Maximum size allowed for the image is 4 MB";
    this.status = this.DefaultStatus;
    this.maxFileSize = 4 * 1024 * 1024; // 4MB
  }

  ngOnInit() {
    this.computervisionService.getAvailableLanguage().subscribe(
      (result: AvailableLanguage[]) => this.availableLanguage = result
    );
  }

  uploadImage(event) {
    this.imageFile = event.target.files[0];
    if (this.imageFile.size > this.maxFileSize) {
      this.status = `The file size is ${this.imageFile.size} bytes, this is more than the allowed limit of ${this.maxFileSize} bytes.`
      this.isValidFile = false;
    } else if (this.imageFile.type.indexOf('image') == -1) {
      this.status = "Please upload a valid image file";
      this.isValidFile = false;
    } else {
      const reader = new FileReader();
      reader.readAsDataURL(event.target.files[0]);
      reader.onload = () => {
        this.imagePreview = reader.result;
      };
      this.status = this.DefaultStatus;
      this.isValidFile = true;
    }
  }

  GetText() {
    if (this.isValidFile) {
      this.loading = true;
      this.imageData.append('imageFile', this.imageFile);
      this.computervisionService.getTextFromImage(this.imageData).subscribe(
        (result: OcrResult) => {
          this.ocrResult = result;
          if (this.availableLanguage.find(x => x.languageID === this.ocrResult.language)) {
            this.DetectedTextLanguage = this.availableLanguage.find(x => x.languageID === this.ocrResult.language).languageName;
          } else {
            this.DetectedTextLanguage = "unknown";
          }
          this.loading = false;
        });
    }
  }
}

سنقوم بحقن خدمة ComputervisionService في دالة البناء (constructor) الخاصة بـ OcrComponent وتعيين رسالة وقيمة للحد الأقصى لحجم الصورة المسموح به داخل دالة البناء.

  • دالة ngOnInit: سنستدعي دالة getAvailableLanguage من خدمتنا في ngOnInit ونخزن النتيجة في مصفوفة من النوع AvailableLanguage.
  • دالة uploadImage: سيتم استدعاء هذه الدالة عند تحميل صورة. سنتحقق مما إذا كان الملف المحمل صورة صالحة وضمن حد الحجم المسموح به. سنقوم بمعالجة بيانات الصورة باستخدام كائن FileReader. ستقوم دالة readAsDataURL بقراءة محتويات الملف المحمل. عند الانتهاء بنجاح من عملية القراءة، سيتم تشغيل حدث reader.onload. سيتم تعيين قيمة imagePreview إلى النتيجة التي يُرجعها كائن fileReader، وهي من النوع ArrayBuffer.
  • دالة GetText: داخل هذه الدالة، سنقوم بإلحاق ملف الصورة بمتغير من النوع FormData. سنستدعي دالة getTextFromImage من الخدمة ونربط النتيجة بكائن من النوع OcrResult. سنبحث عن اسم اللغة من مصفوفة availableLanguage، بناءً على رمز اللغة الذي تُرجعه الخدمة. إذا لم يتم العثور على رمز اللغة، فسنقوم بتعيين اللغة على أنها unknown (غير معروفة).

كود ocr.component.css

سنضيف التنسيق لمنطقة النص في ملف ocr.component.css كما هو موضح أدناه:

.preview-image {
  max-height: 300px;
  max-width: 300px;
}

.image-container {
  display: flex;
  padding: 15px;
  align-content: center;
  align-items: center;
  justify-content: center;
  border: 2px dashed skyblue;
}

إضافة الروابط في قائمة التنقل (Nav Menu)

سنضيف روابط التنقل لمكوناتنا في قائمة التنقل. افتح ملف nav-menu.component.html وقم بإزالة الروابط لمكونات Counter و Fetch data. أضف الأسطر التالية في قائمة روابط التنقل:

<li class="nav-item" [routerLinkActive]="['link-active']">
  <a class="nav-link text-dark" routerLink='/computer-vision-ocr'>Computer Vision</a>
</li>

عرض التنفيذ العملي

اضغط على مفتاح F5 لتشغيل التطبيق. انقر على زر Computer Vision في قائمة التنقل العلوية. يمكنك تحميل صورة واستخراج النص منها كما هو موضح في الصورة المتحركة أدناه.

عرض توضيحي لاستخراج النص من صورة باستخدام تطبيق OCR

الخلاصة التقنية

لقد نجحنا في بناء تطبيق قارئ أحرف ضوئية (OCR) متكامل يجمع بين مرونة Angular لواجهة المستخدم وقوة Azure Computer Vision Cognitive Service لتحليل الصور. أظهر التطبيق قدرة فائقة على استخراج النصوص المطبوعة من الصور المرفوعة، بالإضافة إلى تحديد اللغة التي كُتب بها النص بدقة. الاعتماد على واجهة برمجة تطبيقات OCR API من Computer Vision، والتي تدعم 25 لغة، يفتح آفاقًا واسعة لتطبيقات معالجة المستندات متعددة اللغات. هذا المشروع يقدم نموذجًا عمليًا لكيفية دمج خدمات الذكاء الاصطناعي السحابية مع أطر عمل الويب الحديثة لإنشاء حلول قوية وفعالة.

مقالات ذات صلة قد تهمك:

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *