Spaces:
Sleeping
Sleeping
move decorators to main function
Browse files
app.py
CHANGED
@@ -34,12 +34,8 @@ DIFFICULY = {"easy": 0.18, "medium": 0.1, "hard": 0.05}
|
|
34 |
DIFFICULY_LEVELS = list(DIFFICULY.keys())
|
35 |
|
36 |
|
37 |
-
@interactive(
|
38 |
-
seed=(45, [0, 100], "Puzzle seed"),
|
39 |
-
difficulty=(DIFFICULY_LEVELS[0], DIFFICULY_LEVELS, "Difficulty")
|
40 |
-
)
|
41 |
def generate_random_puzzle(
|
42 |
-
seed: int =
|
43 |
difficulty: str = DIFFICULY_LEVELS[0],
|
44 |
context: dict = {}
|
45 |
):
|
@@ -72,10 +68,6 @@ def create_puzzle(
|
|
72 |
return out, crop
|
73 |
|
74 |
|
75 |
-
@interactive(
|
76 |
-
flip=(False, "Flip Image"),
|
77 |
-
mirror=(False, "Mirror Image"),
|
78 |
-
)
|
79 |
def flip_mirror_piece(
|
80 |
piece: np.ndarray,
|
81 |
flip: bool = False,
|
@@ -87,10 +79,6 @@ def flip_mirror_piece(
|
|
87 |
return flip_image(piece.copy(), flip=flip, mirror=mirror)
|
88 |
|
89 |
|
90 |
-
@interactive(
|
91 |
-
pos_x=(0.5, [0.1, 0.9, 0.005], "Position X", ["left", "right"]),
|
92 |
-
pos_y=(0.5, [0.1, 0.9, 0.005], "Position Y", ["up", "down"]),
|
93 |
-
)
|
94 |
def place_puzzle(
|
95 |
puzzle: np.ndarray,
|
96 |
piece: np.ndarray,
|
@@ -111,11 +99,9 @@ TOLERANCES = {"low": 0.01, "medium": 0.02, "high": 0.05}
|
|
111 |
TOLERANCE_LEVELS = list(TOLERANCES.keys())
|
112 |
|
113 |
|
114 |
-
@interactive(
|
115 |
-
tolerance=(TOLERANCE_LEVELS[0], TOLERANCE_LEVELS, "Tolerance")
|
116 |
-
)
|
117 |
def check_puzzle(tolerance: str = "low", context: dict = {}) -> None:
|
118 |
-
"""Check if the user placed the puzzle piece correctly.
|
|
|
119 |
x_gt, y_gt = context["puzzle_pos"]
|
120 |
flip_gt, mirror_gt = context["puzzle_flip_mirror"]
|
121 |
x, y = context["user_pos"]
|
@@ -133,7 +119,8 @@ def display_feedback(
|
|
133 |
nok_ribbon: np.ndarray,
|
134 |
context: dict = {}
|
135 |
) -> np.ndarray:
|
136 |
-
|
|
|
137 |
ribbon = ok_ribbon if success else nok_ribbon
|
138 |
out = np.hstack([puzzle, ribbon[:puzzle.shape[0], ...]])
|
139 |
return out
|
@@ -152,19 +139,51 @@ def captcha_pipe(inp):
|
|
152 |
puzzle = display_feedback(puzzle, ok_ribbon, nok_ribbon)
|
153 |
return puzzle
|
154 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
|
156 |
if __name__ == "__main__":
|
157 |
import argparse
|
158 |
parser = argparse.ArgumentParser()
|
159 |
parser.add_argument("-b", "--backend", default="gradio",
|
160 |
-
choices=["gradio", "qt"], type=str)
|
|
|
|
|
|
|
|
|
161 |
args = parser.parse_args()
|
162 |
-
markdown_description = "# Code to build this app on gradio \n"
|
|
|
|
|
163 |
markdown_description += "```python\n"+open(__file__, 'r').read()+"```"
|
164 |
img = Image.load_image("sample.jpg")
|
165 |
-
|
166 |
-
gui=args.backend,
|
167 |
-
cache=True,
|
168 |
-
markdown_description=markdown_description
|
169 |
-
)(captcha_pipe)
|
170 |
-
captcha_pipe_interactive(img)
|
|
|
34 |
DIFFICULY_LEVELS = list(DIFFICULY.keys())
|
35 |
|
36 |
|
|
|
|
|
|
|
|
|
37 |
def generate_random_puzzle(
|
38 |
+
seed: int = 43,
|
39 |
difficulty: str = DIFFICULY_LEVELS[0],
|
40 |
context: dict = {}
|
41 |
):
|
|
|
68 |
return out, crop
|
69 |
|
70 |
|
|
|
|
|
|
|
|
|
71 |
def flip_mirror_piece(
|
72 |
piece: np.ndarray,
|
73 |
flip: bool = False,
|
|
|
79 |
return flip_image(piece.copy(), flip=flip, mirror=mirror)
|
80 |
|
81 |
|
|
|
|
|
|
|
|
|
82 |
def place_puzzle(
|
83 |
puzzle: np.ndarray,
|
84 |
piece: np.ndarray,
|
|
|
99 |
TOLERANCE_LEVELS = list(TOLERANCES.keys())
|
100 |
|
101 |
|
|
|
|
|
|
|
102 |
def check_puzzle(tolerance: str = "low", context: dict = {}) -> None:
|
103 |
+
"""Check if the user placed the puzzle piece correctly.
|
104 |
+
Store the result in the context."""
|
105 |
x_gt, y_gt = context["puzzle_pos"]
|
106 |
flip_gt, mirror_gt = context["puzzle_flip_mirror"]
|
107 |
x, y = context["user_pos"]
|
|
|
119 |
nok_ribbon: np.ndarray,
|
120 |
context: dict = {}
|
121 |
) -> np.ndarray:
|
122 |
+
"""Display green/red ribbon on the right side of the puzzle."""
|
123 |
+
success = context.get("success", False)
|
124 |
ribbon = ok_ribbon if success else nok_ribbon
|
125 |
out = np.hstack([puzzle, ribbon[:puzzle.shape[0], ...]])
|
126 |
return out
|
|
|
139 |
puzzle = display_feedback(puzzle, ok_ribbon, nok_ribbon)
|
140 |
return puzzle
|
141 |
|
142 |
+
# add interactivity
|
143 |
+
# -----------------
|
144 |
+
|
145 |
+
|
146 |
+
def main(img: np.ndarray, backend="gradio", debug: bool = False):
|
147 |
+
# If debug mode, add interactive sliders to tune the puzzle generation
|
148 |
+
# and help the "game master" design a feasible puzzle.
|
149 |
+
if debug:
|
150 |
+
interactive(
|
151 |
+
tolerance=(TOLERANCE_LEVELS[0], TOLERANCE_LEVELS, "Tolerance")
|
152 |
+
)(check_puzzle)
|
153 |
+
interactive(
|
154 |
+
seed=(43, [0, 100], "Puzzle seed"),
|
155 |
+
difficulty=(DIFFICULY_LEVELS[0], DIFFICULY_LEVELS, "Difficulty")
|
156 |
+
)(generate_random_puzzle)
|
157 |
+
interactive(
|
158 |
+
pos_x=(0.5, [0.1, 0.9, 0.005], "Position X", ["left", "right"]),
|
159 |
+
pos_y=(0.5, [0.1, 0.9, 0.005], "Position Y", ["up", "down"]),
|
160 |
+
)(place_puzzle)
|
161 |
+
# left, right, up, down will only supported when using the Qt backend
|
162 |
+
interactive(
|
163 |
+
flip=(False, "Flip Image"),
|
164 |
+
mirror=(False, "Mirror Image"),
|
165 |
+
)(flip_mirror_piece)
|
166 |
+
captcha_pipe_interactive = interactive_pipeline(
|
167 |
+
gui=backend,
|
168 |
+
cache=True,
|
169 |
+
markdown_description=markdown_description
|
170 |
+
)(captcha_pipe)
|
171 |
+
captcha_pipe_interactive(img)
|
172 |
+
|
173 |
|
174 |
if __name__ == "__main__":
|
175 |
import argparse
|
176 |
parser = argparse.ArgumentParser()
|
177 |
parser.add_argument("-b", "--backend", default="gradio",
|
178 |
+
choices=["gradio", "qt", "mpl"], type=str)
|
179 |
+
parser.add_argument(
|
180 |
+
"-d", "--debug", action="store_true",
|
181 |
+
help="Debug mode (to tune difficulty and tolerance)"
|
182 |
+
)
|
183 |
args = parser.parse_args()
|
184 |
+
markdown_description = "# Code to build this app on gradio \n\n"
|
185 |
+
markdown_description += "In local, try using `python app.py --backend qt --debug` to get the best experience with keyboard support aswell \n\n"
|
186 |
+
markdown_description += "Please note that matplobi`--backend mpl` is also functional although it won't look as good\n\n"
|
187 |
markdown_description += "```python\n"+open(__file__, 'r').read()+"```"
|
188 |
img = Image.load_image("sample.jpg")
|
189 |
+
main(img, backend=args.backend, debug=args.debug)
|
|
|
|
|
|
|
|
|
|