|
@@ -4,8 +4,8 @@ import glob
|
4
|
4
|
import os
|
5
|
5
|
import multiprocessing
|
6
|
6
|
import numpy
|
7
|
|
-from PIL import Image, ImageFilter
|
8
|
|
-from PIL.ImageOps import autocontrast, invert, grayscale, contain, expand
|
|
7
|
+from PIL import Image, ImageDraw, ImageFilter
|
|
8
|
+from PIL.ImageOps import autocontrast, contain, expand, grayscale, invert
|
9
|
9
|
import pytesseract
|
10
|
10
|
import signal
|
11
|
11
|
import sys
|
|
@@ -49,10 +49,10 @@ OUTPUT_PATH_KILLS = "output-kills.csv"
|
49
|
49
|
# Coordinates
|
50
|
50
|
# ----
|
51
|
51
|
|
52
|
|
-# Name, Top Left, Bottom Right, Number, Invert, BonusRightTrim
|
|
52
|
+# Name, Top Left, Bottom Right, IsNumber, Invert, BonusRightTrim
|
53
|
53
|
|
54
|
54
|
PROFILE_TARGETS = [
|
55
|
|
- ("ID", (1246, 375), (1445, 430), True, True, -10),
|
|
55
|
+ ("ID", (1242, 375), (1445, 430), True, True, -10),
|
56
|
56
|
("Power", (1435, 585), (1733, 634), True, True, 0),
|
57
|
57
|
("Kill Points", (1806, 585), (2112, 633), True, True, 0),
|
58
|
58
|
("Alliance", (1025, 584), (1427, 637), False, True, 0),
|
|
@@ -61,7 +61,7 @@ PROFILE_TARGETS = [
|
61
|
61
|
|
62
|
62
|
MOREINFO_TARGETS = [
|
63
|
63
|
("Power", (1305, 223), (1540, 274), True, True, 0),
|
64
|
|
- ("Kill Points", (1931, 222), (2188, 276), True, True, 0),
|
|
64
|
+ ("Kill Points", (1933, 222), (2188, 276), True, True, 0),
|
65
|
65
|
("Highest Power", (1815, 416), (2105, 483), True, True, 0),
|
66
|
66
|
("Victories", (1815, 515), (2105, 580), True, True, 0),
|
67
|
67
|
("Defeats", (1815, 613), (2105, 675), True, True, 0),
|
|
@@ -74,17 +74,17 @@ MOREINFO_TARGETS = [
|
74
|
74
|
|
75
|
75
|
KILLS_TARGETS = [
|
76
|
76
|
("Kill Points", (1418, 312), (1694, 352), True, False, 0),
|
77
|
|
- ("T1 Kills", (1325, 637), (1538, 684), True, False, 0),
|
|
77
|
+ ("T1 Kills", (1323, 637), (1538, 684), True, False, 0),
|
78
|
78
|
("T1 Kill Points", (1986, 637), (2212, 684), True, False, 0),
|
79
|
|
- ("T2 Kills", (1325, 702), (1538, 755), True, False, 0),
|
|
79
|
+ ("T2 Kills", (1323, 702), (1538, 755), True, False, 0),
|
80
|
80
|
("T2 Kill Points", (1986, 702), (2212, 755), True, False, 0),
|
81
|
|
- ("T3 Kills", (1325, 770), (1538, 824), True, False, 0),
|
|
81
|
+ ("T3 Kills", (1323, 770), (1538, 824), True, False, 0),
|
82
|
82
|
("T3 Kill Points", (1986, 770), (2212, 824), True, False, 0),
|
83
|
|
- ("T4 Kills", (1325, 847), (1538, 897), True, False, 0),
|
|
83
|
+ ("T4 Kills", (1323, 847), (1538, 897), True, False, 0),
|
84
|
84
|
("T4 Kill Points", (1986, 847), (2212, 897), True, False, 0),
|
85
|
|
- ("T5 Kills", (1325, 918), (1538, 968), True, False, 0),
|
|
85
|
+ ("T5 Kills", (1323, 918), (1538, 968), True, False, 0),
|
86
|
86
|
("T5 Kill Points", (1986, 918), (2212, 968), True, False, 0),
|
87
|
|
- ("Previous Kills", (1626, 985), (2228, 1039), False, False, -385)
|
|
87
|
+ ("Previous Kills", (1626, 985), (2228, 1039), True, False, -385)
|
88
|
88
|
]
|
89
|
89
|
|
90
|
90
|
# ----
|
|
@@ -116,6 +116,11 @@ def read_file(fileTuple):
|
116
|
116
|
image = Image.open(file)
|
117
|
117
|
rgbImage = Image.new("RGB", image.size, (255, 255, 255))
|
118
|
118
|
rgbImage.paste(image, mask = image.split()[3])
|
|
119
|
+
|
|
120
|
+ if arguments.debug:
|
|
121
|
+ debugImage = Image.new("RGB", rgbImage.size, (255, 255, 255))
|
|
122
|
+ debugImage.paste(rgbImage, mask = image.split()[3])
|
|
123
|
+ draw = ImageDraw.Draw(debugImage)
|
119
|
124
|
image.close()
|
120
|
125
|
|
121
|
126
|
# Get data
|
|
@@ -123,50 +128,46 @@ def read_file(fileTuple):
|
123
|
128
|
debugOutput = ""
|
124
|
129
|
for i, target in enumerate(targets):
|
125
|
130
|
debugFile = os.path.splitext(filename)[0] + "_" + str(i) + ".png"
|
126
|
|
-
|
127
|
131
|
string = read_string_from_image(rgbImage, Box(target[1][0], target[1][1], target[2][0], target[2][1]), target[3], target[4], target[5], debugFolder + debugFile)
|
128
|
132
|
debugOutput = debugOutput + " " + target[0] + ": " + string + "\n"
|
129
|
133
|
if i:
|
130
|
134
|
outputLine = outputLine + "\t"
|
131
|
135
|
outputLine = outputLine + string
|
|
136
|
+ if arguments.debug: draw.rectangle([target[1][0], target[1][1], target[2][0], target[2][1]], outline="rgb(255,0,0)")
|
|
137
|
+ if arguments.debug: debugImage.save(debugFolder + os.path.splitext(filename)[0] + "_debug" + ".png")
|
132
|
138
|
return (fileNumber, filename, debugOutput, outputPath, outputLine, isDuplicate)
|
133
|
139
|
else:
|
134
|
140
|
return (fileNumber, filename, "", outputPath, "", isDuplicate)
|
135
|
141
|
|
136
|
142
|
# Read text from a section of an image using Tesseract
|
137
|
143
|
def read_string_from_image(rgbImage, box, is_number, inv, bonusRightTrim, debugFilePath):
|
138
|
|
- # Crop to correct dimensions
|
|
144
|
+ # Crop to correct dimensions and invert if flagged
|
139
|
145
|
rgbImage = rgbImage.crop((box.x, box.y, box.x2, box.y2))
|
140
|
|
-
|
141
|
|
- # Invert if flagged
|
142
|
146
|
if inv: rgbImage = invert(rgbImage)
|
143
|
147
|
|
144
|
148
|
# Apply Pillow filters to cut off artifacts
|
145
|
149
|
rgbImage = autocontrast(rgbImage, cutoff=(0, 50))
|
146
|
150
|
|
147
|
|
- # Convert to OpenCV
|
148
|
|
- npImage=numpy.array(rgbImage)
|
149
|
|
-
|
150
|
|
- # Set colors to grayscale
|
151
|
|
- npImage=cv2.cvtColor(npImage, cv2.COLOR_BGR2GRAY)
|
|
151
|
+ # Convert to OpenCV and swap to grayscale
|
|
152
|
+ npImage = numpy.array(rgbImage)
|
|
153
|
+ npImage = cv2.cvtColor(npImage, cv2.COLOR_BGR2GRAY)
|
152
|
154
|
|
153
|
155
|
# Apply OpenCV Filters
|
154
|
156
|
npImage = cv2.medianBlur(npImage, 3)
|
155
|
157
|
_, npImage = cv2.threshold(npImage, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
|
156
|
158
|
# npImage = cv2.adaptiveThreshold(npImage, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
|
157
|
159
|
|
158
|
|
- # Convert to Pillow
|
|
160
|
+ # Convert back to Pillow and crop to content
|
159
|
161
|
rgbImage = Image.fromarray(npImage)
|
160
|
|
-
|
161
|
|
- # Crop to content
|
162
|
162
|
bbox = invert(rgbImage).getbbox()
|
163
|
163
|
if bbox: rgbImage = rgbImage.crop((bbox[0], bbox[1], bbox[2] + bonusRightTrim, bbox[3]))
|
164
|
164
|
if bbox: rgbImage = rgbImage.crop(invert(rgbImage).getbbox())
|
165
|
165
|
rgbImage = expand(rgbImage, border=10, fill=255)
|
166
|
166
|
|
167
|
|
- if arguments.debug:
|
168
|
|
- rgbImage.save(debugFilePath)
|
|
167
|
+ # Save debug image
|
|
168
|
+ if arguments.debug: rgbImage.save(debugFilePath)
|
169
|
169
|
|
|
170
|
+ # Run Tesseract (depends whether it is a number or not)
|
170
|
171
|
if is_number:
|
171
|
172
|
return pytesseract.image_to_string(rgbImage, config="--psm 6 -c tessedit_char_whitelist=0123456789,").strip().replace('\n', ' ').replace('\r', '').replace('.', '').replace(',', '').replace('\t', ' ').replace(' ', '')
|
172
|
173
|
else:
|