יצירת ברקוד PDF417 דורשת ארבע שורות של Python. קריאת ברקוד חזרה מתמונה שצולמה בטלפון, סריקה ברזולוציה של 200 DPI, או מכרטיס טיסה שבילה יום בכיס של מישהו היא המקום שבו העבודה האמיתית מתחילה, וזה המקום שבו רוב האינטגרציות של PDF417 נכשלות בפועל. במאמר זה תלמדו כיצד לקרוא ברקודי PDF417 ב-Python כאשר תמונת המקור אינה מושלמת. אם אתם מחפשים את צד היצירה במקום זאת, המדריך הקודם על איך ליצור ברקודי PDF417 באמצעות Python מכסה יצירת סמלים בסיסיים ומותאמים של PDF417, כולל שליטה בשורות ועמודות, והמדריך קורא הברקוד ב-Python מכסה סריקה כללית של סימבולוגיות שונות. מה שמגיע כאן הוא ניתוח ממוקד ועמוק של זיהוי PDF417.
כל קטע קוד למטה הורץ נגד Aspose.BarCode for Python via .NET 26.7 על לינוקס עם Python 3.12. זמני הריצה ותוצאות הקריאה/החסרה נמדדו, ולא הוערכו, והסקריפט שייצר אותם נמצא בסוף כך שתוכל להריץ אותו מחדש על התמונות שלך.
מה בעצם פוגע בזיהוי PDF417
PDF417 הוא סימבולוגיה מרובדת: שורות של קוד‑מילים, כל קוד‑מילה בנויה מארבעה פסים וארבעה רווחים המתפרסים על פני 17 מודולים. המבנה הזה כולל תיקון שגיאות ריד‑סולומון, ולכן פינה קרועה או כתם קפה בדרך כלל ניתנים לשחזור. מה שלא ניתן לשחזור הוא איבוד רשת המודולים עצמה.
שלושה דברים משבשים את הרשת, בסדר גס של תדירות ההופעה שלהם בייצור:
- רוחב מודול אפקטיבי שנופל מתחת לשני פיקסלים. זהו הכשל השולט. זה קורה דרך הקטנה, דרך מרחק המצלמה, ודרך טשטוש, שמפיץ את הדיו של מודול אחד על השכנים שלו. ברקוד שנוצר בשלושה פיקסלים למודול ולאחר מכן מטושטש הוא בפועל ברקוד של פיקסל אחד למודול.
- פרספקטיבה וסיבוב. ברקוד שצולם בזווית יש שורות שאינן עוד קווי סריקה מקבילים. הגלאי מתמודד עם זה, אך זה דורש מעבר זיהוי שההגדרה המהירה ביותר מדלגת עליו.
- קריסת ניגודיות. נייר תרמי שהדהה, מסך שצולם תחת הילה, או סריקה עם הבהירות נעולה. פחות קטלני ממה שנראה, כפי שמראים המספרים למטה.
ההשלכה המעשית היא שהגדרות הזיהוי הן מנגנון התאוששות, ולא תחליף לאיכות הצילום. הן מחזירות לך את רמת האיכות האמצעית של התמונה. הן אינן מחזירות את הרמה התחתונה.
הגדרת קורא PDF417 ב-Python
התקן את הספרייה מ‑PyPI:
pip install aspose-barcode-for-python-via-net
ממשק ה‑API לזיהוי נמצא ב-aspose.barcode.barcoderecognition. שני מחלקות חשובות למאמר זה: BarCodeReader, שמבצע גילוי ופענוח, ו‑QualitySettings, ששולטת על כמה המזהה מתאמץ.
קריאת ברקוד PDF417 בפייתון
הקריאה המינימלית האפשרית היא שני ארגומנטים ולולאה:
from aspose.barcode import barcoderecognition as rec
reader = rec.BarCodeReader("clean.png", rec.DecodeType.PDF417)
for result in reader.read_bar_codes():
print("Code text:", result.code_text)
print("Symbology:", result.code_type_name)
print("Reading quality:", result.reading_quality)

קרא ברקוד PDF417 בפייתון.
פלט על תמונה נקייה:
Code text: PASSENGER|KHAN/M|SEAT14C|LHE-DXB
Symbology: Pdf417
Reading quality: 100.0
הארגומנט השני אינו אופציונלי בפועל. השאר אותו מחוץ וה‑BarCodeReader חוזר ל‑DecodeType.ALL_SUPPORTED_TYPES, שמבצע זיהוי של יותר משישים סימבוליות על כל אזור מועמד בתמונה. בצינור עבודה שמיועד רק ל‑PDF417 זה בזבוז מוחלט, והוא פותח את הדלת לתוצאה חיובית שגויה של סימבוליה ליניארית בתוך מבנה השורה של PDF417. ציין את הסוג.
אם הקלט שלך מגיע בתור בתים מהעלאה במקום קובץ על הדיסק, העבר זרם והגדר זמן קצוב כך שתמונה פתולוגית לא תוכל לעכב עובד:
import io
from aspose.barcode import barcoderecognition as rec
def decode_pdf417(image_bytes, timeout_ms=2000):
reader = rec.BarCodeReader(io.BytesIO(image_bytes), rec.DecodeType.PDF417)
reader.timeout = timeout_ms
return [r.code_text for r in reader.read_bar_codes()]
השוואת הגדרות איכות זיהוי PDF417 ב-Python
QualitySettings מגיע עם ארבעה פריסטים שכדאי לדעת. הקצאת אחד לקורא היא שורה אחת:
reader = rec.BarCodeReader("scan.png", rec.DecodeType.PDF417)
reader.quality_settings = rec.QualitySettings.high_quality
| Preset | Intended for | Cost |
|---|---|---|
high_performance | תמונות נקיות, שנוצרו על ידי מכונה | הכי מהיר, מדלג על מעברי שחזור |
normal_quality | ברירת מחדל. סריקות וייצוא רגילים | מאוזן |
high_quality | תמונות מצולמות במצלמה, סריקות פגומות | מתון |
max_quality | מעבר ניסיון נוסף על תמונות שכבר נכשלו | הכי איטי בפער רחב |
כדי לגלות מה המשמעות של התיאורים האלה בפועל, ייצרתי PDF417 בשלושה פיקסלים לכל מודול, הפחתתי אותו בשישה דרכים עם Pillow, והפעלתי כל הגדרה מראש על כל גרסה. ממוצע של שלוש ריצות:
| Source image | high_performance | normal_quality | high_quality | max_quality |
|---|---|---|---|---|
| נקייה | קריאה, 35 ms | קריאה, 50 ms | קריאה, 45 ms | קריאה, 106 ms |
| מסובב 12°, מטושטשת | חסר, 15 ms | קריאה, 74 ms | קריאה, 67 ms | קריאה, 157 ms |
| רעש גאוסי (σ 40) | קריאה, 31 ms | קריאה, 49 ms | קריאה, 52 ms | קריאה, 123 ms |
| רזולוציה חצי | קריאה, 22 ms | קריאה, 37 ms | קריאה, 35 ms | קריאה, 86 ms |
| ניגוד נמוך | קריאה, 24 ms | קריאה, 38 ms | קריאה, 43 ms | קריאה, 112 ms |
| טשטוש חזק (σ 2.2) | חסר, 5 ms | חסר, 25 ms | חסר, 85 ms | חסר, 180 ms |
ארבעה דברים יוצאים מטבלה זו, והם שימושיים יותר מהמספרים הבודדים:
- רעש וניגודיות נמוכה אינם הבעיה שאנשים חושבים שהם. Reed-Solomon בתוספת הגלאי ספגו רעש גאוסי כבד והפחתת ניגודיות של 82% בתצורה המהירה ביותר. הפסקו לכוונן זאת.
- סיבוב בתוספת טשטוש הוא המקרה שמפריד בין התצורות. זה גם הפרופיל המדויק של צילום בטלפון נייד, ולכן
high_performanceהוא ברירת מחדל שגויה עבור כל צינור עבודה שמקורו במובייל. max_qualityעולה שלוש פעמים את הזמן שלnormal_qualityולא קורא דבר נוסף. הוא מרוויח את מקומו כנתיב ניסיון שני, ולא כברירת מחדל.- ברגע שרשת המודול נעלמת, אף תצורה אינה משחזרת אותה. שורת הטשטוש הכבדה היא כשל בכל הרמות, ו-
max_qualityבילה 180 מ״ש להוכיח זאת. זוהי בעיית צילום עם תיקון צילום: יותר פיקסלים, פוקוס טוב יותר,x_dimensionגדול יותר בזמן הייצור.
כוונון QualitySettings לקריאת קודי PDF417 מטושטשים ב-Python
קביעת מראש היא חבילה של תכונות בודדות, וניתן להתחיל מקביעת מראש ולשכתב אחת. כאן נמצאים הרווחים האמיתיים עבור פגם ידוע, חוזר על עצמו.
התמונה המסתובבת והממטמת למעלה היא הדגמה טובה. תחת high_performance היא מפספסת. אפשר להפעיל דקונבולוציה על אותו פריסט וזה קורא:
from aspose.barcode import barcoderecognition as rec
reader = rec.BarCodeReader("rotated.png", rec.DecodeType.PDF417)
quality = rec.QualitySettings.high_performance
quality.deconvolution = rec.DeconvolutionMode.NORMAL
reader.quality_settings = quality
for result in reader.read_bar_codes():
print(result.code_text)

כוון את QualitySettings לקריאת קודי PDF417 מטושטשים ב-Python.
נמדד: כשל ב‑12 מ״ש ללא ההחלפה, קריאה ב‑54 מ״ש עם ההחלפה. תכונה אחת הפכה את התוצאה, והתוצאה עדיין חזרה מהר יותר מהקבוע max_quality היה מצפה.
המאפיינים שכדאי לדעת:
| מאפיין | ערכים | מתי להשתמש בזה |
|---|---|---|
deconvolution | FAST, NORMAL, SLOW | טשטוש תנועה ותמונות מחוץ למיקוד |
barcode_quality | HIGH, NORMAL, LOW | פגמים בהדפסה, דעיכה תרמית, ארטיפקטים בפקס |
x_dimension | AUTO, SMALL, NORMAL, LARGE, USE_MINIMAL_X_DIMENSION | קודי ברקוד צפופים, או גודל מודול קבוע ידוע |
minimal_x_dimension | float | להצמד עם USE_MINIMAL_X_DIMENSION כדי להגדיר מינימום |
complex_background | AUTO, DISABLED, ENABLED | קוד ברקוד מודפס על גרפיקה או על טופס עם תבנית |
inverse_image | AUTO, DISABLED, ENABLED | קודי ברקוד לבן על שחור, צילום מסך |
allow_incorrect_barcodes | bool | לצורכי דיאגנוסטיקה בלבד, לעולם לא בייצור |
האחרון הזה ראוי לאזהרה. allow_incorrect_barcodes מחזיר סמלים שנכשלו באימות סכום הביקורת. זהו כלי ניפוי באגים למענה על השאלה “האם הגלאי מצא כאן משהו בכלל?”. הפצת זאת משמעותה לשגר מחרוזות מפוענחות שגויות במקום שלא קיימות, מה שמחמיר את המצב יותר מאיבוד.
אסטרטגיית רמת שכבות שעובדת היטב בייצור: נסו תחילה normal_quality, ובמקרה של כשל נסו שוב פעם אחת עם high_quality בתוספת deconvolution = SLOW. אתם משלמים את הנתיב היקר רק עבור התמונות שזקוקות לכך.
אימות תוצאות פענוח PDF417 בפייתון
מחרוזת מפוענחת אינה באופן אוטומטי מחרוזת נכונה. שלושה שדות ב-BarCodeResult מסייעים:
for result in reader.read_bar_codes():
print("Text:", result.code_text)
print("Reading quality:", result.reading_quality)
print("Confidence:", result.confidence)
print("Region:", [(p.x, p.y) for p in result.region.points])
Text: PASSENGER|KHAN/M|SEAT14C|LHE-DXB
Reading quality: 100.0
Confidence: 100
Region: [(7, 6), (261, 7), (261, 276), (7, 277)]
איסוף מחדש של Macro PDF417 מפוצל על פני תמונות
Macro PDF417 מחלק הודעה לוגית אחת למספר סמלים, מה שמופיע במפרטים של משלוחים ובמסמכים מרובי עמודים. מטא‑נתוני הקטע נשארים לאחר המסע החוזר, ולכן הרכבה מחדש היא דטרמיניסטית:
from aspose.barcode import barcoderecognition as rec
segments = {}
total = None
for path in ["page1.png", "page2.png"]:
reader = rec.BarCodeReader(path, rec.DecodeType.MACRO_PDF417)
for result in reader.read_bar_codes():
meta = result.extended.pdf417
segments[meta.macro_pdf_417_segment_id] = result.code_text
total = meta.macro_pdf_417_segments_count
print(f"{path}: segment {meta.macro_pdf_417_segment_id + 1} of {total}, "
f"file id {meta.macro_pdf_417_file_id}")
if total and len(segments) == total:
payload = "".join(segments[i] for i in sorted(segments))
print("Reassembled:", payload)
else:
print("Incomplete: missing segments")

דף 1.

דף 2.
Output:
Data\pdf417\page1.png: segment 1 of 2, file id 42
Data\pdf417\page2.png: segment 2 of 2, file id 42
Reassembled: SEGMENT-A-DATASEGMENT-B-DATA
שימו לב ש-
macro_pdf_417_file_idהוא מספר שלם, ולא מחרוזת, הן בצד היצירה והן בצד הזיהוי. אותו האובייקט גם חושף אתmacro_pdf_417_file_name,macro_pdf_417_sender,macro_pdf_417_addressee,macro_pdf_417_time_stampו-macro_pdf_417_checksumכאשר המקודד מילא אותם.
מדידת ביצועים של זיהוי PDF417 בתמונות שלך
בחירת הפריסט צריכה להיות מדידה, לא ניחוש. הפנה זאת לתיקייה של קבצים מייצגים מהצינור שלך, והיא תספר לך איזה פריסט מצדיק את העלות שלו:
import time, statistics, pathlib
from aspose.barcode import barcoderecognition as rec
PRESETS = ["high_performance", "normal_quality", "high_quality", "max_quality"]
def probe(path, preset, reps=3):
times, found = [], False
for _ in range(reps):
reader = rec.BarCodeReader(str(path), rec.DecodeType.PDF417)
reader.quality_settings = getattr(rec.QualitySettings, preset)
start = time.perf_counter()
results = list(reader.read_bar_codes())
times.append((time.perf_counter() - start) * 1000)
found = found or bool(results)
return found, statistics.median(times)
for image in sorted(pathlib.Path("samples").glob("*.png")):
row = []
for preset in PRESETS:
found, ms = probe(image, preset)
row.append(f"{preset}: {'read' if found else 'miss'} {ms:.0f}ms")
print(f"{image.name:28} " + " | ".join(row))
clean.png high_performance: read 32ms | normal_quality: read 48ms | high_quality: read 51ms | max_quality: read 130ms
faded_thermal.png high_performance: read 26ms | normal_quality: read 43ms | high_quality: read 46ms | max_quality: read 144ms
half_resolution.png high_performance: read 27ms | normal_quality: read 41ms | high_quality: read 41ms | max_quality: read 89ms
heavy_blur.png high_performance: miss 7ms | normal_quality: miss 24ms | high_quality: miss 69ms | max_quality: miss 180ms
noisy_scan.png high_performance: read 26ms | normal_quality: read 42ms | high_quality: read 47ms | max_quality: read 116ms
Page1.png high_performance: read 21ms | normal_quality: read 34ms | high_quality: read 38ms | max_quality: read 90ms
Page2.png high_performance: read 21ms | normal_quality: read 33ms | high_quality: read 38ms | max_quality: read 89ms
rotated.png high_performance: miss 16ms | normal_quality: read 43ms | high_quality: read 57ms | max_quality: read 147ms
הפעל אותו פעם אחת נגד חמישים הקלטות אמיתיות והדיון המוגדר מראש מסתיים.
ההנחיות המעשיות
- הגבל את
DecodeTypeל-PDF417אלא אם אתה באמת מצפה לסימבוליות משולבות. השתמש ב-MACRO_PDF417,COMPACT_PDF417אוMICRO_PDF417כאשר אתה יודע איזו גרסה. - חתוך לפני שאתה מפענח. שליחת סריקה מלאה של A4 כאשר הברקוד תופס רק 5% ממנה מבזבזת זמן זיהוי ומוסיפה משטח של חיוביות שגויה.
- שמור קבצים ביניים ללא אובדן. PNG או TIFF. JPEG עם רינגינג בהגדרות איכות נמוכות תוקף בדיוק את קצוות הקו שהמפענח צריך.
- סדר את הניסיונות שלך ברמות במקום להשתמש בברירת המחדל האיטית ביותר.
- תקן את הייצור לפני כוונון הזיהוי. אם אתה שולט במקודד, העלאת
x_dimensionאינה עולה על שום דבר ופותרת יותר תקלות מאשר כל הגדרת קורא. ה-מאמר על יצירת PDF417 מכסה את הפרמטרים האלה. - הגדר
timeoutעל כל קורא שנוגע בתמונות שמסופקות על ידי המשתמש.
קבל רישיון חינמי
הגרסה ההערכית מוסיפה סימני מים על הטקסט המפוענח עבור סימבולוגיות שאינן Code 39, מה שעלול להפריע לכל בדיקת סיבוב שאתה מבצע. רישיון זמני חינמי מסיר זאת עבור ההערכה.
משאבים נוספים בחינם
- אפשרויות איכות קריאת ברקוד והגדרות קבועות
- מקרים מיוחדים של קריאת ברקוד
- תיעוד API
- כלים חינמיים של ברקוד באינטרנט
סיכום
קריאת ברקוד PDF417 בפייתון היא פעולה של שתי שורות על תמונות נקיות ובעיית הנדסה על תמונות אמיתיות. המדידות שלמעלה מצביעות על גישה פשוטה: שם את DecodeType, השתמש בברירת המחדל normal_quality, נסה שוב פעם אחת עם high_quality והפעל דקונבולוציה, ולוודא כל תוצאה לפני הפעולה. שמור את הפרמטרים היקרים לנתיב הניסיון מחדש, וכאשר מחלקה שלמה של תמונות נכשלת בכל הגדרה, תקן את הלכידה במקום הקורא. שאלות מוזמנות בפורום התמיכה החינמי.
שאלות נפוצות
למה ברקוד PDF417 זהה נקרא בתמונה אחת ונכשל בתמונה אחרת?
ההכרה תלויה במספר הפיקסלים שכל מודול תופס לאחר הצילום. טשטוש, הקטנה ודחיסת JPEG מצמצמים את רוחב המודול האפקטיבי, וברגע שמודול נופל מתחת לכשניים פיקסלים נקיים, אף פריסט אינו יכול לשחזר אותו.איזה פריסט זיהוי עלי להשתמש עבור PDF417?
התחל עםnormal_quality, שהוא ברירת המחדל. עבור לכיווןhigh_qualityלצילומי מצלמה וסריקות, והקצה אתmax_qualityלמעברי ניסיון מכיוון שהוא איטי בכמה פעמים מבלי לשפר משמעותית את הקריאה.האם הגבלת DecodeType ל‑PDF417 באמת משפרת את מהירות הקריאה?
כן. ברירת המחדל היאDecodeType.ALL_SUPPORTED_TYPES, שמפעילה את הגלאי לכל הסימבוליות הנתמכות. ציון PDF417 במפורש מסיר עבודה זו וגם מסיר את הסיכון לתוצאה חיובית שגויה מסימבוליות אחרת.האם Aspose.BarCode יכול לקרוא הודעת Macro PDF417 המחולקת למספר תמונות?
כן. קרא כל קטע עםDecodeType.MACRO_PDF417והשתמש ב‑macro_pdf_417_file_id,macro_pdf_417_segment_idו‑macro_pdf_417_segments_countבתוצאה המורחבת כדי להרכיב מחדש את המטען בסדר הנכון.איך אני יודע אם תוצאה מפוענחת ניתנת לאמון?
בדוק אתreading_qualityו‑confidenceב‑BarCodeResult, והשתמש בריבועregionכדי לאשר שהברקוד נמצא במיקום הצפוי בתמונה.האם ניתן לקרוא PDF417 מתמונה של רישיון נהיגה או כרטיס עלייה?
כן, בתנאי שהצילום בפוקוס והברקוד אינו נחתך. חתוך לאזור הברקוד לפני הקריאה, והעדף PNG על פני JPEG לקבצים ביניים.
