Add extraction script from wikipedia image
Browse filesThis was my first attempt at generating each individual segment image.
It kinda works, but the issue is that the PNG is not pixel perfect and
that is what the script assumes.
I'm just adding it to be archived. The better approach is to generate
the segments myself.
- .gitignore +2 -1
- led-mosaic/__init__.py +0 -0
- led-mosaic/extract.py +329 -0
.gitignore
CHANGED
|
@@ -2,4 +2,5 @@
|
|
| 2 |
__pycache__
|
| 3 |
.venv
|
| 4 |
venv
|
| 5 |
-
build
|
|
|
|
|
|
| 2 |
__pycache__
|
| 3 |
.venv
|
| 4 |
venv
|
| 5 |
+
build
|
| 6 |
+
images/extracted
|
led-mosaic/__init__.py
ADDED
|
File without changes
|
led-mosaic/extract.py
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Description:
|
| 3 |
+
|
| 4 |
+
Takes in a grid of possible combinations of a 7-segment display
|
| 5 |
+
and generates individual image files for each possible combination
|
| 6 |
+
|
| 7 |
+
- Some light thresholding is applied to the original image,
|
| 8 |
+
such that no artifacts are present in the final processed image
|
| 9 |
+
|
| 10 |
+
- Background color is added using the alpha channel as an index mask
|
| 11 |
+
|
| 12 |
+
- Intensity of non-segment pixels is reduced to have a clearer segment image
|
| 13 |
+
|
| 14 |
+
The grid image was found on Wikipedia:
|
| 15 |
+
https://upload.wikimedia.org/wikipedia/commons/d/d1/7-segment.svg
|
| 16 |
+
|
| 17 |
+
Author: Justin Silver
|
| 18 |
+
Date: 05/28/2023
|
| 19 |
+
"""
|
| 20 |
+
|
| 21 |
+
import numpy as np # for array manipulation
|
| 22 |
+
import cv2 as cv # for image stuff
|
| 23 |
+
import matplotlib.pyplot as plt # for plotting
|
| 24 |
+
import os
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def load_img(img_path, resize=False, resize_factor=0.5):
|
| 28 |
+
"""Load the 7-segment grid image using OpenCV"""
|
| 29 |
+
|
| 30 |
+
# flag needed to maintain alpha data
|
| 31 |
+
seven_seg_grid_img = cv.imread(img_path, flags=cv.IMREAD_UNCHANGED)
|
| 32 |
+
|
| 33 |
+
if resize == True:
|
| 34 |
+
seven_seg_grid_img = cv.resize(seven_seg_grid_img,
|
| 35 |
+
None,
|
| 36 |
+
fx=resize_factor,
|
| 37 |
+
fy=resize_factor,
|
| 38 |
+
interpolation=cv.INTER_AREA)
|
| 39 |
+
|
| 40 |
+
# OpenCV has BGRA ordering by default - fix RGB and BGR channels reverse order
|
| 41 |
+
seven_seg_grid_img = cv.cvtColor(seven_seg_grid_img, cv.COLOR_BGRA2RGBA)
|
| 42 |
+
|
| 43 |
+
return seven_seg_grid_img
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def apply_img_thresholding(img):
|
| 47 |
+
"""Apply thresholding to raw image
|
| 48 |
+
|
| 49 |
+
this is needed because there is some red in the upper edge of some digits
|
| 50 |
+
if this is not done, an ugly red pixel artifact is seen after the
|
| 51 |
+
intensity lowering code
|
| 52 |
+
"""
|
| 53 |
+
|
| 54 |
+
(b, g, r, a) = cv.split(img)
|
| 55 |
+
|
| 56 |
+
ret, r_thresh = cv.threshold(b, 250, 255, cv.THRESH_TRUNC)
|
| 57 |
+
ret, g_thresh = cv.threshold(g, 250, 255, cv.THRESH_TRUNC)
|
| 58 |
+
ret, b_thresh = cv.threshold(r, 250, 255, cv.THRESH_TRUNC)
|
| 59 |
+
ret, a_thresh = cv.threshold(a, 250, 255, cv.THRESH_TRUNC)
|
| 60 |
+
|
| 61 |
+
img = cv.merge((r_thresh, g_thresh, b_thresh, a_thresh))
|
| 62 |
+
|
| 63 |
+
return img
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def find_digits_in_grid(img):
|
| 67 |
+
"""Use a state machine to find location of digit pixels in grid"""
|
| 68 |
+
|
| 69 |
+
# alpha channel is used to determine the start and end index of each digit in grid
|
| 70 |
+
alpha = img[:, :, 3]
|
| 71 |
+
|
| 72 |
+
# indexing into the grid to find the first digit (used for subsequent digits)
|
| 73 |
+
digit_location = {
|
| 74 |
+
'left': 0,
|
| 75 |
+
'right': 0,
|
| 76 |
+
'up' : 0,
|
| 77 |
+
'down' : 0
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
# state machine to find each edge of the digit
|
| 81 |
+
digit_search_state = 'NOTHING_FOUND'
|
| 82 |
+
|
| 83 |
+
for row_idx in range(alpha.shape[0]):
|
| 84 |
+
for col_idx in range(alpha.shape[1]):
|
| 85 |
+
pixel = alpha[row_idx,col_idx]
|
| 86 |
+
|
| 87 |
+
match digit_search_state:
|
| 88 |
+
|
| 89 |
+
# because we are going by row from top to bottom, we will reach the top of the digit first
|
| 90 |
+
case 'NOTHING_FOUND':
|
| 91 |
+
|
| 92 |
+
if pixel > 0:
|
| 93 |
+
digit_search_state = 'DIG_TOP_EDGE_FOUND'
|
| 94 |
+
digit_location['up'] = row_idx
|
| 95 |
+
digit_location['left'] = col_idx # we just need to know the left top edge of the digit to compare later
|
| 96 |
+
break # we don't need to look at this row anymore
|
| 97 |
+
# (it will just repeat the digits on the right)
|
| 98 |
+
|
| 99 |
+
# now we need to get the left edge
|
| 100 |
+
case 'DIG_TOP_EDGE_FOUND':
|
| 101 |
+
|
| 102 |
+
if pixel > 0:
|
| 103 |
+
if col_idx != digit_location['left']: # because we are at the slopeing part of the segment
|
| 104 |
+
digit_location['left'] = col_idx
|
| 105 |
+
break # we don't need to look at this row anymore,
|
| 106 |
+
# cause we still haven't reached the left most edge of the digit
|
| 107 |
+
else:
|
| 108 |
+
# we had the same col location twice, so we are at an edge !
|
| 109 |
+
digit_search_state = 'DIG_LEFT_EDGE_FOUND'
|
| 110 |
+
digit_location['left'] = col_idx
|
| 111 |
+
# we don't need to break, since we can just go all
|
| 112 |
+
# the way to the right to find the right edge
|
| 113 |
+
|
| 114 |
+
case 'DIG_LEFT_EDGE_FOUND':
|
| 115 |
+
# not too robust, because we assume there is a white line across the alpha channel (ignoring black space in middle)
|
| 116 |
+
if pixel == 0:
|
| 117 |
+
digit_search_state = 'DIG_RIGHT_EDGE_FOUND'
|
| 118 |
+
digit_location['right'] = col_idx-1 # -1 because we found the black space, now we need to go one before to get the digit
|
| 119 |
+
break
|
| 120 |
+
|
| 121 |
+
case 'DIG_RIGHT_EDGE_FOUND':
|
| 122 |
+
if pixel > 0:
|
| 123 |
+
digit_location['down'] = row_idx
|
| 124 |
+
break
|
| 125 |
+
elif col_idx == digit_location['right']:
|
| 126 |
+
digit_location['down'] = row_idx-1
|
| 127 |
+
digit_search_state = 'DIG_BOTTOM_EDGE_FOUND'
|
| 128 |
+
break
|
| 129 |
+
|
| 130 |
+
case 'DIG_BOTTOM_EDGE_FOUND':
|
| 131 |
+
# we don't need to do anything here
|
| 132 |
+
break
|
| 133 |
+
|
| 134 |
+
case _:
|
| 135 |
+
raise Exception("Invalid digit_search_state: ", digit_search_state)
|
| 136 |
+
|
| 137 |
+
if (digit_search_state == 'DIG_BOTTOM_EDGE_FOUND'):
|
| 138 |
+
break # to break out of upper loop, we found the whole digit now
|
| 139 |
+
|
| 140 |
+
return digit_location
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
def calculate_pixel_locations(digit_location, verbose=False):
|
| 144 |
+
"""Get some offset and digit size information from digit locations"""
|
| 145 |
+
|
| 146 |
+
# number of pixels each digit's height takes up (+1 because top-left corner is at (0, 0) coordinates)
|
| 147 |
+
digit_height = (digit_location['down'] - digit_location['up']) + 1
|
| 148 |
+
|
| 149 |
+
# number of pixels each digit's width takes up (+1 because top-left corner is at (0, 0) coordinates)
|
| 150 |
+
digit_width = (digit_location['right']- digit_location['left']) + 1
|
| 151 |
+
|
| 152 |
+
# number of cols (x-axis pixels) to skip to get to the left-edge of the first digit
|
| 153 |
+
col_offset = digit_location['left']
|
| 154 |
+
|
| 155 |
+
# number of rows (y-axis pixels) to skip to get to the top-edge of the first digit
|
| 156 |
+
row_offset = digit_location['up']
|
| 157 |
+
|
| 158 |
+
if (verbose):
|
| 159 |
+
print(f"digit_location: {digit_location}")
|
| 160 |
+
print(f"digit_height: {digit_height}")
|
| 161 |
+
print(f"digit_width: {digit_width}")
|
| 162 |
+
print(f"col_offset: {col_offset}")
|
| 163 |
+
print(f"row_offset: {row_offset}")
|
| 164 |
+
|
| 165 |
+
return digit_height, digit_width, col_offset, row_offset
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
def add_special_offset(digit_row):
|
| 169 |
+
"""Add extra offset depending on specific digit row
|
| 170 |
+
|
| 171 |
+
unfortunately the rows are not spaced out equally, whenever the .svg file was created
|
| 172 |
+
this fixes it except for 3 special situations. There is one pixel off (on top) for digit_row:
|
| 173 |
+
7, 6, 1
|
| 174 |
+
It seems like the digit height is actually 1 pixel smaller than it should be... but that's ok. it is such
|
| 175 |
+
a small error, it won't be too noticeable I bet
|
| 176 |
+
Note that all the digits on this row will have the small pixel offset
|
| 177 |
+
"""
|
| 178 |
+
|
| 179 |
+
additional_offset = 0
|
| 180 |
+
if (digit_row == 0):
|
| 181 |
+
additional_offset = 0
|
| 182 |
+
elif (digit_row == 1):
|
| 183 |
+
additional_offset = 0
|
| 184 |
+
elif (digit_row == 2):
|
| 185 |
+
additional_offset = 1
|
| 186 |
+
elif (digit_row == 3):
|
| 187 |
+
additional_offset = 1
|
| 188 |
+
elif (digit_row == 4):
|
| 189 |
+
additional_offset = 2
|
| 190 |
+
elif (digit_row == 5):
|
| 191 |
+
additional_offset = 2
|
| 192 |
+
elif (digit_row == 6):
|
| 193 |
+
additional_offset = 2
|
| 194 |
+
elif (digit_row == 7):
|
| 195 |
+
additional_offset = 2
|
| 196 |
+
else:
|
| 197 |
+
raise(Exception("Invalid digit row: ", digit_row))
|
| 198 |
+
|
| 199 |
+
return additional_offset
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
def apply_segment_thresholding(cropped_digit, digit_row, digit_col):
|
| 203 |
+
"""Threshold segment pixels and reduce brightness of non-segment pixels"""
|
| 204 |
+
# R and B were again swapped
|
| 205 |
+
cropped_digit_fixed_rgba = cv.cvtColor(cropped_digit[digit_row,digit_col,...], cv.COLOR_BGRA2RGBA)
|
| 206 |
+
|
| 207 |
+
# R and B are again swapped
|
| 208 |
+
(b, g, r, a) = cv.split(cropped_digit_fixed_rgba)
|
| 209 |
+
|
| 210 |
+
segment_mask_r_gt_g = r > g # advanced boolean indices
|
| 211 |
+
segment_mask_r_gt_b = r > b # advanced boolean indices
|
| 212 |
+
|
| 213 |
+
segment_mask_r = np.logical_and(segment_mask_r_gt_g, segment_mask_r_gt_b)
|
| 214 |
+
r[segment_mask_r] = 255 # this should already be the case
|
| 215 |
+
g[segment_mask_r] = 0
|
| 216 |
+
b[segment_mask_r] = 0
|
| 217 |
+
|
| 218 |
+
# now we can reduce the intensity a little for the pixels that aren't included in this selection
|
| 219 |
+
# basically this will be all the non-segment pixels
|
| 220 |
+
r[np.logical_not(segment_mask_r)] = r[np.logical_not(segment_mask_r)]*0.25
|
| 221 |
+
g[np.logical_not(segment_mask_r)] = g[np.logical_not(segment_mask_r)]*0.25
|
| 222 |
+
b[np.logical_not(segment_mask_r)] = b[np.logical_not(segment_mask_r)]*0.25
|
| 223 |
+
|
| 224 |
+
# remerge in the same order that we split
|
| 225 |
+
cropped_digit_fixed_rgba = cv.merge((b, g, r, a))
|
| 226 |
+
|
| 227 |
+
return cropped_digit_fixed_rgba
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
def write_img(cropped_digit_fixed_rgba, digit_row, digit_col):
|
| 231 |
+
"""Add background and write image"""
|
| 232 |
+
|
| 233 |
+
# https://stackoverflow.com/questions/53732747/set-white-background-for-a-png-instead-of-transparency-with-opencv
|
| 234 |
+
background_mask = cropped_digit_fixed_rgba[...,3] == 0 # get indexes of where alpha channel is transparent
|
| 235 |
+
cropped_digit_fixed_rgba[background_mask] = [0, 0, 0, 0] # use advanced boolean indexing and set background color
|
| 236 |
+
cropped_digit_new_background = cv.cvtColor(cropped_digit_fixed_rgba, cv.COLOR_BGRA2BGR) # we don't need alpha channel anymore
|
| 237 |
+
|
| 238 |
+
os.makedirs("images/extracted", exist_ok=True)
|
| 239 |
+
cv.imwrite(f"images/extracted/{digit_row*16 + digit_col}.png", cropped_digit_new_background)
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
def extract_digit(img, digit_location, num_dig_rows=8, num_dig_cols=16, verbose=False):
|
| 243 |
+
"""Iterate through the grid image and write each image to an output file"""
|
| 244 |
+
|
| 245 |
+
digit_height, digit_width, col_offset, row_offset = calculate_pixel_locations(digit_location, verbose)
|
| 246 |
+
|
| 247 |
+
# 128 digits, with pixels of digit_height by digit_width, for all 4 channels
|
| 248 |
+
cropped_digit = np.zeros((num_dig_rows, num_dig_cols, digit_height, digit_width, 4), dtype=np.uint8)
|
| 249 |
+
|
| 250 |
+
for digit_row in range(cropped_digit.shape[0]):
|
| 251 |
+
for digit_col in range(cropped_digit.shape[1]):
|
| 252 |
+
|
| 253 |
+
additional_offset = add_special_offset(digit_row)
|
| 254 |
+
|
| 255 |
+
row_grid_start = row_offset*(2*digit_row + 1) + digit_height*(digit_row) + additional_offset
|
| 256 |
+
row_grid_end = row_grid_start+digit_height
|
| 257 |
+
|
| 258 |
+
col_grid_start = col_offset*(2*digit_col + 1) + digit_width*(digit_col)
|
| 259 |
+
col_grid_end = col_grid_start + digit_width
|
| 260 |
+
|
| 261 |
+
cropped_digit[digit_row,digit_col,...] = img[row_grid_start:row_grid_end,col_grid_start:col_grid_end,:]
|
| 262 |
+
|
| 263 |
+
cropped_digit_fixed_rgba = apply_segment_thresholding(cropped_digit, digit_row, digit_col)
|
| 264 |
+
|
| 265 |
+
write_img(cropped_digit_fixed_rgba, digit_row, digit_col)
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
cropped_digit_grid = np.zeros((num_dig_rows*digit_height,num_dig_cols*digit_width,4),dtype=np.uint8)
|
| 269 |
+
|
| 270 |
+
# there's probably a way to do this with numpy functions, I'm just not sure how
|
| 271 |
+
# I need to concatenate in 2 directions at the same time
|
| 272 |
+
for row in range(num_dig_rows) :
|
| 273 |
+
cropped_digit_grid[row*digit_height:digit_height*(1+row),...] = np.concatenate(cropped_digit[row,...],axis=1)
|
| 274 |
+
|
| 275 |
+
return cropped_digit_grid
|
| 276 |
+
|
| 277 |
+
|
| 278 |
+
def plot_img(img, cropped_digit_grid):
|
| 279 |
+
"""Use matplotlib to plot extraction results"""
|
| 280 |
+
|
| 281 |
+
plt.figure(figsize=(20,8)) # just to get full-screen
|
| 282 |
+
|
| 283 |
+
plt.subplot(221) # 2 row, 2 columns, 1st index
|
| 284 |
+
plt.imshow(img)
|
| 285 |
+
plt.title("7 segment RGBA")
|
| 286 |
+
|
| 287 |
+
plt.subplot(222)
|
| 288 |
+
plt.imshow(cropped_digit_grid, cmap='gray')
|
| 289 |
+
plt.title("cropped_digit_grid")
|
| 290 |
+
|
| 291 |
+
plt.subplot(223)
|
| 292 |
+
cropped_digit_processed = cv.imread("images/extracted/1.png", flags=cv.IMREAD_UNCHANGED)
|
| 293 |
+
cropped_digit_processed = cv.cvtColor(cropped_digit_processed, cv.COLOR_RGBA2BGRA)
|
| 294 |
+
plt.imshow(cropped_digit_processed)
|
| 295 |
+
plt.title("cropped_digit_processed[1]")
|
| 296 |
+
|
| 297 |
+
plt.subplot(224)
|
| 298 |
+
cropped_digit_processed = cv.imread("images/extracted/75.png", flags=cv.IMREAD_UNCHANGED)
|
| 299 |
+
cropped_digit_processed = cv.cvtColor(cropped_digit_processed, cv.COLOR_RGBA2BGRA)
|
| 300 |
+
plt.imshow(cropped_digit_processed)
|
| 301 |
+
plt.title("cropped_digit_processed[75]")
|
| 302 |
+
|
| 303 |
+
plt.show()
|
| 304 |
+
|
| 305 |
+
def extract():
|
| 306 |
+
|
| 307 |
+
DEBUG = False
|
| 308 |
+
NUM_DIG_ROWS = 8 # number of 7 segment digits in grid img per row
|
| 309 |
+
NUM_DIG_COLS = 16 # number of 7 segment digits in grid img per column
|
| 310 |
+
OUTPUT_IMAGE_ASPECT_RATIO = 70/123 # this is the default aspect ratio from the extracted image
|
| 311 |
+
OUTPUT_IMAGE_HEIGHT = 30 # this is how big the output tile is in the Y axis
|
| 312 |
+
OUTPUT_IMAGE_WIDTH = OUTPUT_IMAGE_HEIGHT*OUTPUT_IMAGE_ASPECT_RATIO
|
| 313 |
+
INPUT_IMAGE_RESIZE_FACTOR = 0.5
|
| 314 |
+
FLAG_RESIZE_ON = True
|
| 315 |
+
assert(NUM_DIG_COLS*NUM_DIG_ROWS == 2**7) # 7 segments in on/off combination
|
| 316 |
+
|
| 317 |
+
|
| 318 |
+
seven_seg_grid_img = load_img("images/seven_segment_grid.png", FLAG_RESIZE_ON, INPUT_IMAGE_RESIZE_FACTOR)
|
| 319 |
+
seven_seg_grid_img = apply_img_thresholding(seven_seg_grid_img)
|
| 320 |
+
digit_location = find_digits_in_grid(seven_seg_grid_img)
|
| 321 |
+
cropped_digit_grid = extract_digit(seven_seg_grid_img, digit_location, NUM_DIG_ROWS, NUM_DIG_COLS, DEBUG)
|
| 322 |
+
plot_img(seven_seg_grid_img, cropped_digit_grid)
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
|
| 328 |
+
if __name__ == "__main__":
|
| 329 |
+
extract()
|