مقال تقني

OCR للصينية ومتعدد اللغات مع RapidOCR في Delphi عبر HotPDF

تجري HotPDF الـ OCR للصينية ولغات متعددة في Delphi عبر مُكيِّفها الأصلي لـ DLL الـ RapidOCR: ‏THPDFRapidOCRDLLOptions.ForLanguage تربط وسم لغة مثل 'zh-CN' أو 'zh-TW' أو 'ru' أو 'ar' بنموذج تعرف وقاموس محارف متطابقَين، وتحوّل THotPDF.ApplyLoadedOCRTextLayer الأسطر المعروفة إلى طبقة نص Unicode غير مرئية قابلة للبحث على صفحات PDF الممسوحة

جعل عرض توضيحي بحروف لاتينية يعمل هو الجزء السهل. الإخفاقات المثيرة تبدأ حين تنتقل إلى الصينية التقليدية أو الروسية فيتحول المخرج إلى هراء واثق مُحكم التكوين، أو حين يفقد كل سطر محرفه الأخير بصمت، أو حين تعود صفحة عربية بصناديق نصها بترتيب خاطئ. لا شيء من ذلك يرفع استثناءً بذاته. أتت الملفات التعريفية اللغوية المضافة في HotPDF ‏v2.775.0 أساساً لإغلاق تلك الفجوات، والأربعة فخوص أدناه تستحق الفهم حتى لو لم تلمس الكود الأصلي قط، لأن كل واحد منها يفسر عَرَضاً كان في غير ذلك سيطاردك يوماً كاملاً

كيف تختار ForLanguage نموذجاً وقاموساً؟

تفاضل THPDFRapidOCRDLLOptions.ForLanguage وسمَ إلى واحد من تسعة ملفات تعريفية وتعيد خيارات تشير إلى <profile>/recognition.onnx و <profile>/dictionary.txt تحت مجلد نماذجك، مع إبقاء الكاشف المشترك والمصنِّف الاختياري للزاوية وافتراضات الخيوط والبكسل والمهلة من THPDFRapidOCRDLLOptions.Default. يصغّر التابع الوسم حروفه ويحول الشرطات السفلية إلى شرطات ويجز محارف الفراغ المحيطة، فتقبع 'zh_TW' و 'ZH-tw' و ' zh-tw ' جميعها على الملف التعريفي نفسه. والأسماء البديلة قائمة صريحة لا مطابقة بادئة: ‏'zh-Hant-TW' مقبولة لأنها مسردة، بينما صيغة إقليمية اعتباطية غير مسردة ترفع EArgumentException قبل تحميل أي نموذج

تفاضل الملف التعريفي ForLanguage لدى HotPDF لـ THPDFRapidOCRDLLOptions: أوسمة مثل zh_TW و ZH-tw و zh-TW تُطبَّع وتطابق تسعة ملفات تعريفية مسردة، كل واحد يثبّت نموذج تعرف وقاموساً يُضبطان معاً دائماً، بينما وسم غير مسرد يرفع EArgumentException قبل تحميل أي نموذج
وسم واحد يختار زوج نموذج-قاموس مثبتاً واحداً؛ ويبقى الكاشف والمصنِّف والميزانيات مشتركة، والوسم المجهول يفشل سريعاً بدل تحميل أي شيء
الملف التعريفياللغاتأوسمة مثالالنموذج المثبت
chالصينية المبسطة والإنجليزيةzh، zh-CN، zh-Hans، chi_simPP-OCRv4
chinese_chtالصينية التقليديةzh-TW، zh-HK، zh-Hant، chi_traPP-OCRv3
enالإنجليزيةen، en-US، en-GB، engPP-OCRv4
latinالفرنسية والألمانية والإسبانية والبرتغالية والإيطالية والهولندية والتركيةfr، de، es-419، pt-BR، trPP-OCRv3
japanاليابانيةja، ja-JP، jpnPP-OCRv4
koreanالكوريةko، ko-KR، korPP-OCRv4
cyrillicالروسية والأوكرانية والبلغارية والبيلاروسيةru، ru-RU، uk، bgPP-OCRv3
arabicالعربية والفارسية والأرديةar، ar-SA، fa، urPP-OCRv4
devanagariالهندية والماراثية والنيباليةhi، mr، nePP-OCRv4

والمُكيِّف نفسه لا ينزّل شيئاً قط. تزوَّد الملفات مرة واحدة بالمساعد المرفق، مثل tools/Install-RapidOCRModels.ps1 -Destination C:/OCR/models -Language ch,chinese_cht,cyrillic ‏(أو -Language All للملفات التعريفية التسعة كلها)، ويلحق المساعد كاشفاً ومصنِّفاً مشتركين عند أسماء الملفات الجذرية التي تتوقعها Default. بعدها يصير مسح صيني مبسط قابلاً للبحث في بضعة أسطر. وسباكة المحرك هي مفصل IHPDFOCREngine نفسه الموصوف في مقالة DLL الـ RapidOCR داخل العملية وحدّ ABI عندها، فتبقى هذه المقالة مركزة على اللغات

uses
  SysUtils, HPDFDoc, HPDFRapidOCRRecognition;

procedure MakeChineseScanSearchable(const SourceFile, TargetFile: string);
var
  Doc: THotPDF;
  Engine: IHPDFOCREngine;
  Models: THPDFRapidOCRDLLOptions;
  Layer: THPDFOCRTextLayerOptions;
  Info: THPDFOCRTextLayerInfo;
begin
  // ‏ch/recognition.onnx + ‏ch/dictionary.txt، كاشف ومصنِّف مشتركان
  Models := THPDFRapidOCRDLLOptions.ForLanguage('zh-CN');
  Engine := HPDFCreateRapidOCRDLLOCREngine(
    'C:\OCR\Win64\HotPDFRapidOCR.dll', 'C:\OCR\models', Models);
  Doc := THotPDF.Create(nil);
  try
    Doc.AutoLaunch := False;
    if Doc.LoadFromFile(SourceFile) < 1 then
      raise Exception.Create('Cannot load ' + SourceFile);
    Layer := THPDFOCRTextLayerOptions.Default;  // ‏300 DPI، ‏MinimumConfidence ‏0.5
    // قائمة صفحات فارغة تعني كل الصفحات؛ والصفحات ذات نص مسبق تُتخطى
    if not Doc.ApplyLoadedOCRTextLayer([], Engine, Layer, Info) then
      raise Exception.Create(string(Info.Diagnostic));
    Writeln(string(Info.EngineName), ': ', Info.AcceptedWordCount,
      ' lines, ', Info.UniqueScalarCount, ' distinct characters');
    Doc.SaveLoadedDocument(TargetFile);
  finally
    Doc.Free;
  end;
end;

تفصيلان في ذلك المخرج يستحقان ملاحظة. يعيد المسار الأصلي نتيجة واحدة لكل سطر نص مكتشف لا لكل كلمة، فتعدّ AcceptedWordCount أسطراً هنا، وتُقارن MinimumConfidence بمتوسط ثقة محارف السطر كله: سطر متوسطه 0.45 يُسقط وحدةً واحدة. وتبلّغ UniqueScalarCount كم محرف Unicode مميز اضطرت طبقة النص إلى تعيينه في خطها وجدول ToUnicode عندها، وهو فحص عقلي مفيد بأن نص CJK وصل فعلاً بدل حَفنة من الاحتياطات اللاتينية. وأبقِ واجهة المحرك حية عبر المستندات، لأن تهيئة النموذج تجري في المصنع وهي الخطوة المكلفة

لماذا ينتج تبديل نموذج التعرف وحده هراءً؟

نموذج تعرف CTC لا يُخرج محارف قط، بل فهارس أصناف فقط، والقاموس هو الشيء الوحيد الذي يحول الفهرس 1,204 إلى رمز. استبدل ch/recognition.onnx بـ cyrillic/recognition.onnx مع إبقاء القاموس الصيني، وسيصدر النموذج بكل سرور فهارس سيريلية صالحة يترجمها القاموس القديم إلى محارف هان عشوائية. والنتيجة تبدو نصاً، وتجتاز تحقق UTF-8، وقابلة للبحث عن لا شيء تماماً. ولهذا تضبط ForLanguage دائماً RecognitionModel و CharacterDictionary معاً، ولهذا لا ينبغي أبداً للخيارات المبنية يدوياً أن تغيّر أحدهما دون الآخر

وفحص السلامة البديهي، مقارنة حجم القاموس بعرض مخرج النموذج، ضروري لكنه غير كافٍ. قاموسان قد يملكان العدد نفسه من المدخلات بترتيب مختلف، وانزياح بمقدار واحد في الترتيب يزيح كل محرف نقطةَ كود واحدة. لذلك تفحص HotPDF على مرحلتين حين يهيئ المصنع النموذج. أولاً يجب أن يساوي عدد أصناف المخرج مدخلات القاموس زائد اثنين. وثانياً حين يضمّ ملف ONNX قائمة بيانات وصفية باسم character تُقارن كل مدخل قاموس معها بالترتيب، ويُفشل عدمُ تطابق التهيئةَ بـ EInvalidOperation وتشخيص أصلي بدل إنتاج هراء مقنع لاحقاً

و "زائد اثنين" يأتيان من تخطيط الأصناف. الصنف 0 هو الفراغ CTC، والأصناف من 1 إلى N هي أسطر القاموس بترتيب الملف، والصنف الأخير مسافة. وبعض القواميس تحمل مدخل مسافة خاصاً بها أيضاً، ويجب إبقاء ذلك السطر كما هو تماماً. هنا يُحدث Trim حسن النية ضرراً حقيقياً: إنه يحول مدخل مسافة مفردة إلى سلسلة فارغة ويزيح الجدول أو يكسره. والتطبيع الوحيد الآمن هو إزالة إرجاع سطر لاحق، فيُحمَّل قاموس محفوظ بنهايات أسطر CRLF صحيحاً، بينما تُرفض علامة ترتيب بايتات UTF-8 أو سطر فارغ أو مدخل يحوي جدولة. يُظهر الهيكل أدناه التخطيط بلغة Pascal؛ إنه كود توضيحي لا API من HotPDF

تخطيط جدول أصناف CTC لدى HotPDF لقواميس RapidOCR: الصنف 0 هو الفراغ، والأصناف من 1 إلى N هي أسطر القاموس بترتيب الملف مع إبقاء أي مدخل مسافة منفردة، والصنف الأخير مسافة، فينتج N زائد 2 من أصناف المخرج يتحقق منها المصنع مقابل النموذج، مع البيانات الوصفية
القاموس هو الشيء الوحيد الذي يحول فهارس الأصناف إلى محارف، فيُتحقق من حجمه وترتيبه ومدخل مسافته قبل التعرف على صفحة واحدة
// للتوضيح فقط: جدول الأصناف الذي يتوقعه مُعَرِّف CTC
uses
  SysUtils, IOUtils;

function BuildCTCClassTable(const FileName: string): TArray<string>;
var
  Text, Entry: string;
  Lines: TArray<string>;
  I, Last: Integer;
begin
  Text := TEncoding.UTF8.GetString(TFile.ReadAllBytes(FileName));
  if (Text <> '') and (Text[1] = #$FEFF) then
    raise EArgumentException.Create('Dictionary must be UTF-8 without a BOM');
  Lines := Text.Split([#10]);
  Last := High(Lines);
  if (Last >= 0) and (Lines[Last] = '') then
    Dec(Last);                                   // سطر جديد عند نهاية الملف
  SetLength(Result, Last + 3);
  Result[0] := '';                               // الصنف 0: الفراغ CTC
  for I := 0 to Last do
  begin
    Entry := Lines[I];
    if (Entry <> '') and (Entry[Length(Entry)] = #13) then
      SetLength(Entry, Length(Entry) - 1);       // ‏CRLF: أسقط الـ CR فقط
    if (Entry = '') or (Pos(#9, Entry) > 0) then
      raise EArgumentException.Create('Invalid dictionary entry');
    Result[I + 1] := Entry;                      // لا ‏Trim أبدا: الفراغ ' ' صنف
  end;
  Result[Last + 2] := ' ';                       // الصنف الأخير: مسافة
  // يجب أن يساوي ‏Length(Result) عدد أصناف مخرج النموذج
end;

ماذا يفعل فك CTC الجشع فعلاً؟

يفك فك CTC الجشع الصنفَ الأعلى نقاطاً عند كل خطوة زمنية، ويطوي التكرارات المتتالية في محرف واحد، ويسقط صنف الفراغ؛ والفراغ هو ما يسمح لحروف مضاعفة حقاً بأن تنجو. ينظر نموذج التعرف إلى سطر نص بوصفه سلسلة شرائح رأسية ضيقة، ولكل شريحة، أي خطوة زمنية، يخرج احتمالاً لكل صنف. سطر يحوي AA中 قد ينتج تسلسل argmax ‏A A blank A 中 space. فطي خطوتَي A الأولتين يعطي A واحدة، والفراغ يفصلها عن A التالية، والنتيجة AA中 والمسافة اللاحقة سليمة. وبلا قاعدة الفراغ لتكن book و bok غير قابلتين للتمييز

جولة GreedyCTCDecode لدى HotPDF: ست خطوات زمنية تصوّت أصناف argmax‏: A و A وفراغ و A ومحرف هان ومسافة، تطوي التكرارات المتتالية، والفراغ يصفّر حارس التكرار فينجو حرف مضاعف حقاً، وثلاثة أعطاب حدود تُسقط بصمت تباعد الكلمات أو المحرف الأخير أو المحارف المضاعفة
المفكك بضعة عشر سطراً وكل حدّ مهم: أدرِج الصنف الأخير، وأدرِج الخطوة الأخيرة، ودع الفراغ وحده يفصل التكرارات

ولأن المفكك بضعة عشر سطراً فقط، من السهل أن تخطئ الحدود، والإخفاقات صامتة. إن توقف حلقة argmax الداخلية صنفاً قبيل النهاية فلن يفوز صنف المسافة أبداً ويعود كل سطر بلا تباعد كلمات، وهو ما يخرب بحث العبارات على صفحات الإنجليزية واللاتينية. وإن توقفت الحلقة الخارجية خطوة زمنية قبيل النهاية اختفى المحرف الأخير من كل سطر، وهو في سطر قصير قد يكون ثلث النص. وإن لم يُصفِّر الفراغُ حارسَ التكرار فطوت محارف مضاعفة مثل ll أو مضاعفات صينية مثل 谢谢 إلى واحد. يُدرِج مفكك HotPDF الصنف الأخير والخطوة الزمنية الأخيرة، ويبقي التكرارات المفصولة بفراغ، ويرفض إضافةً النقاط غير المحدودة أو الخارجة عن 0 إلى 1، وأي عدد أصناف لا يطابق القاموس. وهذا هو المنطق نفسه بوصفه توضيحاً بلغة Pascal

// للتوضيح فقط: فك CTC جشع بحدود صحيحة.
// تحمل ‏Scores احتمالات ‏Steps * Classes، صفاً واحداً لكل خطوة زمنية
function GreedyCTCDecode(const Scores: array of Single;
  Steps, Classes: Integer; const Characters: array of string): string;
var
  Step, C, Best, Previous: Integer;
  BestScore: Single;
begin
  if (Classes < 3) or (Length(Characters) <> Classes) or
    (Length(Scores) <> Steps * Classes) then
    raise EArgumentException.Create('Model output does not match the dictionary');
  Result := '';
  Previous := 0;                            // الصنف 0 هو الفراغ CTC
  for Step := 0 to Steps - 1 do             // أدرِج الخطوة الزمنية الأخيرة
  begin
    Best := 0;
    BestScore := Scores[Step * Classes];
    for C := 1 to Classes - 1 do            // أدرِج الصنف الأخير ‏(المسافة)
      if Scores[Step * Classes + C] > BestScore then
      begin
        Best := C;
        BestScore := Scores[Step * Classes + C];
      end;
    if (Best <> 0) and (Best <> Previous) then
      Result := Result + Characters[Best];
    Previous := Best;                       // الفراغ يصفّر حارس التكرار
  end;
end;

والفك الجشع ليس أدق استراتيجيات CTC المتاحة؛ فبحث beam مع نموذج لغة يصلح بعض الشرائح الملتبسة. أما للمستندات المطبوعة عند 300 DPI فنتيجة الجشع عادة هي ما لدى النموذج أن يعطيه، والمفكك ليس المكان لتعويض ضعف النموذج. مثلاً يستطيع نموذج Latin ‏PP-OCRv3 أن يقرأ ñ بوصفها n حتى على دخل نظيف. لا تخفي HotPDF ذلك باستبدالات محارف في المعالجة اللاحقة، لأن جدول استبدال يصلح الإسبانية يكسر شيئاً آخر، ومحرف خاطئ في طبقة قابلة للبحث أسوأ من إخفاق صريح

كيف ترتب HotPDF أسطر النص، بما فيها العربية من اليمين إلى اليسار؟

ترتب HotPDF صناديق النص المكتشفة من أعلى إلى أسفل، وتجمع الصناديق في صف حين تتداخل رأسياً بنصف ارتفاع الصندوق الأصغر على الأقل، وترتب كل صف من اليسار إلى اليمين، أو من اليمين إلى اليسار حين تُفعَّل RightToLeft؛ ولا تُعكس محارف كل سطر معروف قط. والتجميع مهم لأن الكاشف كثيراً ما يقسم سطراً بصرياً واحداً إلى عدة صناديق، تسمية وقيمة تفصلهما فجوة عريضة مثلاً، وفرز صافٍ بالإحداثي العلوي كان سيشابكها مع السطر المجاور كلما اختلفت قممهما ببكسل أو بكسلين

يضبط الملف التعريفي العربي RightToLeft := True، وهو يخبر الـ DLL أن يرتب صناديق كل صف بحافته اليمنى، من الهامش الأيمن إلى الداخل. وهذا هو الأثر كله. فالنص الذي يعيده النموذج لسطر هو أصلاً بترتيب Unicode المنطقي، الترتيب الذي يقرؤه كاتب عربي ويكتبه، وهو أيضاً الترتيب الذي تتوقعه استخراج نص PDF والبحث. وقلب السلسلة ميكانيكياً لتجعلها "تبدو صحيحة" في مصحح أخطاء يكسر البحث والنسخ واللصق وقارئات الشاشة. أما العرض ثنائي الاتجاه وتشكيل الرموز فمن شأن العارض

محرك واحد يخدم ملفاً تعريفياً لغوياً واحداً. لا كشف تلقائي للكتابة، فالمستند الذي يخلط أنظمة كتابة يحتاج محركاً لكل ملف تعريفي، مطبقاً على الصفحات التي تستخدمه. ولأن ApplyLoadedOCRTextLayer تأخذ قائمة صفحات صريحة وتثبت كل نداء معاملةً مستقلة من نوع الكل أو لا شيء، فالأمر بسيط

uses
  SysUtils, HPDFDoc, HPDFRapidOCRRecognition;

function CreateRapidEngine(const Tag: string): IHPDFOCREngine;
var
  Models: THPDFRapidOCRDLLOptions;
begin
  // ترفع ‏EArgumentException لوسم مجهول قبل تحميل أي نموذج
  Models := THPDFRapidOCRDLLOptions.ForLanguage(Tag);
  Models.MaxPixels := 33554432;          // سعة لصفحات A3 عند 300 DPI
  Result := HPDFCreateRapidOCRDLLOCREngine(
    'C:\OCR\Win64\HotPDFRapidOCR.dll', 'C:\OCR\models', Models);
end;

procedure OCRMixedArchive(Doc: THotPDF);
var
  Chinese, Arabic: IHPDFOCREngine;
  Layer: THPDFOCRTextLayerOptions;
  Info: THPDFOCRTextLayerInfo;
begin
  Chinese := CreateRapidEngine('zh-TW');  // الملف التعريفي ‏chinese_cht
  Arabic := CreateRapidEngine('ar-SA');   // الملف التعريفي ‏arabic، ‏RightToLeft = ‏True
  Layer := THPDFOCRTextLayerOptions.Default;
  if not Doc.ApplyLoadedOCRTextLayer([0, 1, 2], Chinese, Layer, Info) then
    raise Exception.Create(string(Info.Diagnostic));
  if not Doc.ApplyLoadedOCRTextLayer([3], Arabic, Layer, Info) then
    raise Exception.Create(string(Info.Diagnostic));
end;

سطر MaxPixels موجود لسبب. تفترض خيارات الـ DLL افتراضياً 16,777,216 بكسل لكل طلب، وهو يغطي A4 و US Letter عند 300 DPI باتساع، لكن صفحة A3 عند 300 DPI هي نحو 3508 في 4961 بكسل، أي قرابة 17.4 مليوناً، فيُرفض الطلب بوصفه فوق الميزانية. ارفع MaxPixels ‏(السقف 67,108,864) أو اخفض THPDFOCRTextLayerOptions.DPI للمقاسات الكبيرة. وترتيب اليمين إلى اليسار يستخدم تصدير HPDFRapidOCRSetReadingDirection الاختياري لنسخة ABI رقم 1؛ ولا يتطلبه المُكيِّف إلا عند ضبط RightToLeft، فيواصل DLL أقدم خدمةَ اللغات من اليسار إلى اليمين ويفشل عند إنشاء المحرك بـ EArgumentException تسمي التصدير المفقود للعربية

لماذا تفشل نماذج OCR الأحدث في التحميل؟

تربط DLL الـ RapidOCR لدى HotPDF نسخة ONNX Runtime ‏1.14 ثابتة، لا تستطيع قراءة نماذج حُفظت بنسخة ONNX IR رقم 10، وقد تتطلب الصادرات الأحدث مثل نماذج PP-OCRv5 بيئة تشغيل أحدث من ذلك؛ فيفشل ذلك النموذج عند إنشاء المحرك بتشخيص أصلي. وقيودُها هي سبب تثبيت حزم اللغات على أزواج مُعَرِّف وقاموس محددة من PP-OCRv3 و PP-OCRv4 بدل "الأحدث"، ولماذا يخلط الجدول أعلاه الجيلين: كل زوج مثبت هو زوج يُحمَّل ويُتحقق منه تحت تلك البيئة

ويفرض المثبِّت الاقتران. كل ملف في بيانه يحمل hash من نوع SHA256، وملف موجود به مختلف يوقف التثبيت بدل الكتابة فوقه، وكل تنزيل يهبط باسم مؤقت ولا ينتقل إلى مكانه إلا بعد مطابقة hash عنده. يحمي ذلك من النسخة الهادئة من مشكلة القاموس: أحدهم يُسقط recognition.onnx أحدث في مجلد ملف تعريفي يدوياً، فيصادف أن عدد الأصناف يطابق، ولا يفشل شيء حتى يبلّغ عميل أن البحث لا يجد كلمات يراها بأم عينه. وفي وقت التشغيل يبقى المُكيِّف دون اتصال ولا يجلب نموذجاً مفقوداً أبداً. ويتحقق المُعَرِّف أيضاً من شكل النموذج عند التحميل، مقبلاً دخل NCHW بارتفاع مثبت 32 أو 48 بكسل أو بارتفاع ديناميكي يجريه عند 48

وإن احتجت نظام كتابة لا تغطيه التسعة ملفات تعريفية فلا يزال بوسك أن تشير بـ RecognitionModel و CharacterDictionary إلى ملفاتك الخاصة. تسري الفحوص نفسها، وهذا هو الهدف: الزوج غير المتطابق يفشل عند التهيئة، لا في أرشيف عميلك. وللصفحات التي لا يناسبها أي ملف تعريفي من RapidOCR، يندمج مُكيِّف Tesseract لـ PDF قابل للبحث في نداء ApplyLoadedOCRTextLayer نفسه، وللنماذج ASCII المطبوعة آلياً لا يحتاج محرك OCR المدمج بمطابقة القوالب نماذج إطلاقاً

مرجع سريع: قائمة تحقق RapidOCR متعدد اللغات

  • أنشئ الخيارات بـ THPDFRapidOCRDLLOptions.ForLanguage وعامل EArgumentException وسمَاً غير مدعوم لا عطلاً في وقت التشغيل
  • غيّر RecognitionModel و CharacterDictionary معاً لا أحدهما أبداً؛ فتساوي أعداد الأصناف لا يثبت تساوي ترتيب المحارف
  • أبقِ القواميس UTF-8 بلا BOM، ولا تُجز مدخلات أبداً، وتوقع أن يملك النموذج ‏N + 2 أصناف: فراغ، ‏N مدخلات، مسافة
  • على مفكك CTC مخصص أن يغطي الصنف الأخير والخطوة الزمنية الأخيرة وأن يبقي التكرارات مفصولة بفراغ
  • استخدم محركاً واحداً لكل ملف تعريفي لغوي ومرّر قوائم صفحات صريحة للمستندات مختلطة الأنظمة
  • تغيّر RightToLeft ترتيب الصناديق فقط؛ ويبقى النص المعروف بترتيب Unicode المنطقي
  • ثبّت النماذج بـ Install-RapidOCRModels.ps1 لتحفظ ثوابث SHA256 اقترانَ النموذج والقاموس؛ واضبط UseAngleClassifier := False إن كنت ثبّتّ بـ -SkipClassifier
  • ارفع MaxPixels فوق الافتراضي 16,777,216 قبل تشغيل صفحات A3 أو أكبر عند 300 DPI

الملفات التعريفية اللغوية لـ RapidOCR والمُكيِّف الأصلي للـ DLL ومسار طبقة نص الـ OCR جزء من مكوّن HotPDF Delphi PDF Component لـ Delphi و C++Builder و FPC/Lazarus على Windows، بدءاً من v2.775.0 للملفات التعريفية متعددة اللغات