Skip to content

Commit

Permalink
fix(single-mode): error when recognize status
Browse files Browse the repository at this point in the history
fix #39
  • Loading branch information
NateScarlet committed Jun 10, 2021
1 parent 7249f78 commit 8f2ece0
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 92 deletions.
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
.PHONY: default test lint
.PHONY: default test lint format

default: test lint
default: test format

test:
py -3.8 -m pytest auto_derby

lint:
py -3.8 -m black -t py38 --check --diff .

format:
py -3.8 -m black -t py38 .
34 changes: 23 additions & 11 deletions auto_derby/imagetools.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import cv2
import cv2.img_hash
import numpy as np
from PIL.Image import Image, fromarray
from PIL.Image import BICUBIC, BILINEAR, Image, fromarray


def md5(b_img: np.ndarray, *, save_path: Optional[Text] = None) -> Text:
Expand Down Expand Up @@ -158,8 +158,10 @@ def mix(a: np.ndarray, b: np.ndarray, a_mix: float) -> np.ndarray:
)


def bg_mask_by_outline(outline_img: np.ndarray) -> np.ndarray:
h, w = outline_img.shape[:2]
def border_flood_fill(
cv_img: np.ndarray, color: Tuple[int, ...] = (255,)
) -> np.ndarray:
h, w = cv_img.shape[:2]

border_points = (
*((0, i) for i in range(h)),
Expand All @@ -168,27 +170,37 @@ def bg_mask_by_outline(outline_img: np.ndarray) -> np.ndarray:
*((i, h - 1) for i in range(w)),
)

fill_mask_img = cv2.copyMakeBorder(outline_img, 1, 1, 1, 1, cv2.BORDER_CONSTANT)
bg_mask_img = np.zeros_like(outline_img)
fill_mask_img = cv2.copyMakeBorder(cv_img, 1, 1, 1, 1, cv2.BORDER_CONSTANT)
bg_mask_img = np.zeros_like(cv_img)
for i in border_points:
x, y = i
if outline_img[y, x] != 0:
if cv_img[y, x] != 0:
continue
cv2.floodFill(bg_mask_img, fill_mask_img, (x, y), (255,), 0, 0)
cv2.floodFill(bg_mask_img, fill_mask_img, (x, y), color, 0, 0)

return bg_mask_img


def resize_by_heihgt(img: Image, height: int) -> Image:
def bg_mask_by_outline(outline_img: np.ndarray) -> np.ndarray:
return border_flood_fill(outline_img)


def resize_by_heihgt(img: Image, height: int, *, resample: int = BICUBIC) -> Image:
w, h = img.width, img.height
w = round(height / h * w)
h = height
return img.resize((w, h))
return img.resize((w, h), resample=resample)


def fill_area(img: np.ndarray, color: Tuple[int, ...], *, size_lt: int):
def fill_area(
img: np.ndarray,
color: Tuple[int, ...],
*,
mode: int = cv2.RETR_EXTERNAL,
size_lt: int,
):
contours, _ = cv2.findContours(
(img * 255).astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE
(img * 255).astype(np.uint8), mode, cv2.CHAIN_APPROX_NONE
)
for i in contours:
size = cv2.contourArea(i)
Expand Down
46 changes: 12 additions & 34 deletions auto_derby/single_mode/context.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# -*- coding=UTF-8 -*-
# pyright: strict
from __future__ import annotations
import cv2
import numpy as np

import os
from typing import Text, Tuple

from PIL.Image import Image
import cast_unknown as cast
import cv2
import numpy as np
import PIL.ImageOps
from PIL.Image import Image
from PIL.Image import fromarray as image_from_array

from .. import ocr, imagetools, templates, template

import os
from .. import imagetools, ocr, template, templates


def _ocr_date(img: Image) -> Tuple[int, int, int]:
Expand Down Expand Up @@ -90,41 +90,19 @@ def _recognize_status(img: Image) -> Tuple[int, Text]:
cv_img = cv2.copyMakeBorder(cv_img, 4, 4, 4, 4, cv2.BORDER_CONSTANT, value=(255,))

blurred_img = cv2.medianBlur(cv_img, 7)
binary_img = cv2.adaptiveThreshold(

text_img = cv2.adaptiveThreshold(
blurred_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, -1
)

contours, hierarchy = cv2.findContours(
binary_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE
text_img = 255 - cast.instance(
np.maximum(text_img, imagetools.border_flood_fill(text_img)), np.ndarray
)
if not contours:
raise ValueError("_recognize_status: image is empty")

text_img = np.zeros_like(binary_img)

def _contour_level(h: np.ndarray) -> int:
_, _, _, parent = h
if parent < 0:
return 0
return _contour_level(hierarchy[0][parent]) + 1

for index, h in enumerate(hierarchy[0]):
level = _contour_level(h)
if level < 2:
continue
is_white = level % 2 == 0
if is_white and cv2.contourArea(contours[index]) < 160:
continue
color = (255,) if is_white else (0,)
cv2.drawContours(text_img, contours, index, thickness=cv2.FILLED, color=color)
if color == (0,):
# use white border
cv2.drawContours(text_img, contours, index, thickness=1, color=(255,))
text_img = cv2.medianBlur(text_img, 5)
imagetools.fill_area(text_img, (0,), mode=cv2.RETR_LIST, size_lt=40)

if os.getenv("DEBUG") == __name__:
cv2.imshow("cv_img", cv_img)
cv2.imshow("blurred_img", blurred_img)
cv2.imshow("binary_img", binary_img)
cv2.imshow("text_img", text_img)
cv2.waitKey()
cv2.destroyAllWindows()
Expand Down
19 changes: 19 additions & 0 deletions auto_derby/single_mode/context_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,22 @@ def test_update_by_character_detail_4():
assert ctx.head == ctx.STATUS_A, ctx.head
assert ctx.middle == ctx.STATUS_A, ctx.middle
assert ctx.last == ctx.STATUS_G, ctx.last


def test_update_by_character_detail_issue39():
img = PIL.Image.open(_TEST_DATA_PATH / "character_detail_issue39.png").convert("RGB")
ctx = Context()
ctx.update_by_character_detail(img)

assert ctx.turf == ctx.STATUS_A, ctx.turf
assert ctx.dart == ctx.STATUS_F, ctx.dart

assert ctx.sprint == ctx.STATUS_F, ctx.sprint
assert ctx.mile == ctx.STATUS_C, ctx.mile
assert ctx.intermediate == ctx.STATUS_A, ctx.intermediate
assert ctx.long == ctx.STATUS_A, ctx.long

assert ctx.lead == ctx.STATUS_G, ctx.lead
assert ctx.head == ctx.STATUS_A, ctx.head
assert ctx.middle == ctx.STATUS_A, ctx.middle
assert ctx.last == ctx.STATUS_F, ctx.last
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 15 additions & 20 deletions ocr_labels.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,6 @@
"0001c827fc7ffe7ffe7f8e6386418e418e61fe7ffeffbeff8c63800300030003": "",
"fefffefffeff803f801f800fc007c003e001e001f001f001f801f800f8006000": "7",
"c003c003c003c003c003c003c007c007c007e00ff00ff83e3efc1ff80f700600": "",
"e007e00fe00f600e700c781c781c383c383cfc3ffc3ffc7f1e700ef00ff007e0": "A",
"f83ffc3f3e381f000f0007000700077e07ff07fe07e00fe01fe0fefffc7ff03f": "G",
"c01ff8fffcff7ef01e000f000f000f000f000f000f001f003e007cf0fcfff07f": "C",
"ff073f3e0ff80ff00f700f38ff1fff1f3f3c0ff00fe00fc00fe00ff03f7cff1f": "B",
"ff0fff3f077f077803f003f003e003e003e003e003f00378077c0f3eff1fff03": "D",
"e01ff87ffefc3f700f000f000700030003fe03fe07e00fc01fe03ef0fcfff87f": "G",
"8007f01ffc7f3cfc00f800fcc03fc01fc01fc07f00fc00f81efcfefffc7ff81f": "3",
"f03ff07ff87820700078007c003ec01fe00ff001f800f800fc7ffc7ff87f0000": "2",
"c001c001c001c001c001c001c003c003e007e007f01ff03f787e7ffc1ff81ff0": "",
Expand All @@ -220,10 +214,6 @@
"f03ff87ff8fc38f000f000f800fe803fc007e003f801f800f800f8fff8fff87f": "2",
"f07ff8fff8fff07f003e001f000f800f800fc007c007c007e007f003e003e003": "7",
"f07ff8ff7cf800f000f000fc007f003f00fc00f000f000f03cfcfcfff87fe01f": "3",
"0078ffff3f000f000f000f00df1fff3fff070f000f000f000f001f00fffffeff": "E",
"0700ff1f1f3c0f780ff00ff00fe00fc00fc00fe00ff00ff00f780f3eff1fff07": "D",
"ff03ff1f0f3e073c03380338071eff1fff1f077c03f803f003f8077cbf3fff0f": "B",
"ff03ff0f1f780ff80ff00f700f3cff1fff3f0ff00fe00fc00fe01ff87f7eff0f": "B",
"0000f01ff87f7c7c0078007c003e001fe00ff003f800fc00fc3ffc7ff83f0000": "2",
"0000e01ff83f783838003800f80ffc3ffc7e3c7838783878787cf03fe01f8007": "6",
"c000c001c001fe3fff7fff7fc763c361e773ff7fff7fe773c001c001c001c000": "",
Expand Down Expand Up @@ -288,13 +278,8 @@
"e07ff0ffe0fc00f8007c803f807f00fe00f000f070f8f0fff03fc01f00000000": "3",
"e00ff81f783f003c003e801fc01f803f007e00fc08fcfc7ff83ff01f00000000": "3",
"0000f81ff83f387c007c003fc01fc03f007e007c00f87c7efc7ff03f80070000": "3",
"e007fc3f3e7f0f3c0f001f00ff00fc0fe03f007f00f800f00ff03f7cfe3ff007": "S",
"fe033f3f0f780f700f700e38fe1ffe3f3e7c0ef00ee00ee00ee01ef0fe3ffe0f": "B",
"8003e007e007f00ff81f781e381c3c1c3c3c7c3efe3ffe7f0f7007f007e000c0": "A",
"e00ff87f7c781e300f008707870f030e03fe03fe07f00fe01ee07cf0f8fff03f": "G",
"e01ff87ff8fe30fc00fc007c003fc03f00fe00f800f000f0f8fff87ff03fc007": "3",
"c03fe07f70207800781ff87ff87f78f078f078f0f8f0f07fe03f800f00000000": "6",
"f83ffc7f1e780e001e00fe01fc0ff83f807f00f800f006e01ff07efcfc7fe00f": "S",
"0000f00ff81f703e003c003e801fc01f803f007e00fc18fcfc7efc3ff01fe007": "3",
"e00ff03ff83c78183800f80ffc3ffc7f3c7838787878f83ff01fe00f00000000": "6",
"e01ff87ffc7f38f000f8007c003fe01ff007f801fc00fc7ffc7ff87f00000000": "2",
Expand Down Expand Up @@ -375,14 +360,24 @@
"f007f80ffc3f1e3e1f3c1f7c1ffc1ffc1ffc1ffc1f7c1f3c1e3efc3ff80ff003": "0",
"fc3ffc7f7c003c003c00fc1ffc3ffe7f1c7800f000f018f87e7cfe7ffc3ff00f": "5",
"c001f007fc1f3c3c1e781e781ef8fcfffcfff8ffc0f90078087cfc3ffc1ff807": "9",
"e00ff83f3c3c1e000f03c7036702677e27fe27fe07e00ee01ef3fc7ff83fe01f": "G",
"fc073f3f1f7c0f781f781f38ff1fff1f3f3c1f701fe00fe01ff03f78ff3ffe0f": "B",
"f301ff1f0f3f077c0770077007f007f007f007f007700778073c1f3fff0ffe01": "D",
"e200ff0f1f3f073c0738073c0f1eff1fff1f0f7c077807f807780f7eff1ffe03": "B",
"0000ff3fff1f1f001f001f00ff1fff3f3f7c04f800f800fc1efcff7ffe1ff80f": "5",
"e007fc1ffe3f1e781ef01ef01ef8fefffcfff0fb00f000781c3cfc3ff80fe003": "9",
"0000003fc07ff07fe07f807f007e007f007f007f007f007f007f003e00000000": "1",
"e003f80ffe3f1e7c1f781e78fc3ffc1ffe3ffe7f0ff80ff80f783f7cfc1ff007": "8",
"0000fcfffc7f3c003e007e00ff3fffff3efc00f000f018f03ef8fefff83ff00f": "5",
"0003e01ff87f7c783f001f00ff1fff7f7ffe3ff81ff01ff03ef8fcfef87ff00f": "6"
"0003e01ff87f7c783f001f00ff1fff7f7ffe3ff81ff01ff03ef8fcfef87ff00f": "6",
"e007f00f380c381c981d98198c19cc338c310e300670e667e76773ee3ffc1e7c": "A",
"fe7fffe003e083ffc33fc301833103700378c37fc33fc300c300e700ff007e00": "F",
"fc3fffff07e087ffc77fe639463006600670c63fe61fe600660066007e007e00": "F",
"8007f03f3c700ee0c6ffc37f6330730073006300c77886ff0ee03c70f03f800f": "C",
"e00ff00f300c30189819981998399c338c710c600660e6e7e6cf37cc3ff81ef8": "A",
"c00ff03e38700c63c67fe63c673c237f23e363c7e6cfc6cf0ce01c60f87fe01f": "G",
"c007f83f1c700e63c67f623c227cb3e1b3c1e2c7e6cfc6c40ce03870f03fc007": "G",
"fc03ff1f073c8360c3e3c3e3c371037003e0c3c7c3c6c3c783e10370ff3ffe1f": "B",
"fe01ff0f031e4330f361f36333e633e633e633e63363f3614330031eff0ffe03": "D",
"e00ff83e1c700e63c77fe33c737cb3ff93c1f3c763cec3cf06c11c60f83fe01f": "G",
"fc3fffff07e083ffe37fe33f033803300338e31fe300e37f03e007e0fefffe7f": "E",
"fe0fff1f03304360e3e3e3c763ce63ce63ce63c6e3c7e3630370033cff1ffe07": "D",
"fe07fe1f0738c770e763e763c73107300660e6e366c7e6c3c6610778fe3ffc0f": "B",
"e003781e1e388771c37fc33f871f0e383c70fce1fec3e3e387600e78fc3ff00f": "S"
}
23 changes: 0 additions & 23 deletions typings/cv2/_contrib.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -29745,29 +29745,6 @@ def imwritemulti(filename, img, params=...) -> retval:
"""
...

def inRange(src, lowerb, upperb, dst=...) -> dst:
"""
. @brief Checks if array elements lie between the elements of two other arrays.
.
. The function checks the range as follows:
. - For every element of a single-channel input array:
. \f[\texttt{dst} (I)= \texttt{lowerb} (I)_0 \leq \texttt{src} (I)_0 \leq \texttt{upperb} (I)_0\f]
. - For two-channel arrays:
. \f[\texttt{dst} (I)= \texttt{lowerb} (I)_0 \leq \texttt{src} (I)_0 \leq \texttt{upperb} (I)_0 \land \texttt{lowerb} (I)_1 \leq \texttt{src} (I)_1 \leq \texttt{upperb} (I)_1\f]
. - and so forth.
.
. That is, dst (I) is set to 255 (all 1 -bits) if src (I) is within the
. specified 1D, 2D, 3D, ... box and 0 otherwise.
.
. When the lower and/or upper boundary parameters are scalars, the indexes
. (I) at lowerb and upperb in the above formulas should be omitted.
. @param src first input array.
. @param lowerb inclusive lower boundary array or a scalar.
. @param upperb inclusive upper boundary array or a scalar.
. @param dst output array of the same size as src and CV_8U type.
"""
...

def initCameraMatrix2D(objectPoints, imagePoints, imageSize, aspectRatio=...) -> retval:
"""
. @brief Finds an initial camera intrinsic matrix from 3D-2D point correspondences.
Expand Down
4 changes: 3 additions & 1 deletion typings/cv2/cv2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -18403,7 +18403,9 @@ def imwritemulti(filename, img, params=...) -> retval:
"""
...

def inRange(src, lowerb, upperb, dst=...) -> dst:
def inRange(
src: ndarray, lowerb: ArrayLike, upperb: ArrayLike, dst: Optional[ndarray] = ...
) -> ndarray:
"""
. @brief Checks if array elements lie between the elements of two other arrays.
.
Expand Down
15 changes: 14 additions & 1 deletion typings/numpy.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -33466,7 +33466,20 @@ mgrid: ...
<numpy.lib.index_tricks.MGridClass object>
"""

def minimum(*args, **kwargs):
def minimum(
x1: ndarray,
x2: ndarray,
/,
out: Optional[ndarray] = None,
*,
where: bool = True,
casting: Text = "same_kind",
order: Text = "K",
dtype: Optional[Type[Any]] = None,
subok: bool = True,
signature: Any = ...,
extobj: Any = ...,
) -> Union[ndarray, Scalar]:
"""
<ufunc 'minimum'>
"""
Expand Down

0 comments on commit 8f2ece0

Please sign in to comment.