Spaces:
Sleeping
Sleeping
Commit
·
a0612ff
1
Parent(s):
a73c25c
filter less the cards
Browse files
app.py
CHANGED
|
@@ -85,47 +85,47 @@ def detect_cards_and_sum(image, game):
|
|
| 85 |
H, W = annotated.shape[:2]
|
| 86 |
img_area = float(H * W)
|
| 87 |
|
| 88 |
-
# ---
|
| 89 |
gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
|
| 90 |
-
|
| 91 |
-
edges = cv2.Canny(
|
| 92 |
edges = cv2.dilate(edges, np.ones((3, 3), np.uint8), iterations=1)
|
| 93 |
|
| 94 |
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
| 95 |
|
|
|
|
|
|
|
|
|
|
| 96 |
values = []
|
| 97 |
-
drawn_boxes = 0
|
| 98 |
|
| 99 |
for cnt in contours:
|
| 100 |
-
|
| 101 |
-
rect = cv2.minAreaRect(cnt) # (center, (w, h), angle)
|
| 102 |
(cx, cy), (rw, rh), _ = rect
|
| 103 |
if rw == 0 or rh == 0:
|
| 104 |
continue
|
| 105 |
|
| 106 |
-
box = cv2.boxPoints(rect)
|
| 107 |
box = np.int32(box)
|
| 108 |
|
| 109 |
-
# use bounding area (more stable with edges than contour area)
|
| 110 |
box_area = rw * rh
|
| 111 |
-
if box_area < 0.
|
| 112 |
continue # too small or too big to be a card
|
| 113 |
|
| 114 |
-
# aspect ratio (card ~ 1.4
|
| 115 |
long_side = max(rw, rh)
|
| 116 |
short_side = min(rw, rh)
|
| 117 |
ratio = long_side / short_side
|
| 118 |
-
if ratio < 1.
|
| 119 |
continue
|
| 120 |
|
| 121 |
# rectangularity: contour area close to its minAreaRect area
|
| 122 |
cnt_area = cv2.contourArea(cnt)
|
| 123 |
-
if cnt_area / box_area < 0.
|
| 124 |
continue
|
| 125 |
|
| 126 |
# perspective warp to a canonical card size (2:3 ratio)
|
| 127 |
dst_w, dst_h = 300, 450
|
| 128 |
-
M = cv2.getPerspectiveTransform(order_points(box),
|
| 129 |
np.array([[0, 0],
|
| 130 |
[dst_w-1, 0],
|
| 131 |
[dst_w-1, dst_h-1],
|
|
@@ -151,9 +151,8 @@ def detect_cards_and_sum(image, game):
|
|
| 151 |
ty = int(moments["m01"] / moments["m00"])
|
| 152 |
else:
|
| 153 |
tx, ty = int(cx), int(cy)
|
| 154 |
-
cv2.putText(annotated, str(val), (tx
|
| 155 |
cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 255), 3)
|
| 156 |
-
drawn_boxes += 1
|
| 157 |
|
| 158 |
if not values:
|
| 159 |
# return the annotated image anyway so you can see what was (not) detected
|
|
@@ -166,6 +165,7 @@ def detect_cards_and_sum(image, game):
|
|
| 166 |
|
| 167 |
|
| 168 |
|
|
|
|
| 169 |
# Gradio UI
|
| 170 |
with gr.Blocks() as demo:
|
| 171 |
gr.Markdown("## Card Value Detector (Skyjo / Flip7)")
|
|
|
|
| 85 |
H, W = annotated.shape[:2]
|
| 86 |
img_area = float(H * W)
|
| 87 |
|
| 88 |
+
# --- edge map ---
|
| 89 |
gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
|
| 90 |
+
blur = cv2.GaussianBlur(gray, (5, 5), 0)
|
| 91 |
+
edges = cv2.Canny(blur, 50, 150)
|
| 92 |
edges = cv2.dilate(edges, np.ones((3, 3), np.uint8), iterations=1)
|
| 93 |
|
| 94 |
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
| 95 |
|
| 96 |
+
# sort largest to smallest
|
| 97 |
+
contours = sorted(contours, key=cv2.contourArea, reverse=True)
|
| 98 |
+
|
| 99 |
values = []
|
|
|
|
| 100 |
|
| 101 |
for cnt in contours:
|
| 102 |
+
rect = cv2.minAreaRect(cnt)
|
|
|
|
| 103 |
(cx, cy), (rw, rh), _ = rect
|
| 104 |
if rw == 0 or rh == 0:
|
| 105 |
continue
|
| 106 |
|
| 107 |
+
box = cv2.boxPoints(rect)
|
| 108 |
box = np.int32(box)
|
| 109 |
|
|
|
|
| 110 |
box_area = rw * rh
|
| 111 |
+
if box_area < 0.002 * img_area or box_area > 0.9 * img_area:
|
| 112 |
continue # too small or too big to be a card
|
| 113 |
|
| 114 |
+
# aspect ratio (card ~ 1.4�1.8 between long/short edges)
|
| 115 |
long_side = max(rw, rh)
|
| 116 |
short_side = min(rw, rh)
|
| 117 |
ratio = long_side / short_side
|
| 118 |
+
if ratio < 1.1 or ratio > 2.2:
|
| 119 |
continue
|
| 120 |
|
| 121 |
# rectangularity: contour area close to its minAreaRect area
|
| 122 |
cnt_area = cv2.contourArea(cnt)
|
| 123 |
+
if cnt_area / box_area < 0.5:
|
| 124 |
continue
|
| 125 |
|
| 126 |
# perspective warp to a canonical card size (2:3 ratio)
|
| 127 |
dst_w, dst_h = 300, 450
|
| 128 |
+
M = cv2.getPerspectiveTransform(order_points(box),
|
| 129 |
np.array([[0, 0],
|
| 130 |
[dst_w-1, 0],
|
| 131 |
[dst_w-1, dst_h-1],
|
|
|
|
| 151 |
ty = int(moments["m01"] / moments["m00"])
|
| 152 |
else:
|
| 153 |
tx, ty = int(cx), int(cy)
|
| 154 |
+
cv2.putText(annotated, str(val), (tx-10, ty-10),
|
| 155 |
cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 255), 3)
|
|
|
|
| 156 |
|
| 157 |
if not values:
|
| 158 |
# return the annotated image anyway so you can see what was (not) detected
|
|
|
|
| 165 |
|
| 166 |
|
| 167 |
|
| 168 |
+
|
| 169 |
# Gradio UI
|
| 170 |
with gr.Blocks() as demo:
|
| 171 |
gr.Markdown("## Card Value Detector (Skyjo / Flip7)")
|