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

دعونا نحاول معرفة ذلك ، في نفس الوقت سنكتب وحدة فك ترميز لهذه الرموز.
مقدمة
استخدام الباركود له تاريخ طويل. بدأت محاولات الأتمتة الأولى في الخمسينيات ، وتم الحصول على براءة اختراع لقارئ الكود في عام 1952. أراد المهندس المشاركة في فرز السيارات على السكك الحديدية لتبسيط هذه العملية. كانت الفكرة واضحة - ترميز الرقم باستخدام الشرائط وقراءتها باستخدام الخلايا الضوئية. في عام 1962 ، بدأ استخدام الرموز رسميًا لتحديد السيارات على السكك الحديدية الأمريكية (نظام
KarTrak ) ، في عام 1968 تم استبدال
مصباح البحث بحزمة ليزر ، مما زاد من الدقة وقلل من حجم القارئ. في عام 1973 ، ظهر تنسيق "رمز المنتج العالمي" ، وفي عام 1974 تم بيع أول منتج باستخدام الماسح الضوئي للرمز (علكة ريجليز للمضغ هي الولايات المتحدة ؛) في سوبر ماركت. في عام 1984 ، استخدم ثلث المتاجر اللافتات ، لكن في روسيا بدأ استخدامها حوالي التسعينات.
يتم استخدام الكثير من الرموز المختلفة لمهام مختلفة ، على سبيل المثال ، يمكن تمثيل التسلسل "12345678" بهذه الطرق (وهذا ليس كل شيء):

لنبدأ في تحليل bitwise. علاوة على ذلك ، فإن كل ما هو موضح أدناه سوف يشير إلى نموذج "Code-128" - ببساطة لأن تنسيقه بسيط ومباشر. يمكن لأولئك الذين يرغبون في تجربة الأنواع الأخرى فتح
مولد عبر الإنترنت والاطلاع على أنفسهم.
للوهلة الأولى ، يبدو الباركود مجرد تسلسل عشوائي للخطوط ، في الواقع ، هيكله ثابت بوضوح:

1 - المساحة الفارغة اللازمة لتحديد بداية الشفرة بوضوح
2 - رمز البداية. بالنسبة إلى Code-128 ، هناك 3 خيارات ممكنة (تسمى A و B و C): 11010000100 أو 11010010000 أو 11010011100 ، فهي تتوافق مع جداول الرموز المختلفة (لمزيد من التفاصيل ، راجع
Wikipedia ).
3 - في الواقع الكود الذي يحتوي على البيانات التي نحتاجها
4 - المجموع الاختباري
5 - رمز التوقف. بالنسبة إلى Code-128 ، هذا هو 1100011101011.
6 (1) - مساحة فارغة.
الآن حول كيفية ترميز البتات. كل شيء بسيط جدًا هنا - إذا كنت تأخذ عرض أنحف سطرًا كـ "1" ، فإن خط العرض المزدوج سيعطي الكود "11" وثلاثة "111" وما إلى ذلك. ستكون المساحة الفارغة هي "0" أو "00" أو "000" وفقًا لنفس المبدأ. يمكن لأولئك الذين يرغبون في مقارنة رمز البداية في الصورة للتأكد من أن القاعدة قد تحققت.
الآن يمكنك البدء في البرمجة.
الحصول على تسلسل بت
من حيث المبدأ ، هذا هو الجزء الأكثر صعوبة ، وبالطبع خوارزميًا ، يمكن تنفيذه بطرق مختلفة. لست متأكدًا من أن الخوارزمية الموضحة أدناه مثالية ، لكنها كافية لإجراء دراسة حالة.
للبدء ، قم بتحميل الصورة ، وتمديدها في العرض ، واتخاذ خط أفقي من منتصف الصورة ، وتحويلها إلى b / w وتحميلها كصفيف.
from PIL import Image import numpy as np import matplotlib.pyplot as plt image_path = "barcode.jpg" img = Image.open(image_path) width, height = img.size basewidth = 4*width img = img.resize((basewidth, height), Image.ANTIALIAS) hor_line_bw = img.crop((0, int(height/2), basewidth, int(height/2) + 1)).convert('L') hor_data = np.asarray(hor_line_bw, dtype="int32")[0]
في الرمز الشريطي ، يشير الرقم "1" إلى اللون الأسود ، وعلى RGB ، على العكس ، 0 ، لذلك يجب قلب المصفوفة. في الوقت نفسه ، نحسب متوسط القيمة.
hor_data = 255 - hor_data avg = np.average(hor_data) plt.plot(hor_data) plt.show()
نبدأ البرنامج للتأكد من تحميل الباركود بشكل صحيح:

الآن تحتاج إلى تحديد عرض "بت" واحد. للقيام بذلك ، نسلط الضوء على بداية تسلسل البداية "1101" ، مع تسجيل لحظات انتقال الرسم البياني عبر الخط الأوسط.
pos1, pos2 = -1, -1 bits = "" for p in range(basewidth - 2): if hor_data[p] < avg and hor_data[p + 1] > avg: bits += "1" if pos1 == -1: pos1 = p if bits == "101": pos2 = p break if hor_data[p] > avg and hor_data[p + 1] < avg: bits += "0" bit_width = int((pos2 - pos1)/3)
نسجل فقط التحولات من خلال الوسط ، بحيث يتم كتابة الكود "1101" على أنه "101" ، لكن هذا يكفي بالنسبة لنا لمعرفة عرضه بالبكسل.
الآن فك الفعلي. نجد الانتقال التالي خلال المنتصف ونحدد عدد البتات التي تقع في الفاصل الزمني. نظرًا لأن المطابقة ليست مطلقة (قد يكون الرمز منحنًا أو ممتدًا قليلاً) ، فإننا نستخدم التقريب.
bits = "" for p in range(basewidth - 2): if hor_data[p] > avg and hor_data[p + 1] < avg: interval = p - pos1 cnt = interval/bit_width bits += "1"*int(round(cnt)) pos1 = p if hor_data[p] < avg and hor_data[p + 1] > avg: interval = p - pos1 cnt = interval/bit_width bits += "0"*int(round(cnt)) pos1 = p
لست متأكدًا مما إذا كان هذا هو الخيار الأفضل ، ربما يكون هناك طريقة أفضل ، يمكن لأي شخص أن يكتب في التعليقات.
إذا تم كل شيء بشكل صحيح ، فنحن نتعرف على تسلسل الإخراج التالي:
11010010000110001010001000110100010001101110100011011101000111011011
01100110011000101000101000110001000101100011000101110110011011001111
00010101100011101011
فك التشفير
هنا ، من حيث المبدأ ، لا توجد صعوبات. يتم تشفير الأحرف في
Code-128 برمز 11 بت ، والذي يحتوي على 3 أنواع (A و B و C) ويمكن تخزين إما ترميزات أحرف مختلفة أو أرقام من 00 إلى 99.
في حالتنا ، بداية التسلسل هي 11010010000 ، والتي تتوافق مع "الرمز B". تم كسره بشكل رهيب ليتم تشغيله يدويًا في جميع رموز ويكيبيديا ، لذلك تم ببساطة نسخ الجدول من المتصفح وتم إجراء تحليله أيضًا في Python (تلميح: هذا ليس ضروريًا للإنتاج).
CODE128_CHART = """ 0 _ _ 00 32 S 11011001100 212222 1 ! ! 01 33 ! 11001101100 222122 2 " " 02 34 " 11001100110 222221 3 # # 03 35 # 10010011000 121223 ... 93 GS } 93 125 } 10100011110 111341 94 RS ~ 94 126 ~ 10001011110 131141 103 Start Start A 208 SCA 11010000100 211412 104 Start Start B 209 SCB 11010010000 211214 105 Start Start C 210 SCC 11010011100 211232 106 Stop Stop - - - 11000111010 233111""".split() SYMBOLS = [value for value in CODE128_CHART[6::8]] VALUESB = [value for value in CODE128_CHART[2::8]] CODE128B = dict(zip(SYMBOLS, VALUESB))
الآن يبقى أبسط شيء. نقوم بتقسيم تسلسل البت إلى كتل مكونة من 11 حرفًا:
sym_len = 11 symbols = [bits[i:i+sym_len] for i in range(0, len(bits), sym_len)]
أخيرًا ، نصمم الخط ونعرضه على الشاشة:
str_out = "" for sym in symbols: if CODE128A[sym] == 'Start': continue if CODE128A[sym] == 'Stop': break str_out += CODE128A[sym] print(" ", sym, CODE128A[sym]) print("Str:", str_out)
لن أعطي الإجابة على ما تم ترميزه في الجدول ، فليكن واجباً للقراء (استخدام البرامج الجاهزة للهواتف الذكية سيعتبر الغش :).
لا تنفذ الشفرة أيضًا التحقق من اتفاقية حقوق الطفل ، ويمكن لأولئك الذين يرغبون في القيام بذلك بأنفسهم.
بالطبع ، الخوارزمية غير كاملة ، وقد كتبت في نصف ساعة. لأغراض أكثر احترافية ، توجد مكتبات جاهزة ، مثل
pyzbar . سيتطلب الرمز الذي يستخدم هذه المكتبة 4 أسطر فقط:
from pyzbar.pyzbar import decode img = Image.open(image_path) decode = decode(img) print(decode)
(تحتاج أولاً إلى تثبيت المكتبة عن طريق إدخال pyzbar تثبيت أمر الأوامر)
إضافة : كتب
vinograd19 في تعليقات حول عد CRC:
تاريخ أرقام الشيكات مثير للاهتمام. نشأ تطوريًا.
مطلوب رقم الاختيار من أجل تجنب فك التشفير غير صحيح. إذا كان الباركود هو 1234 ، وتم التعرف عليه على أنه 7234 ، فأنت بحاجة إلى التحقق من الصحة ستمنع استبدال 1 ب 7. قد يكون التحقق من الصحة غير دقيق بحيث يتم تحديد 90٪ على الأقل من الأرقام غير الصالحة مسبقًا.
النهج الأول: دعنا فقط نأخذ المبلغ. بحيث يكون باقي القسمة على 10 يساوي 0. حسنًا ، تحمل الأحرف الـ 12 الأولى حمولة من المعلومات ، ويتم تحديد الرقم الأخير بحيث يتم تقسيم مجموع الأرقام على 10. فك تشفير التسلسل ، إذا كان المجموع غير قابل للقسمة على عشرة ، فهذا يعني فك الشفرة مع وجود خطأ وتحتاج إلى القيام هذا مرة أخرى. على سبيل المثال ، الرمز 1234 صالح. 1 + 2 + 3 + 4 = 10. الرمز 1216 صالح أيضًا ، لكن 1218 غير صالح.
هذا يتجنب مشاكل التشغيل الآلي. ومع ذلك ، في وقت إنشاء الرموز الشريطية ، كان هناك تراجع في شكل كتابة رقم على المفاتيح. وهناك حالة سيئة: إذا غيرت ترتيب الخانتين ، فإن المجموع الاختباري لا يتغير ، وهذا أمر سيء. أي أنه إذا تم وضع الرمز الشريطي 1234 على أنه 2134 ، فسوف يتقارب المجموع الاختباري ، لكننا أدخلنا الرقم الخطأ. اتضح أن الترتيب الخاطئ للأرقام هو حالة شائعة إذا طرقت المفاتيح بسرعة.
النهج الثاني. حسنًا ، لنجعل المبلغ أكثر تعقيدًا. بحيث يتم أخذ الأرقام الموجودة في الأماكن الزوجية في الاعتبار مرتين. بعد ذلك ، عند تغيير الطلب ، بالتأكيد لن يتقارب المبلغ المطلوب. على سبيل المثال ، الكود 2364 صالح (2 + 3 + 3 + 6 + 4 + 4 = 20) ، والكود 3264 غير صالح (3+ 2 + 2 + 6 + 4 + 4 = 19). ولكن هنا كان مثالا سيئا آخر للقيادة. بعض لوحات المفاتيح بحيث يتم ترتيب عشرة أرقام في صفين. الصف الأول هو 12345 وتحته ، الصف الثاني هو 67890. إذا ، بدلاً من المفتاح "1" ، اضغط المفتاح "2" على اليمين ، فإن المجموع الاختباري سيمنع الإدخال غير الصحيح. لكن إذا بدلًا من المفتاح "1" ، فاضغط على المفتاح "6" أدناه ، فقد لا يحذر. بعد كل شيء ، 6 = 1 + 5 ، وفي حالة وجود هذا الرقم في مكان متساوي عند حساب المجموع الاختباري ، لدينا 2 * 6 = 2 * 1 + 2 * 5. وهذا يعني أن المجموع الاختباري زاد بمقدار 10 بالضبط ، لذلك لم يتغير رقمه الأخير. على سبيل المثال ، المجموع الاختباري في الكودتين 2134 و 2634 متماثلان. سيحدث الخطأ نفسه إذا ضغطنا على 7 بدلاً من 2 ، بدلاً من 3 اضغط 8 ، وهكذا.
النهج الثالث. حسنًا ، دعنا نأخذ المبلغ مرة أخرى ، فقط الأرقام في الأماكن الزوجية ستؤخذ في الاعتبار ... ثلاث مرات. بمعنى ، الرمز 1234565 صالح ، لأن 1 + 2 * 3 + 3 + 4 * 3 + 5 + 6 * 3 +5 = 50.
أصبحت الطريقة الموضحة هي المعيار لحساب المجموع الاختباري EAN13 مع بعض التصحيحات: أصبح عدد الأرقام ثابتًا ويساوي 13 ، حيث يكون العدد 13 هو نفس المجموع الاختباري. يتم احتساب الأرقام في الأماكن الفردية ثلاث مرات ، وحتى في الأماكن الفردية - مرة واحدة.الخاتمة
كما ترون ، حتى شيء بسيط مثل الباركود يحتوي على الكثير من الأشياء المثيرة للاهتمام فيه. بالمناسبة ، اختراق حياة أخرى لأولئك الذين قرأوا هنا - النص الموجود تحت الباركود (إن وجد) يكرر محتواه بالكامل. يتم ذلك بحيث في حالة وجود رمز غير قابل للقراءة ، يمكن للمشغل إدخاله يدويًا. لذلك ، من السهل معرفة محتويات الباركود - ما عليك سوى إلقاء نظرة على النص أدناه.
كما هو موضح في التعليقات ، فإن الأكثر شعبية في التجارة هو كود EAN-13 ، وترميز البتات هو نفسه هناك ، وأولئك الذين يرغبون في
رؤية بنية الشخصية
بأنفسهم .
إذا لم يفقد القراء اهتمامهم ، فيمكنك مراعاة رموز QR بشكل منفصل.
شكرا لاهتمامكم