5.29. الباركود ورموز Data Matrix¶
تُكمل عائلتان إضافيتان من الرموز مفككات شفرات الكاميرا. فـ الباركود أحادي البعد -- الخطوط على جانب علبة الحبوب، وسوار المعصم في المستشفى، وملصق الشحن -- هو أقدم الرموز القابلة للقراءة آلياً والتي لا تزال في الاستخدام اليومي. أما رموز Data Matrix فهي ثنائية البعد مثل رموز QR، لكنها أكثر كثافة عند حجم الحمولة نفسه وموجَّهة للوسم الصناعي -- علامة الصانع المحفورة بالليزر على لوحة دارة بدلاً من الملصق على الجدار. ويحتوي وحدة image على مفكك مخصص لكل منهما، يغطي التطبيقات الصناعية وتطبيقات البيع بالتجزئة والمخزون التي لم تصل إليها رموز ثنائية الأبعاد الاستهلاكية تماماً.
5.29.1. الباركود أحادي البعد¶
يشفّر الباركود أحادي البعد حمولته على شكل سلسلة من الأشرطة العمودية بعروض متفاوتة، تُقرأ من اليسار إلى اليمين (أو من الأعلى إلى الأسفل للرموز ذات الاتجاه العمودي). وتُكمَّم العروض إلى إحدى مجموعة صغيرة من القيم، وتهجّي سلسلة العروض الأحرف بأي نظام ترميز اختاره الطابع: رقمي لرمز منتج UPC، أو أبجدي رقمي لرقم قطعة في مستودع، أو نص اعتباطي لملصق Code 128.
تمسح find_barcodes() الإطار بحثاً عن الباركود أحادي البعد في أي من أنظمة الترميز المدعومة، وتعيد قائمة من كائنات النتائج BarCode:
codes = img.find_barcodes()
for c in codes:
img.draw_rectangle(c.rect, color=(0, 255, 0))
print(c.payload, c.type, c.quality)
يمسح المفكك الإطار أفقياً وعمودياً في استدعاء واحد، فيُعثَر على باركود مطبوع بأي زاوية في مرور واحد دون أن يضطر التطبيق إلى تدوير الدخل. ويقيّد roi نطاق البحث؛ ولا توجد معاملات ضبط أخرى -- فالمفكك مكتفٍ ذاتياً.
تغطي أنظمة الترميز المدعومة العائلات الاستهلاكية والصناعية الشائعة. مجموعة البيع بالتجزئة هي image.EAN2 و image.EAN5 و image.EAN8 و image.UPCE و image.UPCA و image.EAN13 (الرموز الرقمية ثابتة الطول على معظم العبوات الاستهلاكية)، و image.ISBN10، و image.ISBN13 (العائلات نفسها مُعاد توظيفها للكتب). والمجموعة العامة الغرض هي image.I25 (Interleaved 2 of 5، الشائعة في ملصقات الشحن)، و image.CODABAR (المستخدمة في المكتبات وبنوك الدم)، و image.CODE39، و image.CODE93، و image.CODE128 (أنظمة ترميز أبجدية رقمية متغيرة الطول للنص الاعتباطي). وتُكمل القائمة عائلة حافة الرف image.DATABAR (RSS-14) و image.DATABAR_EXP (RSS-Expanded).
يحمل كل كشف مفردات مربع الإحاطة -- x و y و w و h و rect و corners -- والحمولة المفككة payload كسلسلة نصية. و type هو ثابت نظام الترميز من القائمة أعلاه، الذي يفحصه التطبيق عندما يهتم تحديداً بالعائلة التي فُكِّكت (مثل قبول EAN13 فقط لتطبيق ماسح بقالة).
الحقلان اللذان يهمان للترشيح هما rotation و quality. فـ rotation هو زاوية الباركود في مستوى الصورة بالراديان: يتعامل المفكك مع الدورانات الاعتباطية، لكن الكود اللاحق الذي يريد عرض الكشف بنظافة قد يرغب في ترشيح الرموز التي تعود مائلة بما يتجاوز عتبة ما.
أما quality فهو عدد مرات الفك: عدد خطوط المسح التي فكّكت الحمولة نفسها بنجاح. يمر المفكك عبر كل صف (وعمود) من الإطار يتقاطع مع الباركود، ويزيد العداد في كل مرة ينجح فيها الفك. فالباركود المطبوع ذو التركيز الحاد والإضاءة الجيدة يعطي quality في العشرات؛ أما الباركود المحجوب جزئياً أو الملطخ فقد يُفكَّك على خط مسح واحد أو اثنين فقط ويُبلغ عن quality يساوي 1 -- 2. وترشيح الكشوف دون quality > 5 يتخلص من حالات الفك الخاطئة العابرة ذات خط المسح الواحد دون أي كلفة على الكشوف الحقيقية.
تطبيق الباركود أحادي البعد صغير. التقط إطاراً، واستدعِ find_barcodes()، وكرّر على القائمة المعادة، ورشّح حسب c.type و c.quality، ثم مرّر c.payload عبر UART أو USB إلى أي مرحلة لاحقة تسجّل المسح أو تحتسبه.
5.29.2. Data Matrix¶
رمز Data Matrix هو رمز ثنائي البعد يشفّر حمولته على شكل شبكة من الخلايا السوداء والبيضاء، بالطريقة نفسها التي يفعلها رمز QR. وهو يختلف عن رمز QR في جانبين عمليين: فهو أصغر عند حجم الحمولة نفسه (الترميز أكثر كثافة) وهو موجَّه للاستخدام الصناعي بدلاً من الاستهلاكي (حيث تهيمن رموز QR). فالأنماط المحفورة بالليزر في القطع المعدنية على أرضية المصنع، والملصقات المطبوعة على عبوات الدارات المتكاملة، والعلامات الموضوعة على المحاقن الطبية -- كلها عادةً رموز Data Matrix، وليست رموز QR.
تمسح find_datamatrices() الإطار بحثاً عن رموز Data Matrix وتعيد قائمة من كائنات النتائج DataMatrix:
codes = img.find_datamatrices()
for c in codes:
img.draw_rectangle(c.rect, color=(0, 255, 0))
print(c.payload, c.rows, c.columns)
يقيّد roi نطاق البحث بالطريقة المعتادة. والمقبض الوحيد الخاص بالمفكك للضبط هو effort، وهو عدد صحيح يتحكم في مدى جهد المفكك للعثور على تطابق. فالقيم الأعلى تحسّن كشف الرموز الباهتة أو التالفة أو المائلة على حساب معدل الإطارات؛ والقيم الأدنى تعمل أسرع لكنها قد تفوّت رموزاً كان الجهد الأعلى ليجدها. والقيم دون 160 تقريباً تفشل فعلياً في الكشف؛ والقيم فوق 240 تقريباً تعطي عوائد متناقصة. والقيمة الافتراضية 200 توازن معقول لصورة واضحة، ونقطة البداية الصحيحة لتطبيق جديد هي القيمة الافتراضية زائد أو ناقص 20 حسبما إذا كانت الأهداف نظيفة (أدنى) أو متضررة (أعلى).
يحمل كل كشف مفردات مربع الإحاطة والزوايا الأربع المكتشفة، والحمولة المفككة payload، و rotation في مستوى الصورة بالراديان. وتصف بيانات التخطيط الوصفية حجم وكثافة الرمز الذي قرأه المفكك: rows و columns هما عددا خلايا شبكة البيانات؛ و capacity هو الحد الأقصى لعدد أحرف الحمولة التي يمكن أن يحملها الرمز بذلك الحجم؛ و padding هو عدد تلك الخانات التي ظلت غير مستخدمة (capacity - len(payload)).
تكون حقول التخطيط مفيدة للتطبيقات التي تحتاج إلى التحقق من تنسيق علامة محفورة بدلاً من محتواها. فقد يشترط نظام تتبع قطع أن تكون كل العلامات رموز 12×12 بحرفي حشو على الأكثر؛ ويُعلَّم كشف عاد بحجم 8×8 (رمز أصغر مما تتطلبه المواصفة) أو بـ 10 أحرف حشو (فارغ في معظمه) لإعادة الوسم.
5.29.3. متى نختار أيهما¶
حيث كان التمييز بين QR و AprilTag يعود إلى نوع الحمولة (بيانات اعتباطية مقابل معرّف صغير)، فإن التمييز بين الباركود ورموز Data Matrix يعود إلى الكثافة المادية والصناعة.
عندما يكون التطبيق موجهاً للمستهلك وتكون الرموز موجودة بالفعل في الميدان -- البقالة والكتب وملصقات الشحن وكتب المكتبات -- يكون الكاشف الصحيح هو find_barcodes(). فالرموز التي يقرأها التطبيق طُبعت ليقرأها نظام آخر، وأنظمة ترميز البيع بالتجزئة المعيارية هي ما توقعه ذلك النظام.
عندما يكون التطبيق صناعياً وتكون الرموز تُطبع من أجل التطبيق -- تتبع المخزون على أرضية المصنع، ورموز الدفعات المحفورة على القطع، وعلامات التتبع على الأجهزة الطبية -- يكون الكاشف الصحيح هو find_datamatrices() أو find_qrcodes()، حسبما إذا كان التطبيق يحتاج إلى الكثافة الأعلى لـ Data Matrix أو الدعم الأوسع لأدوات QR.
حفنة من التطبيقات تمزج الكواشف الأربعة كلها في خط أنابيب واحد. فقد تشغّل كاميرا فحص طرود مرور find_barcodes() لـ UPC المطبوع، ومرور find_qrcodes() لرمز QR شحن على الصندوق نفسه، ومرور find_datamatrices() لرمز قطعة محفور، كلها على الإطار الملتقط نفسه؛ وتُربط قوائم النتائج الثلاث بموضع مربع الإحاطة وتُبلَّغ كسجل كشف واحد. وتتراكم كلفة كل كاشف، لذا فإن التطبيقات التي تفعل ذلك عادةً تضيّق كل مرور بـ roi مناسب بدلاً من البحث في الإطار الكامل عن كل نوع من الرموز.