rough playable version finished
This commit is contained in:
131
solve.py
Normal file
131
solve.py
Normal file
@@ -0,0 +1,131 @@
|
||||
from PIL import Image
|
||||
from pyzbar.pyzbar import decode
|
||||
import itertools
|
||||
from math import perm
|
||||
from tqdm import tqdm
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
NUM_PIECES_WIDTH = 4
|
||||
NUM_PIECES_HEIGHT = 3
|
||||
BOX_SIZE = 2
|
||||
TILE = 78
|
||||
# 7x7 finder, upscaled to 14x14 (black=1, white=0)
|
||||
TEMPLATE = np.kron(np.array([
|
||||
[1,1,1,1,1,1,1],
|
||||
[1,0,0,0,0,0,1],
|
||||
[1,0,1,1,1,0,1],
|
||||
[1,0,1,1,1,0,1],
|
||||
[1,0,1,1,1,0,1],
|
||||
[1,0,0,0,0,0,1],
|
||||
[1,1,1,1,1,1,1],
|
||||
], dtype=np.uint8), np.ones((BOX_SIZE, BOX_SIZE), np.uint8))
|
||||
H, W = TEMPLATE.shape # 14x14
|
||||
|
||||
|
||||
def decodeQRCode(image : Image.Image) -> str | None:
|
||||
# Decode the QR code
|
||||
decoded_objects = decode(image)
|
||||
|
||||
# Check if any QR code was found
|
||||
if decoded_objects:
|
||||
# Iterate through all the detected QR codes and print their data
|
||||
for obj in decoded_objects:
|
||||
return obj.data.decode("utf-8")
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def cut_pieces(image):
|
||||
# Get the size of the image
|
||||
width, height = image.size
|
||||
|
||||
# Calculate the size of each grid cell
|
||||
cell_width = width // NUM_PIECES_WIDTH
|
||||
cell_height = height // NUM_PIECES_HEIGHT
|
||||
|
||||
pieces = []
|
||||
|
||||
# Split the original image into 12 pieces
|
||||
for i in range(NUM_PIECES_WIDTH * NUM_PIECES_HEIGHT):
|
||||
# Calculate the coordinates of the current grid cell
|
||||
x1 = (i % NUM_PIECES_WIDTH) * cell_width
|
||||
y1 = (i // NUM_PIECES_WIDTH) * cell_height
|
||||
x2 = x1 + cell_width
|
||||
y2 = y1 + cell_height
|
||||
|
||||
# Crop the corresponding part of the original image
|
||||
cropped_piece = image.crop((x1, y1, x2, y2))
|
||||
pieces.append(cropped_piece)
|
||||
|
||||
return pieces
|
||||
|
||||
|
||||
def to_bw01(img):
|
||||
# Force 1-bit, then map black->1, white->0
|
||||
a = np.array(img.convert("1")) # {0,255}
|
||||
return (a == 0).astype(np.uint8)
|
||||
|
||||
|
||||
def finder_corner_exact(tile_bw):
|
||||
crops = {
|
||||
'TL': tile_bw[0:H, 0:W ],
|
||||
'TR': tile_bw[0:H, TILE-W:TILE ],
|
||||
'BL': tile_bw[TILE-H:TILE, 0:W ],
|
||||
'BR': tile_bw[TILE-H:TILE, TILE-W:TILE ],
|
||||
}
|
||||
for corner, crop in crops.items():
|
||||
if np.array_equal(crop, TEMPLATE):
|
||||
return corner
|
||||
return None # no exact finder in this tile
|
||||
|
||||
|
||||
def three_tiles_with_finders(tiles):
|
||||
hits = []
|
||||
for tile in tiles:
|
||||
corner = finder_corner_exact(to_bw01(tile))
|
||||
if corner is not None:
|
||||
hits.append((tile, corner))
|
||||
if len(hits) == 3:
|
||||
break
|
||||
return hits
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
img = Image.open("./scrambled_test_qr_code.png")
|
||||
new_image = Image.new("RGB", (img.height, img.height))
|
||||
|
||||
pieces = cut_pieces(img)
|
||||
corners = three_tiles_with_finders(pieces)
|
||||
|
||||
for tile, corner in corners:
|
||||
if corner == 'TL':
|
||||
new_image.paste(tile, (0,0))
|
||||
elif corner == 'TR':
|
||||
new_image.paste(tile, (156,0))
|
||||
elif corner == 'BL':
|
||||
new_image.paste(tile, (0,156))
|
||||
else:
|
||||
sys.exit()
|
||||
|
||||
|
||||
pieces = [piece for piece in pieces if piece not in [tile for tile, _ in corners]]
|
||||
assert len(pieces) == 9
|
||||
new_image.show()
|
||||
possible_combos = itertools.permutations(pieces, 6)
|
||||
num_possible_combos = perm(len(pieces), 6)
|
||||
print(f"Testing {num_possible_combos} combinations")
|
||||
|
||||
for a,b,c,d,e,f in tqdm(possible_combos, total=num_possible_combos):
|
||||
new_image.paste(a, (78, 0))
|
||||
new_image.paste(b, (0, 78))
|
||||
new_image.paste(c, (78, 78))
|
||||
new_image.paste(d, (156, 78))
|
||||
new_image.paste(e, (78, 156))
|
||||
new_image.paste(f, (156, 156))
|
||||
output = decodeQRCode(new_image)
|
||||
if output:
|
||||
print(output)
|
||||
|
||||
print(decodeQRCode(img))
|
||||
|
||||
Reference in New Issue
Block a user