class FieldView(ImageCanvas): def __init__(self, root, width, height): super().__init__(root, width, height) self.color_table = Colors() self.current_level = None self.color_table.setLevel(0) def updateField(self, field, level): success, level = tryGetInt(level) if success and level != self.current_level: self.color_table.setLevel(level) field = convert_field(field) lut = np.array(self.color_table.colors) image = lut[field] # TODO: check out lut.take which might be faster image = Image.fromarray(image, "RGB") image = image.resize((self.width, self.height), Image.NEAREST) self.updateImage(image)
def runFor(src, level): img = Image.open(src) scaled_img_old = img.resize((10, 20), Image.NEAREST) o_width = img.width + img.height o_height = img.height * 2 result_img = Image.new("RGB", (o_width, o_height), (0, 0, 0, 255)) result_img.paste(img, (0, 0)) result_img.paste(img, (0, img.height)) result_img.paste( scaled_img_old.resize((floor(img.height / 2), img.height), Image.NEAREST), (img.width, 0), ) scaled_img_new = Image.new("RGB", (10, 20), (0, 0, 0, 255)) res_img_old = Image.new("RGB", (10, 20), (0, 0, 0, 255)) res_img_new = Image.new("RGB", (10, 20), (0, 0, 0, 255)) spanx = img.width / 10 spany = img.height / 20 np_img = np.array(img, dtype=np.uint16) np_scaled_img = np.array(scaled_img_old, dtype=np.uint8) colors = Colors() colors.setLevel(level) cols = [colors.black, colors.white, colors.color1, colors.color2] for y in range(20): for x in range(10): pix = np_scaled_img[y, x] col_old = getColor(pix, cols) res_img_old.putpixel((x, y), tuple(cols[col_old])) xidx = round(spanx * (x + 0.5)) yidx = round(spany * (y + 0.5)) target = np_img[yidx - 1:yidx + 2, xidx - 1:xidx + 2] pix = [0, 0, 0] # grab 9 pixels in a 3x3 square # and compute average for i in range(3): for j in range(3): tmp = target[i, j] pix[0] += tmp[0] * tmp[0] pix[1] += tmp[1] * tmp[1] pix[2] += tmp[2] * tmp[2] pix[0] = int(sqrt(pix[0] / 9)) pix[1] = int(sqrt(pix[1] / 9)) pix[2] = int(sqrt(pix[2] / 9)) col_new = getColor(pix, cols) scaled_img_new.putpixel((x, y), tuple(pix)) res_img_new.putpixel((x, y), tuple(cols[col_new])) result_img.paste( scaled_img_new.resize((floor(img.height / 2), img.height), Image.NEAREST), (img.width, img.height), ) result_img.paste( res_img_old.resize((floor(img.height / 2), img.height), Image.NEAREST), (img.width + floor(img.height / 2), 0), ) result_img.paste( res_img_new.resize((floor(img.height / 2), img.height), Image.NEAREST), (img.width + floor(img.height / 2), img.height), ) result_img.show()
def runFor(src, level): img = Image.open(src) scaled_img_old = img.resize((10, 20), Image.NEAREST) o_width = img.width + img.height o_height = img.height * 2 result_img = Image.new("RGB", (o_width, o_height), (0, 0, 0, 255)) result_img.paste(img, (0, 0)) result_img.paste(img, (0, img.height)) result_img.paste( scaled_img_old.resize((floor(img.height / 2), img.height), Image.NEAREST), (img.width, 0), ) scaled_img_new = Image.new("RGB", (10, 20), (0, 0, 0, 255)) res_img_old = Image.new("RGB", (10, 20), (0, 0, 0, 255)) res_img_new = Image.new("RGB", (10, 20), (0, 0, 0, 255)) spanx = img.width / 10 spany = img.height / 20 np_img = np.array(img, dtype=np.uint16) np_scaled_img = np.array(scaled_img_old, dtype=np.uint8) colors = Colors() colors.setLevel(level) for y in range(20): for x in range(10): pix = np_scaled_img[y, x] col_old = colors.getClosestColorIndex(pix) res_img_old.putpixel((x, y), tuple(colors.getColorByIndex(col_old))) xidx = round(spanx * (x + 0.5)) yidx = round(spany * (y + 0.5)) pix = [0, 0, 0] # grab 9 pixels in a 3x3 square # and compute average for i in range(xidx - 1, xidx + 2): for j in range(yidx - 1, yidx + 2): tmp = np_img[j, i] pix[0] += tmp[0] * tmp[0] pix[1] += tmp[1] * tmp[1] pix[2] += tmp[2] * tmp[2] pix[0] = round(sqrt(pix[0] / 9)) pix[1] = round(sqrt(pix[1] / 9)) pix[2] = round(sqrt(pix[2] / 9)) col_new = colors.getClosestColorIndex(pix) scaled_img_new.putpixel((x, y), tuple(pix)) res_img_new.putpixel((x, y), tuple(colors.getColorByIndex(col_new))) result_img.paste( scaled_img_new.resize((floor(img.height / 2), img.height), Image.NEAREST), (img.width, img.height), ) result_img.paste( res_img_old.resize((floor(img.height / 2), img.height), Image.NEAREST), (img.width + floor(img.height / 2), 0), ) result_img.paste( res_img_new.resize((floor(img.height / 2), img.height), Image.NEAREST), (img.width + floor(img.height / 2), img.height), ) result_img.show()
def getColors(level, field): img = Image.open(field) res_img = Image.new( "RGBA", (img.width, img.height), (0, 0, 0, 255), ) res_img.paste(img.convert("RGBA"), (img.width * 0, 0)) # nes pix size, block span and capture are only valid on perfect calibration # perfect calibration implies capturing the right and bottom black edges # still, since we're capturing a safe zone, things should still work with small discrepancies nes_pixels_to_sample = ( (2, 4.5), (4.5, 2), (4.5, 4.5), ) nes_pix_xsize = img.width / 80 nes_pix_ysize = img.height / 160 spanx = nes_pix_xsize * 8 spany = nes_pix_ysize * 8 corner_highlight = Image.new("RGBA", (1, 1), (255, 0, 0, 128)) capture_highlight = Image.new("RGBA", (1, 1), (0, 255, 0, 128)) np_img = np.array(img, dtype=np.uint16) colors = Colors() colors.setLevel(level) color_instances = ([], [], [], []) for y in range(20): for x in range(10): xidx = spanx * x yidx = spany * y # print the top-left corner res_img.paste(corner_highlight, (round(xidx), round(yidx)), corner_highlight) pixels = [] for offsetx, offsety in nes_pixels_to_sample: right = round(xidx + nes_pix_xsize * offsetx) top = round(yidx + nes_pix_ysize * offsety) left = round(xidx + nes_pix_xsize * (offsetx + 1)) bottom = round(yidx + nes_pix_ysize * (offsety + 1)) cap = capture_highlight.resize((left - right, bottom - top)) res_img.paste(cap, (right, top), cap) # grab all pixels in the capture area for i in range(right, left): for j in range(top, bottom): pixels.append(np_img[j, i]) pix = getAverageColor(pixels) col_index = colors.getClosestColorIndex(pix) color_instances[col_index].extend(pixels) if level == 0: res_img.convert("RGB").resize((img.width * 3, img.height * 3)).show() # average the colors col1 = getAverageColor(color_instances[2]) col2 = getAverageColor(color_instances[3]) return col1, col2
# expecting all 4 colors as np.array(dtype=np.uint8) def parseImage(img, colors): img = np.array(img, dtype=np.uint8) return parseImage2(img, colors.black, colors.white, colors.color1, colors.color2) if __name__ == "__main__": # run this from root directory as "python -m nestris_ocr.ocr_algo.board" from nestris_ocr.colors import Colors import nestris_ocr.utils.time as time img = Image.open("nestris_ocr/assets/test/board_lvl7.png") colors = Colors() colors.setLevel(7) iterations = 25000 start = time.time() for i in range(iterations): parseImage(img, colors) elapsed = time.time() - start print(elapsed, elapsed / iterations) print(parseImage(img, colors))