محلل ذكي لعدد مكتوب بالكلمات



فاتحة


مساء الخير أيها القراء الأعزاء. في هذه المقالة سأتحدث عن كيفية تحليل عدد مكتوب بالكلمات باللغة الروسية.


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


للكسول:
رابط لمشروع جيثب: رابط .



من الخوارزمية إلى النتيجة


سيصف هذا القسم الخوارزميات المستخدمة. الحذر ، والكثير من الرسائل!


بيان المشكلة


في العمل ، أحتاج إلى التعرف على النص من مستند مطبوع تم تصويره بكاميرا هاتف ذكي / جهاز لوحي. نظرًا لاتفاقية عدم الكشف ، لا يمكنني تقديم مثال لصورة فوتوغرافية ، لكن النقطة المهمة هي أن المستند يحتوي على جدول مكتوب فيه بعض المؤشرات بالأرقام والكلمات ، ويجب قراءة هذه البيانات. تحليل النص بالكلمات ضروري كأداة تحقق إضافية للتأكد من أن الرقم يتم التعرف عليه بشكل صحيح. ولكن ، كما تعلمون ، لا يضمن OCR التعرف على النص بدقة. على سبيل المثال ، يمكن التعرف على الرقم العشرين المكتوب بالكلمات على أنه "dvupat" أو حتى "dvupat". من الضروري مراعاة ذلك واستخراج أكبر قدر ممكن من المعلومات ، وتقييم حجم الخطأ المحتمل.


المذكرة. للتعرف على النص ، أستخدم tesseract 4. بالنسبة لـ .NET ، لا توجد حزمة NuGet جاهزة للإصدار الرابع ، لذلك قمت بإنشاء واحدة من فرع المشروع الرئيسي ، والذي يمكن أن يكون مفيدًا: Genesis.Tesseract4 .



خوارزمية تحليل العدد الأساسي


لنبدأ بأخرى بسيطة ، وهي خوارزمية التعرف على النص المكتوبة بالكلمات ، حتى الآن دون أخطاء. إذا كنت مهتمًا بالتحليل الذكي ، فتخط هذا القسم.


أنا لست جيدًا في googling ، لذلك لم أجد على الفور خوارزمية جاهزة لحل هذه المشكلة. ومع ذلك ، هذا حتى للأفضل ، لأن خوارزمية اخترعها أنفسنا يعطي مساحة أكبر للترميز. واتضح أن المهمة نفسها مثيرة للاهتمام.


لذلك ، دعونا نأخذ عددًا صغيرًا ، على سبيل المثال ، "مائة وثلاثة وعشرون". يتكون من ثلاث كلمات ( الرموز ) ، كل منها تقابل رقمًا ، يتم تلخيص كل هذه الأرقام:


" " = + + = 100 + 20 + 3 = 123

حتى الآن ، كل شيء بسيط ، لكننا نحفر أعمق ، على سبيل المثال ، ضع في اعتبارك الرقم "مائتي اثنا عشر ألفًا ومائة وخمسة"


" " = ( + ) × + ( + ) = 212 * 1.000 + 105 = 212.105.

كما ترون ، عندما يكون هناك الآلاف في العدد (وكذلك الملايين والدرجات الأخرى من الألف) ، يتم تقسيم الرقم إلى أجزاء تتكون من رقم صغير محلي ، في المثال أعلاه - 212 ، وعامل (1000). يمكن أن يكون هناك العديد من هذه الشظايا ، لكنها جميعًا ترتب تنازليًا للعامل ، على سبيل المثال ، ألف أو ألف لا يمكن أن يتبعوا ألف. ينطبق هذا أيضًا على أجزاء من عدد صغير ، حيث لا يمكن للمئات اتباع المئات وعشرات العشرات ، وبالتالي فإن الإدخال "مائة وخمس مائة" غير صحيح. سوف نسمي خاصية تربط بين رمزين من نفس النوع مستوى ، على سبيل المثال ، الرموز المميزة "مائة" و "ثلاثمائة" لها مستوى واحد ، وهي أكبر من الرمز "الخمسين".


من هذه الاعتبارات ، ولدت فكرة الخوارزمية. دعنا نكتب جميع الرموز ( العينات ) الممكنة ، التي سنخصص لكل منها رقمًا ، بالإضافة إلى معلمتين - مستوى المضاعف وعلامة.


رمزعددمستوىالتعديل؟
صفر
0
1
لا
واحد / واحد
1
1
لا
اثنين / اثنين
2
1
لا
...
...
1
لا
تسعة عشر
19
1
لا
عشرون
20
2
لا
...
...
2
لا
تسعون
90
2
لا
مائة
100
3
لا
...
...
3
لا
تسعمائة
900
3
لا
الف / الف / الف
1.000
4
نعم
مليون / مليون / مليون
1.000.000
5
نعم
...
...
...
نعم
كوادريليون / كوادريليون / كوادريليون
1.000.000.000.000.000
8
نعم

في الواقع ، يمكنك إضافة أي رموز أخرى إلى هذا الجدول ، بما في ذلك بالنسبة للغات الأجنبية ، لا تنسَ أنه في بعض البلدان يستخدم نظام تسمية طويل وليس قصير.


الآن دعنا ننتقل إلى التحليل. سوف نحصل على أربع كميات:


  1. المستوى العالمي ( المستوى العالمي ). يشير إلى مستوى المضاعف الأخير. غير محدد في البداية وضروري للسيطرة. إذا واجهنا رمزًا مضاعفًا يكون مستواه أكبر من أو يساوي المستوى العالمي ، فهذا خطأ.
  2. القيمة العالمية (globalValue). إجمالي الأفعى ، حيث تكون النتيجة نتيجة ضرب العدد المحلي والعامل.
  3. المستوى المحلي ( المستوى المحلي ). يشير إلى مستوى مستوى الرمز المميز الأخير. غير محدد في البداية ، يعمل بشكل مشابه للمستوى العالمي ، ولكن تتم إعادة تعيينه بعد اكتشاف المضاعف.
  4. القيمة المحلية (localValue) أحد أعمدة الرمز المميز غير المضاعف ، أي أرقام تصل إلى 999.

الخوارزمية هي كما يلي:


  1. قم بتقسيم السلسلة إلى الرموز باستخدام "\ s +" العادية.
  2. نأخذ الرمز التالي ، نحصل على معلومات عنه من العينة.
  3. إذا كان المضاعف:
    • إذا تم ضبط المستوى العالمي ، فإننا نتأكد من أنه أكبر من أو يساوي مستوى الرمز المميز. إذا لم يكن كذلك ، فهذا خطأ ؛ الرقم غير صحيح.
    • اضبط المستوى العام على مستوى الرمز المميز الحالي.
    • اضرب قيمة الرمز المميز بالقيمة المحلية وأضف النتيجة إلى القيمة العمومية.
    • نحن مسح القيمة المحلية والمستوى.
  4. إذا لم يكن هذا هو المضاعف:
    • إذا تم تعيين المستوى المحلي ، فإننا نتأكد من أنه أكبر من أو يساوي مستوى الرمز المميز. إذا لم يكن كذلك ، فهذا خطأ ؛ الرقم غير صحيح.
    • اضبط المستوى المحلي على مستوى الرمز المميز الحالي.
    • أضف قيمة الرمز المميز إلى القيمة المحلية.
  5. نعود النتيجة كمجموع القيم العالمية والمحلية.

مثال على العمل من أجل الرقم "مليونان ومائتان اثنا عشر ألف ومائة وخمسة وثمانون".


رمز
globalLevel
globalValue
ذات المستوى المحلي
localValue
-
-
-
-
اثنان
-
-
1
2
مليون
5
2.000.000
-
-
مائتان
5
2.000.000
3
200
اثنا عشر
5
2.000.000
1
212
ألف
4
2212000
-
-
مائة
4
2212000
3
100
ثمانون
4
2212000
2
180
خمسة
4
2212000
1
185

ستكون النتيجة 2.212.185.


تحليل ذكي


يمكن استخدام هذه الخوارزمية لتنفيذ مقارنات أخرى ، وليس فقط لتحليل الأرقام ، ولهذا السبب سأحاول وصفها بمزيد من التفاصيل.


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


لقد حددت ثلاثة أنواع من الأخطاء التي واجهتها في عملية العمل:


  1. استبدال الأحرف مع الآخرين بنمط مماثل. على سبيل المثال ، يتم استبدال الحرف "c" لسبب ما بكلمة "p" و "n" بكلمة "و" والعكس بالعكس. عند استخدام الإصدار الثالث من tesseract ، يمكن استبدال الحرف "o" بصفر. هذه الأخطاء ، غير المعالجة ، هي الأكثر شيوعًا ، وتتطلب التوليف لمكتبة معرفة محددة. لذا ، فإن مبادئ العمل الخاصة بالإصدارات tesseract 3 و 4 لها اختلافات جوهرية ، وبالتالي ستكون هناك أخطاء مختلفة.
  2. دمج الرمز. يمكن للكلمات أن تندمج معًا (لم تقابلها بعد). بالاقتران مع الخطأ الأول ، فإنه يولد عبارات شيطانية مثل "مزدوجة واحدة". دعونا نحاول شيطان مثل هذه الوحوش أيضًا.
  3. الضوضاء - الحروف والعبارات اليسرى في النص. لسوء الحظ ، لا يمكن فعل الكثير في الوقت الحالي ، ولكن هناك احتمال عند جمع إحصاءات مهمة بما فيه الكفاية.

في الوقت نفسه ، لا تتغير خوارزمية التحليل الموضحة أعلاه تقريبًا ، والفرق الرئيسي هو تقسيم السلسلة إلى رموز.


ولكن لنبدأ بجمع بعض الإحصاءات حول استخدام الحروف في الرموز. من بين 33 حرفًا من اللغة الروسية ، يتم استخدام 20 حرفًا فقط عند كتابة أعداد صحيحة غير سالبة ، دعنا نسميها حروف جيدة :




ما تبقى من 13 ، على التوالي ، سوف يطلق عليها رسائل سيئة . الحد الأقصى لحجم الرمز المميز هو 12 حرفًا (13 عند العد إلى quadrillion). يجب تقسيم المواد الفرعية التي تزيد عن هذه القيمة.


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


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


لوصف تكلفة إدراج أحرف وحذفها واستبدالها ، قمتُ بإنشاء جدول مثل هذا: رابط إلى جدول به أوزان . على الرغم من أنها مليئة بالطريقة الثلاث P (الجنس والإصبع والسقف) ، ولكن إذا قمت بملئها بالبيانات بناءً على إحصائيات التعرف الضوئي على الحروف ، يمكنك تحسين جودة التعرف على الأرقام بشكل كبير. يحتوي رمز المكتبة على ملف المورد NumeralLevenshteinData.txt ، حيث يمكنك إدراج بيانات من جدول مماثل باستخدام Ctrl + A و Ctrl + C و Ctrl + V.


إذا تم العثور على حرف غير جدول في النص ، على سبيل المثال ، صفر ، فإن تكلفة إدراجه تساوي الحد الأقصى للقيمة من الجدول ، وتكلفة الحذف والاستبدال تساوي الحد الأدنى ، لذلك من المرجح أن تستبدل الخوارزمية الصفر بحرف "o" ، وإذا كنت تستخدم الإصدار الثالث من tesseract ، فمن المنطقي إضافة صفر إلى الجدول وكتابة الحد الأدنى للسعر لاستبداله بالحرف "o".


لذلك ، قمنا بإعداد البيانات لخوارزمية فاغنر فيشر ، دعنا نجري تغييرات على الخوارزمية لتقسيم السلسلة إلى الرموز. للقيام بذلك ، سنخضع لتحليل إضافي لكل رمز ، ولكن قبل ذلك سنقوم بتوسيع المعلومات حول الرمز المميز بالخصائص التالية:


  • مستوى الخطأ . رقم حقيقي من 0 (بدون خطأ) إلى 1 (الرمز المميز غير صحيح) ، مما يعني مدى مقارنة الرمز المميز بالعينة.
  • علامة على استخدام رمز مميز . عند تحليل سلسلة باستخدام الحطام المتناثر ، سيتم تجاهل جزء من الرموز ، حيث لن يتم تعيين هذه السمة. في هذه الحالة ، سيتم اعتبار قيمة الخطأ الإجمالية بمثابة المتوسط ​​الحسابي لأخطاء الرموز المميزة المستخدمة.

خوارزمية تحليل الرمز:


  1. نحن نحاول العثور على الرمز المميز في الجدول كما هو. إذا وجدنا - كل شيء على ما يرام ، إعادته.
  2. إذا لم يكن كذلك ، فقم بعمل قائمة بالخيارات الممكنة:
  3. نحن نحاول مطابقة الرمز مع العينة باستخدام خوارزمية فاغنر فيشر. يتكون هذا الخيار من رمز واحد (نموذج معين) ويكون خطأه مساويًا لأفضل مسافة مقسومة على طول العينة.


    مثال: تتم مقارنة الرمز المميز "صفر" مع العينة "صفر" ، بينما تكون المسافة 0.5 ، لأن تكلفة استبدال الحرف السيئ "y" بحرف "o" هي 0.5. سيكون الخطأ الكلي لهذا الرمز المميز 0.5 / 4 = 0.125.
  4. إذا كانت السلسلة الفرعية كبيرة بدرجة كافية (لدي 6 أحرف) ، فنحن نحاول تقسيمها إلى جزأين من 3 أحرف على الأقل في كل منهما. لسلسلة من 6 أحرف سيكون هناك تقسيم واحد: 3 + 3 أحرف. لسلسلة من 7 أحرف - هناك بالفعل خياران ، 3 + 4 و 4 + 3 ، إلخ. بالنسبة لكل خيار من الخيارات ، نسمي نفس وظيفة تحليل الرمز المميز بشكل متكرر ، ندخل الخيارات المستلمة في القائمة.


    حتى لا تموت في العودية ، نحدد الحد الأقصى لمستوى الفشل. بالإضافة إلى ذلك ، يتم تقليل الخيارات التي تم الحصول عليها نتيجة للتقسيم بشكل مصطنع بمقدار معين (الخيار ، افتراضيًا 0.1) ، بحيث يكون خيار المقارنة المباشرة أكثر قيمة. اضطررت لإضافة هذه العملية ، لأنه تم تقسيم نقاط فرعية من النوع "المزدوج" بنجاح إلى رموز "اثنين" و "خمسة" ، ولم يتم اختزالها إلى "عشرين". للأسف ، هذه هي ميزات اللغة الروسية.


    مثال: الرمز المميز "المزدوج" له مقارنة مباشرة مع العينة "العشرين" ، الخطأ 0.25. بالإضافة إلى ذلك ، فإن أفضل خيار للتقسيم هو "two" + "five" بتكلفة 0.25 (استبدال "a" بكلمة "i") ، تفاقمت بشكل مصطنع إلى 0.35 ، ونتيجة لذلك يفضل الرمز "عشرون".


  5. بعد تجميع جميع الخيارات ، نختار أفضل رمز مميز بأقل قدر ممكن من الأخطاء المتضمنة فيه. يتم إرجاع النتيجة.

بالإضافة إلى ذلك ، يتم تقديم التحقق من الرمز المميز في خوارزمية إنشاء الأرقام الرئيسية بحيث لا يتجاوز الخطأ الخاص بها قيمة معينة (الخيار الافتراضي 0.67). مع هذا ، نقوم بفحص القمامة المحتملة ، ولكن ليس بنجاح كبير.


الخوارزمية باختصار بالنسبة لأولئك الذين كانوا كسولين للغاية لقراءة النص أعلاه


نقوم بتقسيم سلسلة الإدخال ، وهي الرقم بالكلمات ، إلى سلاسل فرعية باستخدام \ s + انتظام ، ثم نحاول مطابقة كل سلسلة فرعية مع نماذج الرموز أو تقسيمها إلى سلاسل فرعية أصغر ، واختيار أفضل النتائج. نتيجة لذلك ، نحصل على مجموعة من الرموز التي نقوم من خلالها بإنشاء عدد ، ويتم أخذ قيمة الخطأ على أنها المتوسط ​​الحسابي للأخطاء بين الرموز المستخدمة في الإنشاء.


شحذ خوارزمية لمهمة محددة


في مهمتي ، الأرقام غير سالبة وصغيرة نسبيًا ، لذلك سأستبعد الرموز غير الضرورية من "مليون" وأعلى. بالنسبة للاختبار ، أيها القراء الأعزاء ، لقد أضفت رموزًا إضافية للغة بلغة ، والتي سمحت بتحليل الأوتار مثل "خمس قطع" و "قص مائتي" وحتى "ثلاثة مقاطع مضحكة و قطعتين من الذهب". إنه أمر مضحك ، لكنه لا يتطلب تغييرات في الخوارزمية.


مزيد من التحسن


الخوارزمية الموجودة بها عيوب:


  1. مراقبة الحالة. سيتم التعرف على السلسلتين "ألفي" و "ألفي" بخطأ صفري في عام 2000. في مهمتي ، لا يلزم التحكم في الحالة ، بل إنه ضار ، ولكن إذا كنت بحاجة إلى مثل هذه الوظيفة ، فيتم حلها عن طريق إدخال علامة إضافية في الرمز المميز تكون مسؤولة عن حالة الرمز المميز التالي .
  2. الأرقام السالبة. يتم تقديم رمز إضافي ناقص مع معالجة خاصة. لا يوجد شيء معقد ، ولكن لا تنسَ أن الحرف "y" سيء ولا يحدث بالأرقام ، فستحتاج إلى تغيير خصائص الوزن أو الأمل في ألا يتغير أثناء عملية التعرف الضوئي على الحروف.
  3. أرقام كسرية. يتم حلها عن طريق استبدال النوع الطويل برموز مزدوجة ومقدمة من "أعشار" ، "المئات" ، وما إلى ذلك ... لا تنس أن تراجع جداول الحروف.
  4. التعرف على الأرقام التي يدخلها المستخدمون. لأن عند إدخال النص يدويًا ، نرتكب في أغلب الأحيان أخطاء تتعلق بإعادة تحرير siVMolov ، يجب عليك إضافة هذه العملية إلى خوارزمية Wagner-Fisher.
  5. دعم للغات أخرى. نقدم الرموز الجديدة ، وسّع جدول الأوزان.
  6. معالجة القمامة. في بعض المستندات ، تتم طباعة البيانات ، وقد تكون جودة الصورة رديئة ، وقد تكون الخلية فارغة. في هذه الحالة ، فإن القمامة التي تحتاج إلى تنظيف بطريقة ما تدخل في الخط. أفضل ما يمكنني تقديمه في الوقت الحالي هو المعالجة المسبقة للوثيقة قبل التعرف الضوئي على الحروف. ساعدتني إزالة خطوط الجدول وتعبئتها بلون قريب من لون المساحة الخالية للخلية. هذا لم يحل جميع المشاكل ، لكنه حسن جودة التعرف على النص من الوثائق حيث كان الجدول انحناءات بسبب كدمة أو مصور ملتوية. من الناحية المثالية ، يجب عليك تدوير الخلية نفسها والتعرف عليها بشكل منفصل ، إذا كان لديك بالطبع جدول على الإطلاق.

إذن ما هو بيت القصيد؟


يحتوي المشروع على مثال لتطبيق وحدة التحكم الذي يعمل من خلال ملف samples.txt مع أمثلة للمحلل اللغوي. فيما يلي لقطة شاشة للنتائج:




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


بالنسبة للقسم الأخير ، كنت دائمًا أتساءل عن مقدار هذا "dofiga". أيضا ، أعطى البرنامج نفسه إجابة كافية على مقدار ما يتطلبه الأمر (لا أستخدم ، ولكن لا يزال) وحتى يحدد بدقة معنى الكلمة الروسية القديمة "الظلام". ونعم ، لم يتضمن الاستنتاج تدبيراً آخر لم يسمح التعليم بإضافته ، لكن البرنامج يعتقد أنه يساوي ألف =)


بضع كلمات عن المكتبة


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


تتم كتابة المكتبة نفسها ضمن .NET Standart 2.0 و C # 7.x ، ويمكن ترجمة الخوارزميات بسهولة إلى لغات أخرى.


في حالة وجود توسعة محتملة للمكتبة ، سأضيف تركيبة المكونات المهمة في محلل الأرقام بالكلمات (Genesis.CV.NumberUtils مساحة الاسم):


  • RussianNumber.cs - المحلل اللغوي مباشرة
  • RussianNumber.Data.cs - ملف مع وصف الرموز
  • RussianNumber.ToString.cs - عدد لتحويل النص في الكلمات
  • RussianNumberParserOptions.cs - خيارات المحلل اللغوي
  • NumeralLevenshtein.cs - تنفيذ خوارزمية فاغنر فيشر
  • NumeralLevenshteinData.txt - المورد ، بيانات أوزان الحروف

استخدام:


  • RussianNumber.ToString (القيمة) - تحويل رقم إلى نص
  • RussianNumber.Parse (القيمة ، [خيارات]) - تحويل النص إلى رقم

استنتاج


آمل حقًا ألا يبدو المقال مملًا لك رغم وفرة النص. لقد توصلت مؤخرًا إلى الكثير من الموضوعات المتعلقة برؤية الكمبيوتر ، والتي يوجد شيء يمكن سرده ، لذلك أود أن أعرف رأيًا حول هذا التنسيق من المقالات. ما يستحق إضافة أو ، على العكس ، إزالة؟ ما هو أكثر إثارة للاهتمام بالنسبة لك ، القراء ، الخوارزميات أنفسهم أو شظايا رمز؟


هل تحب المقال؟ تحقق من الآخرين:


Source: https://habr.com/ru/post/ar453642/


All Articles