-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBankOCR.py
98 lines (86 loc) · 2.82 KB
/
BankOCR.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import functools
def normalizeCode(code):
lines = [l for l in code.split('\n')]
if len(lines) < 3:
raise ValueError("Invalid number of lines ({0})".format(len(lines)))
numChars = max([len(l) for l in lines])
# assure that all lines have the same amount of characters
def adjustLine(l):
return l + ' ' * max(numChars-len(l), 0);
lines = [adjustLine(l) for l in lines]
return '\n'.join(lines)
def splitDigits(code):
lines = [l for l in code.split('\n')]
numChars = max([len(l) for l in lines])
numDigits = numChars//3
digits = ['']*numDigits
for i in range(numDigits):
digits[i] += lines[0][i*3:i*3+3] + '\n'
digits[i] += lines[1][i*3:i*3+3] + '\n'
digits[i] += lines[2][i*3:i*3+3]
return digits
__numbers = '''
_ _ _ _ _ _ _ _
| | | _| _||_||_ |_ ||_||_|
|_| ||_ _| | _||_| ||_| _|
'''[1:]#remove first newline
#create a dict that maps each digit in string representation to its number (also str to keep leading 0)
__digitMap = dict([(d,str(i)) for i,d in enumerate(splitDigits(normalizeCode(__numbers)))])
def convertDigit(digit):
try:
return __digitMap[digit]
except KeyError:
return '?'
def convertDigits(digits):
for d in splitDigits(digits):
yield convertDigit(d)
def checksum(number):
if len(number) == 9:
sum = 0
for i, n in enumerate(number):
try:
sum += int(n) * (9-i)
except ValueError:
return False;
return sum % 11 == 0
return False;
def recover(code):
recovered = []
def replace(code, i, c):
#print(code[:i] + c + code[i+1:])
number = ''.join(convertDigits(code[:i] + c + code[i+1:]))
if checksum(number):
recovered.append(number)
for i,c in enumerate(code):
if c == '_' or c == '|':
replace(code, i, ' ')
elif c == ' ':
replace(code, i, '_')
replace(code, i, '|')
return recovered
def test(code, expected):
code = normalizeCode(code)
digits = splitDigits(code)
number = ''.join([convertDigit(d) for d in digits])
actual = number
if '?' in actual or not checksum(actual):
recovered = recover(code)
if not recovered:
actual += ' ILL'
elif len(recovered) == 1:
actual = recovered[0]
else:
actual = number + ' AMB ' + str(recovered)
if (actual != expected):
print(code)
print("Got: {0}\n Expected: {1}) ".format(actual, expected))
else:
print(actual)
# for k,v in __digitMap.items():
# print(k)
# print(v)
with open('BankOCR_Test.txt', 'r') as f:
codes = [c for c in f.read().split(';\n') if c]
for code in codes:
lines = code.split('\n')
test('\n'.join(lines[0:3]), lines[3])