תכנות וזיהוי/הוספת זיהוי תווים אופטי - GOCR
לשם מה הגדרת זיהוי תווים אופטי
[עריכה].
התוכנית יודעת לקחת תמונה אחת ולזהות לאיזה אות או סימן התמונה הכי דומה.
אבל בזיהוי תמונה חשוב יותר לדעת מה משמעותו של כל חלק בתמונה ,
ואת זה ליישם על ידי יצירת תמונה חדשה באותו גודל של התמונה הישנה
עם כמה עקומים סגורים ובתוך העקומים כתוב מה הם העצמים המופיעים בתמונה.
לדוגמה : בלקיחת קלט של התמונה כאן נוצרת כפלט התמונה מתחתיה,
נוצרת תמונה לבנה עם קווים ובתוכם כתוב : שרקרק, שרקרק, ענף ודבורה.
דבר קצת פחות מורכב אבל דומה מבחינות מסוימות,
הוא לבודד מתמונה המכילה טקסט עם כל מיני עצמים אחרים את הטקסט,
וליצור קובץ טקסט המכיל רק את הטקסט מהתמונה.
לזה קוראים זיהוי אותיות אופטי או OCR.
באינטרנט יש דוגמה ל- OCR עם קוד פתוח באתר GOCR,
היא נכתבה על ידי : Joerg Schulenburg.
איך משלבים
[עריכה]יש כמה אפשרויות לשלב את שתי התוכנות, GOCR והתוכנה לזיהוי כתב:
- לתרגם את כל הפונקציות מ- GOCR כך שהתוכנה המשולבת תהיה
גם OCR וגם זיהוי תמונה. כאשר הזיהוי הצורני או הזיהוי על פי מיקום
(בשורה או בתמונה) יתקבל על פי בסיסי נתונים של תמונות.
נקרא לזה: "שילוב כל הפונקציות".
- לתרגם רק את הפונקציות שמוצאות את מיקומי העצמים בתמונה.
כדי להגיע לתוכנת OCR וגם זיהוי תמונה, להמשיך לפתח פונקציות חדשות
המשלבות את הרעיונות של שתי התוכנות. נקרא לזה: "שילוב רעיונות".
- להפעיל את GOCR מתוך התוכנה בלא לשנות את הקוד של GOCR , ולא את מה שכתבנו בתוכנה,
אלא רק תוספת של כמה שורות לקוד של התוכנה כדי להפעיל את GOCR כתוכנית מחוץ לתוכנה שלנו.
נקרא לזה : "הפעלה בלבד" (רק זה בוצע בתוכנה).
- להפעיל את GOCR מתוך התוכנה , באפשרות הקיימת בתוכנת GOCR ליצירת שני קבצים : אחד הוא קובץ
המכיל את הטקסט המפוענח והקובץ השני מסביר איך נוצר הקובץ המפוענח.
להתעלם מקובץ הטקסט המפוענח , ולהשתמש בקובץ ההסבר כבסיס לפענוח הטקסט . נקרא לזה "ניצול ההסבר".
בעיות בשילוב
[עריכה]ניצול ההסבר נראה מבטיח, אבל ...
[עריכה]מה GOCR נותן לנו
[עריכה]אחת האפשרויות לבקש מ - GOCR ליצור קובץ טקסט המכיל סדרת אותיות,
כל אחת כתובה בערך כמו הטבלה הזאת, המתקבלת בדו"ח דגימת תמונה מהתוכנה שלנו :
- 0777777777777777
- 0077777777777777
- 7007777777777777
- 7700777777777777
- 7770077777777777
- 7777000770077777
- 7777700770077777
- 7777700770077777
- 7777700770077777
- 7777700000000007
- 7777777777007777
- 7777777777007777
- 7777777777700777
- 7777777777770077
- 7777777777777007
- 7777777777777700
לכל אות מקבלים טבלה שגודלה 16 על 16, הרקע מוצג על ידי הספרה 7 והאות על ידי הספרה 0 .
נוסף לטבלה מקבלים (רק ב - GOCR משהוא בערך כמו שכתוב כאן )תוספת 4 מספרים :
זוג מספרים הקובעים את מיקום הקדקוד השמאלי תחתון של המלבן בתוך התמונה המפוענחת ,
והזוג הנוסף את הרוחב והגובה של המלבן בתמונה.
אבל ...
[עריכה]GOCR היא תוכנה תפורה לזיהוי לדפוס לטיני , על פי הגופנים הלטיניים. היא מקבצת חלקי אותיות ומפרקת אותיות.
לדוגמה : אם ננסה לפענח על פיה בעברית את האות 'ק' שנמצאת בסוף משפט היא תחלק את האות לשתי אותיות :
'ר' שהיא לא תדע לפענח ו- 'I' גדולה באנגלית בתחילת שורה נוספת . לכן ניצול ההסבר לא בא בחשבון כשיטה לשילוב התוכנות.
מה לא הגיוני לשלב
[עריכה]GOCR מכילה אלפי שורות קוד שרובן מתארות פונקציות העוסקות בזיהוי הצורני של האות.
בתוכנה שלנו הזיהוי הצורני נעשה אוטומטי על ידי התוכנה בעזרת השוואה לבסיס נתונים של תמונות,
בשיטת באכ"ך המוזכרת בפרקים הקודמים.
לכן שילוב בשיטת "שילוב כל הפונקציות" הוא גורם לעבודה מיותרת.
כלומר: תרגום הפונקציות העוסקות בפונקציות המיישמות זיהוי צורני מיותר, במקומן צריך להשתמש
בזיהוי הצורני על פי השוואה לתמונות מהתוכנה שלנו.
התוכנות כתובות בשפות שנות
[עריכה]התוכנה שלנו כתובה ב - CPP ואילו GOCR ב - C .
ב-"הפעלה בלבד" ו-"ניצול ההסבר" אין כל כך בעיה, כי מהדרים
את הקוד של GOCR במהדר של DEV-CPP, יש שם אפשרות להדר שפת C .
ומפעילים את קוד הריצה בצורה כזו :
- קודם יוצרים מתמונת מפת הסיביות קובץ PGM כמו שהוסבר בפרק טיפול בתמונות מפת סיביות.
- בהמשך אומרים למחשב להפעיל קובץ Go.bat מחלון Ghwnd ,הקובץ המופעל מריץ את תוכנת GOCR על התמונה כקלט.
- לבסוף אומרים למחשב להציג למשתמש ( להפעיל ) את קובץ הפלט Outg.txt .
כך מפעילים את הקובץ Go.bat מהתוכנה : ;LoadFileInF("Go.bat",Ghwnd)
ובדיוק כך מפעילים את הקובץ Outg.txt מהתוכנה : ;LoadFileInF("Outg.txt",Ghwnd)
כאשר תוכן הקובץ Go.bat הוא : gor image.pgm -m 2 -v 8 -e Verbg.txt -o Outg.txt
הסבר השורה : הפעל על התמונה image.pgm את GOCR
את פיענוח האותיות כתוב בקובץ Outg.txt ואת ההסבר לפיענוח כתוב בקובץ Verbg.txt .
תוכן הפונקציה LoadFileInF המפעילה את הקובץ ( Go.bat ) pszFileName מתוך תיקיית הקבצים
בחלון NextHwnd היא :
BOOL LoadFileInF(LPSTR pszFileName,HWND NextHwnd)
{BOOL bSuccess = FALSE;
if(ShellExecute(NextHwnd,NULL,pszFileName,
NULL,NULL,SW_NORMAL))
bSuccess = TRUE;
return bSuccess;
}
בעיית התרגום ב"שילוב רעיונות"
[עריכה]שפת CPP ו - C כתובות כמעט אותו דבר . ההבדל העיקרי בינהן
ששפת CPP היא קשיחה בהתמרת משתנים( משתנים מטיפוסי נתונים שונים )ואילו שפת C לא .
לדוגמה ,בשפת כדי ליצור חלון עם רקע לבן כותבים שורה כזו:
;wc.hbrWinBackground = SS_WHITERECT
ואילו בשפת CPP מוסיפים:
;wc.hbrWinBackground = (HBRUSH)SS_WHITERECT
כלומר הפוך את משתנה SS_WHITERECT לטיפוס HBRUSH ורק אחר כך תציב אותו כחלק ממשתני מבנה החלון.
להתמרה כזו קוראים באנגלית : CAST .
לתרגם מספר מועט של שורות זה קל , אבל הרבה שורות קוד זה קשה.
בעיית המקביליות
[עריכה]המחשב שואף לעשות כמה שיותר פעולות במקביל . אם אומרים לו לבצע פקודה הלוקחת הרבה זמן,
ואחר כך אומרים לו לעשות פקודה שלוקחת מעט זמן, הוא נוהג להתחיל את הפעולה השנייה,
כאשר הוא עדיין לא סיים את הפעולה הראשונה.
ב-"הפעלה בלבד" ו-"ניצול ההסבר" נוצרת הבעיה כאשר אומרים למחשב להפעיל את GOCR לפענוח תמונה,
ואחר כך אומרים לו להציג את תוכן קובץ הטקסט של הפלט: הוא מציג את הטקסט, לפני הפענוח!
פתרון שעדיין לא ניסיתי אותו, מבוסס על הרעיון : במקום לנסות ליצור פונקציות העובדות
באופן סידרתי, אפשר לנסות ולעבוד בצורה רישמית באופן מקבילי. ברגע שיש לנו שליטה
על המקביליות, בעזרת משתנים המשמשים כדגלים (אנגלית Semaphors) נכפה את הפונקציות לעבוד באופן סידרתי.
#include <windows.h>
#define DeciSecond 10
enum Flugs_stop{not_running,will_be_stopped}
DWORD Function_thread_id;
volatile Flugs_stop Flug_stop =not_running;
int So_Long_Time_Consuming_Function(int MyInVar,HWND GoHwnd)
{
.
.
.
LoadFileInF("Go.bat",GoHwnd);
Flug_stop= not_running;
return ...
}
int WINAPI WinMain(...)
{
Flug_stop = will_be_stopped;
//כאן מתחיל המסעף היוצר פונקציה נוספת הפועלת במקביל
CreateThread(NULL,0,& So_Long_Time_Consuming_Function,0,0,
&Function_thread_id);
while(Flug_stop==will_be_stopped) Sleep(DeciSecond);
//,Go.bat לא מספיק שהשורה הבאה תתחיל לפעול אחרי פעולת קובץ האצווה
//,GOCR אלא היא חייבת להתחיל אחרי סיום
//.Go.bat המופעל על ידי קובץ האצווה
LoadFileInF("Outg.txt",Ghwnd);
.
.
.
}
פתרון על ידי קביעת קטע חיוני
[עריכה]בתוכנה הבעיה לא פתורה, אבל באינטרנט יש תקווה לפתרון : הפעלת שני קטעי פעולות, כאשר הראשון
חייב להיגמר לפני שהשני מתחיל , לראשון קוראים קטע חיוני , ובאנגלית : Critical Section.
ליישם את זה צריך לכתוב סדרת פונקציות הקובעות קטע מהתוכנה כקטע חיוני , משהוא כזה :
CRITICAL_SECTION MyFlag
InitializeCriticalSection(&MyFlag)
EnterCriticalSection(&MyFlag)
קטע חיוני
LeaveCriticalSection(&MyFlag)
DeleteCriticalSection(&MyFlag)
פתרון על ידי המשתמש בתוכנה
[עריכה]המשתמש בתוכנה יכול לנסות להפעיל את GOCR מהתוכנה כמה פעמים עד שהוא מקבל את קובץ הטקסט המפוענח .
על הפתרון הזה אפשר להגיד שהקושיה טובה מהפתרון.
בעיית חזרה על משתנים קבועים או פונקציות באותו שם
[עריכה]תוכנת GOCR מכילה אלפי שורות קוד. מספיק שמוסיפים פונקציה קטנה,
המשתמשת בספריית חלונות ולשם כך כותבים :
#include <windows.h>
גורמים לגילוי של עוד אלפי שורות קוד, ולסבירות גבורה שלשני דברים
שונים בתוכנה יהיה אותו שם ולבלבול המהדר.
ב-"הפעלה בלבד" ו-"ניצול ההסבר" חוסכים את הבעיה הזו.