diff --git a/src/arcaea_offline_ocr/device/roi/definitions/auto/__init__.py b/src/arcaea_offline_ocr/device/roi/definitions/auto/__init__.py deleted file mode 100644 index 270a1e0..0000000 --- a/src/arcaea_offline_ocr/device/roi/definitions/auto/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .common import DeviceAutoRoiSizes -from .t1 import DeviceAutoRoiSizesT1 -from .t2 import DeviceAutoRoiSizesT2 diff --git a/src/arcaea_offline_ocr/device/roi/definitions/auto/common.py b/src/arcaea_offline_ocr/device/roi/definitions/auto/common.py deleted file mode 100644 index a6e9c11..0000000 --- a/src/arcaea_offline_ocr/device/roi/definitions/auto/common.py +++ /dev/null @@ -1,7 +0,0 @@ -from ..common import DeviceRoiSizes - - -class DeviceAutoRoiSizes(DeviceRoiSizes): - def __init__(self, w: int, h: int): - self.w = w - self.h = h diff --git a/src/arcaea_offline_ocr/device/roi/definitions/auto/t1.py b/src/arcaea_offline_ocr/device/roi/definitions/auto/t1.py deleted file mode 100644 index 291a29c..0000000 --- a/src/arcaea_offline_ocr/device/roi/definitions/auto/t1.py +++ /dev/null @@ -1,123 +0,0 @@ -from .common import DeviceAutoRoiSizes - - -class DeviceAutoRoiSizesT1(DeviceAutoRoiSizes): - @property - def factor(self): - return ( - ((self.w / 16) * 9) / 720 if (self.w / self.h) < (16 / 9) else self.h / 720 - ) - - @property - def w_mid(self): - return self.w / 2 - - @property - def h_mid(self): - return self.h / 2 - - @property - def top_bar(self): - return (0, 0, self.w, 50 * self.factor) - - @property - def layout_area_h_mid(self): - return self.h / 2 + self.top_bar[3] - - @property - def pfl_left_from_w_mid(self): - return 5 * self.factor - - @property - def pfl_x(self): - return self.w_mid + self.pfl_left_from_w_mid - - @property - def pfl_w(self): - return 76 * self.factor - - @property - def pfl_h(self): - return 26 * self.factor - - @property - def pure(self): - return ( - self.pfl_x, - self.layout_area_h_mid + 110 * self.factor, - self.pfl_w, - self.pfl_h, - ) - - @property - def far(self): - return ( - self.pfl_x, - self.pure[1] + self.pure[3] + 12 * self.factor, - self.pfl_w, - self.pfl_h, - ) - - @property - def lost(self): - return ( - self.pfl_x, - self.far[1] + self.far[3] + 10 * self.factor, - self.pfl_w, - self.pfl_h, - ) - - @property - def score(self): - w = 280 * self.factor - h = 45 * self.factor - return ( - self.w_mid - w / 2, - self.layout_area_h_mid - 75 * self.factor - h, - w, - h, - ) - - @property - def rating_class(self): - return ( - self.w_mid - 610 * self.factor, - self.layout_area_h_mid - 180 * self.factor, - 265 * self.factor, - 35 * self.factor, - ) - - @property - def max_recall(self): - return ( - self.w_mid - 465 * self.factor, - self.layout_area_h_mid - 215 * self.factor, - 150 * self.factor, - 35 * self.factor, - ) - - @property - def jacket(self): - return ( - self.w_mid - 610 * self.factor, - self.layout_area_h_mid - 143 * self.factor, - 375 * self.factor, - 375 * self.factor, - ) - - @property - def clear_status(self): - w = 550 * self.factor - h = 60 * self.factor - return ( - self.w_mid - w / 2, - self.layout_area_h_mid - 155 * self.factor - h, - w, - h, - ) - - @property - def partner_icon(self): - w = 90 * self.factor - h = 75 * self.factor - return (self.w_mid - w / 2, 0, w, h) diff --git a/src/arcaea_offline_ocr/device/roi/definitions/auto/t2.py b/src/arcaea_offline_ocr/device/roi/definitions/auto/t2.py deleted file mode 100644 index f214da0..0000000 --- a/src/arcaea_offline_ocr/device/roi/definitions/auto/t2.py +++ /dev/null @@ -1,125 +0,0 @@ -from .common import DeviceAutoRoiSizes - - -class DeviceAutoRoiSizesT2(DeviceAutoRoiSizes): - @property - def factor(self): - return ( - ((self.w / 16) * 9) / 1080 - if (self.w / self.h) < (16 / 9) - else self.h / 1080 - ) - - @property - def w_mid(self): - return self.w / 2 - - @property - def h_mid(self): - return self.h / 2 - - @property - def top_bar(self): - return (0, 0, self.w, 75 * self.factor) - - @property - def layout_area_h_mid(self): - return self.h / 2 + self.top_bar[3] - - @property - def pfl_mid_from_w_mid(self): - return 60 * self.factor - - @property - def pfl_x(self): - return self.w_mid + 10 * self.factor - - @property - def pfl_w(self): - return 100 * self.factor - - @property - def pfl_h(self): - return 24 * self.factor - - @property - def pure(self): - return ( - self.pfl_x, - self.layout_area_h_mid + 175 * self.factor, - self.pfl_w, - self.pfl_h, - ) - - @property - def far(self): - return ( - self.pfl_x, - self.pure[1] + self.pure[3] + 30 * self.factor, - self.pfl_w, - self.pfl_h, - ) - - @property - def lost(self): - return ( - self.pfl_x, - self.far[1] + self.far[3] + 35 * self.factor, - self.pfl_w, - self.pfl_h, - ) - - @property - def score(self): - w = 420 * self.factor - h = 70 * self.factor - return ( - self.w_mid - w / 2, - self.layout_area_h_mid - 110 * self.factor - h, - w, - h, - ) - - @property - def rating_class(self): - return ( - max(0, self.w_mid - 965 * self.factor), - self.layout_area_h_mid - 330 * self.factor, - 350 * self.factor, - 110 * self.factor, - ) - - @property - def max_recall(self): - return ( - self.w_mid - 625 * self.factor, - self.layout_area_h_mid - 275 * self.factor, - 150 * self.factor, - 50 * self.factor, - ) - - @property - def jacket(self): - return ( - self.w_mid - 915 * self.factor, - self.layout_area_h_mid - 215 * self.factor, - 565 * self.factor, - 565 * self.factor, - ) - - @property - def clear_status(self): - w = 825 * self.factor - h = 90 * self.factor - return ( - self.w_mid - w / 2, - self.layout_area_h_mid - 235 * self.factor - h, - w, - h, - ) - - @property - def partner_icon(self): - w = 135 * self.factor - h = 110 * self.factor - return (self.w_mid - w / 2, 0, w, h) diff --git a/src/arcaea_offline_ocr/device/roi/extractor/__init__.py b/src/arcaea_offline_ocr/device/roi/extractor/__init__.py deleted file mode 100644 index 66ae350..0000000 --- a/src/arcaea_offline_ocr/device/roi/extractor/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .common import DeviceRoiExtractor diff --git a/src/arcaea_offline_ocr/device/roi/masker/__init__.py b/src/arcaea_offline_ocr/device/roi/masker/__init__.py deleted file mode 100644 index fd4f408..0000000 --- a/src/arcaea_offline_ocr/device/roi/masker/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .auto import * -from .common import DeviceRoiMasker diff --git a/src/arcaea_offline_ocr/device/roi/masker/auto/__init__.py b/src/arcaea_offline_ocr/device/roi/masker/auto/__init__.py deleted file mode 100644 index cc84af6..0000000 --- a/src/arcaea_offline_ocr/device/roi/masker/auto/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .common import DeviceAutoRoiMasker -from .t1 import DeviceAutoRoiMaskerT1 -from .t2 import DeviceAutoRoiMaskerT2 diff --git a/src/arcaea_offline_ocr/device/roi/masker/auto/common.py b/src/arcaea_offline_ocr/device/roi/masker/auto/common.py deleted file mode 100644 index ed725d2..0000000 --- a/src/arcaea_offline_ocr/device/roi/masker/auto/common.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..common import DeviceRoiMasker - - -class DeviceAutoRoiMasker(DeviceRoiMasker): - ... diff --git a/src/arcaea_offline_ocr/device/roi/masker/auto/t1.py b/src/arcaea_offline_ocr/device/roi/masker/auto/t1.py deleted file mode 100644 index 84ba4a8..0000000 --- a/src/arcaea_offline_ocr/device/roi/masker/auto/t1.py +++ /dev/null @@ -1,123 +0,0 @@ -import cv2 -import numpy as np - -from .common import DeviceAutoRoiMasker - -GRAY_BGR_MIN = np.array([50] * 3, np.uint8) -GRAY_BGR_MAX = np.array([160] * 3, np.uint8) - -WHITE_HSV_MIN = np.array([0, 0, 240], np.uint8) -WHITE_HSV_MAX = np.array([179, 10, 255], np.uint8) - -PST_HSV_MIN = np.array([100, 50, 80], np.uint8) -PST_HSV_MAX = np.array([100, 255, 255], np.uint8) - -PRS_HSV_MIN = np.array([43, 40, 75], np.uint8) -PRS_HSV_MAX = np.array([50, 155, 190], np.uint8) - -FTR_HSV_MIN = np.array([149, 30, 0], np.uint8) -FTR_HSV_MAX = np.array([155, 181, 150], np.uint8) - -BYD_HSV_MIN = np.array([170, 50, 50], np.uint8) -BYD_HSV_MAX = np.array([179, 210, 198], np.uint8) - -TRACK_LOST_HSV_MIN = np.array([170, 75, 90], np.uint8) -TRACK_LOST_HSV_MAX = np.array([175, 170, 160], np.uint8) - -TRACK_COMPLETE_HSV_MIN = np.array([140, 0, 50], np.uint8) -TRACK_COMPLETE_HSV_MAX = np.array([145, 50, 130], np.uint8) - -FULL_RECALL_HSV_MIN = np.array([140, 60, 80], np.uint8) -FULL_RECALL_HSV_MAX = np.array([150, 130, 145], np.uint8) - -PURE_MEMORY_HSV_MIN = np.array([90, 70, 80], np.uint8) -PURE_MEMORY_HSV_MAX = np.array([110, 200, 175], np.uint8) - - -class DeviceAutoRoiMaskerT1(DeviceAutoRoiMasker): - @classmethod - def gray(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - bgr_value_equal_mask = np.max(roi_bgr, axis=2) - np.min(roi_bgr, axis=2) <= 5 - img_bgr = roi_bgr.copy() - img_bgr[~bgr_value_equal_mask] = np.array([0, 0, 0], roi_bgr.dtype) - img_bgr = cv2.erode(img_bgr, cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))) - img_bgr = cv2.dilate(img_bgr, cv2.getStructuringElement(cv2.MORPH_RECT, (1, 1))) - return cv2.inRange(img_bgr, GRAY_BGR_MIN, GRAY_BGR_MAX) - - @classmethod - def pure(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cls.gray(roi_bgr) - - @classmethod - def far(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cls.gray(roi_bgr) - - @classmethod - def lost(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cls.gray(roi_bgr) - - @classmethod - def score(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), WHITE_HSV_MIN, WHITE_HSV_MAX - ) - - @classmethod - def rating_class_pst(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), PST_HSV_MIN, PST_HSV_MAX - ) - - @classmethod - def rating_class_prs(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), PRS_HSV_MIN, PRS_HSV_MAX - ) - - @classmethod - def rating_class_ftr(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), FTR_HSV_MIN, FTR_HSV_MAX - ) - - @classmethod - def rating_class_byd(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), BYD_HSV_MIN, BYD_HSV_MAX - ) - - @classmethod - def max_recall(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cls.gray(roi_bgr) - - @classmethod - def clear_status_track_lost(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), - TRACK_LOST_HSV_MIN, - TRACK_LOST_HSV_MAX, - ) - - @classmethod - def clear_status_track_complete(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), - TRACK_COMPLETE_HSV_MIN, - TRACK_COMPLETE_HSV_MAX, - ) - - @classmethod - def clear_status_full_recall(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), - FULL_RECALL_HSV_MIN, - FULL_RECALL_HSV_MAX, - ) - - @classmethod - def clear_status_pure_memory(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), - PURE_MEMORY_HSV_MIN, - PURE_MEMORY_HSV_MAX, - ) diff --git a/src/arcaea_offline_ocr/device/roi/masker/auto/t2.py b/src/arcaea_offline_ocr/device/roi/masker/auto/t2.py deleted file mode 100644 index 430a3fb..0000000 --- a/src/arcaea_offline_ocr/device/roi/masker/auto/t2.py +++ /dev/null @@ -1,128 +0,0 @@ -import cv2 -import numpy as np - -from .common import DeviceAutoRoiMasker - -PFL_HSV_MIN = np.array([0, 0, 248], np.uint8) -PFL_HSV_MAX = np.array([179, 10, 255], np.uint8) - -WHITE_HSV_MIN = np.array([0, 0, 240], np.uint8) -WHITE_HSV_MAX = np.array([179, 10, 255], np.uint8) - - -PST_HSV_MIN = np.array([100, 50, 80], np.uint8) -PST_HSV_MAX = np.array([100, 255, 255], np.uint8) - -PRS_HSV_MIN = np.array([43, 40, 75], np.uint8) -PRS_HSV_MAX = np.array([50, 155, 190], np.uint8) - -FTR_HSV_MIN = np.array([149, 30, 0], np.uint8) -FTR_HSV_MAX = np.array([155, 181, 150], np.uint8) - -BYD_HSV_MIN = np.array([170, 50, 50], np.uint8) -BYD_HSV_MAX = np.array([179, 210, 198], np.uint8) - -MAX_RECALL_HSV_MIN = np.array([125, 0, 0], np.uint8) -MAX_RECALL_HSV_MAX = np.array([130, 100, 150], np.uint8) - -TRACK_LOST_HSV_MIN = np.array([170, 75, 90], np.uint8) -TRACK_LOST_HSV_MAX = np.array([175, 170, 160], np.uint8) - -TRACK_COMPLETE_HSV_MIN = np.array([140, 0, 50], np.uint8) -TRACK_COMPLETE_HSV_MAX = np.array([145, 50, 130], np.uint8) - -FULL_RECALL_HSV_MIN = np.array([140, 60, 80], np.uint8) -FULL_RECALL_HSV_MAX = np.array([150, 130, 145], np.uint8) - -PURE_MEMORY_HSV_MIN = np.array([90, 70, 80], np.uint8) -PURE_MEMORY_HSV_MAX = np.array([110, 200, 175], np.uint8) - - -class DeviceAutoRoiMaskerT2(DeviceAutoRoiMasker): - @classmethod - def pfl(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), PFL_HSV_MIN, PFL_HSV_MAX - ) - - @classmethod - def pure(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cls.pfl(roi_bgr) - - @classmethod - def far(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cls.pfl(roi_bgr) - - @classmethod - def lost(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cls.pfl(roi_bgr) - - @classmethod - def score(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), WHITE_HSV_MIN, WHITE_HSV_MAX - ) - - @classmethod - def rating_class_pst(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), PST_HSV_MIN, PST_HSV_MAX - ) - - @classmethod - def rating_class_prs(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), PRS_HSV_MIN, PRS_HSV_MAX - ) - - @classmethod - def rating_class_ftr(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), FTR_HSV_MIN, FTR_HSV_MAX - ) - - @classmethod - def rating_class_byd(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), BYD_HSV_MIN, BYD_HSV_MAX - ) - - @classmethod - def max_recall(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), - MAX_RECALL_HSV_MIN, - MAX_RECALL_HSV_MAX, - ) - - @classmethod - def clear_status_track_lost(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), - TRACK_LOST_HSV_MIN, - TRACK_LOST_HSV_MAX, - ) - - @classmethod - def clear_status_track_complete(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), - TRACK_COMPLETE_HSV_MIN, - TRACK_COMPLETE_HSV_MAX, - ) - - @classmethod - def clear_status_full_recall(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), - FULL_RECALL_HSV_MIN, - FULL_RECALL_HSV_MAX, - ) - - @classmethod - def clear_status_pure_memory(cls, roi_bgr: cv2.Mat) -> cv2.Mat: - return cv2.inRange( - cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), - PURE_MEMORY_HSV_MIN, - PURE_MEMORY_HSV_MAX, - ) diff --git a/src/arcaea_offline_ocr/device/roi/definitions/__init__.py b/src/arcaea_offline_ocr/device/rois/definition/__init__.py similarity index 100% rename from src/arcaea_offline_ocr/device/roi/definitions/__init__.py rename to src/arcaea_offline_ocr/device/rois/definition/__init__.py diff --git a/src/arcaea_offline_ocr/device/rois/definition/auto.py b/src/arcaea_offline_ocr/device/rois/definition/auto.py new file mode 100644 index 0000000..66508c9 --- /dev/null +++ b/src/arcaea_offline_ocr/device/rois/definition/auto.py @@ -0,0 +1,255 @@ +from .common import DeviceRois + +__all__ = ["DeviceRoisAuto", "DeviceRoisAutoT1", "DeviceRoisAutoT2"] + + +class DeviceRoisAuto(DeviceRois): + def __init__(self, w: int, h: int): + self.w = w + self.h = h + + +class DeviceRoisAutoT1(DeviceRoisAuto): + @property + def factor(self): + return ( + ((self.w / 16) * 9) / 720 if (self.w / self.h) < (16 / 9) else self.h / 720 + ) + + @property + def w_mid(self): + return self.w / 2 + + @property + def h_mid(self): + return self.h / 2 + + @property + def top_bar(self): + return (0, 0, self.w, 50 * self.factor) + + @property + def layout_area_h_mid(self): + return self.h / 2 + self.top_bar[3] + + @property + def pfl_left_from_w_mid(self): + return 5 * self.factor + + @property + def pfl_x(self): + return self.w_mid + self.pfl_left_from_w_mid + + @property + def pfl_w(self): + return 76 * self.factor + + @property + def pfl_h(self): + return 26 * self.factor + + @property + def pure(self): + return ( + self.pfl_x, + self.layout_area_h_mid + 110 * self.factor, + self.pfl_w, + self.pfl_h, + ) + + @property + def far(self): + return ( + self.pfl_x, + self.pure[1] + self.pure[3] + 12 * self.factor, + self.pfl_w, + self.pfl_h, + ) + + @property + def lost(self): + return ( + self.pfl_x, + self.far[1] + self.far[3] + 10 * self.factor, + self.pfl_w, + self.pfl_h, + ) + + @property + def score(self): + w = 280 * self.factor + h = 45 * self.factor + return ( + self.w_mid - w / 2, + self.layout_area_h_mid - 75 * self.factor - h, + w, + h, + ) + + @property + def rating_class(self): + return ( + self.w_mid - 610 * self.factor, + self.layout_area_h_mid - 180 * self.factor, + 265 * self.factor, + 35 * self.factor, + ) + + @property + def max_recall(self): + return ( + self.w_mid - 465 * self.factor, + self.layout_area_h_mid - 215 * self.factor, + 150 * self.factor, + 35 * self.factor, + ) + + @property + def jacket(self): + return ( + self.w_mid - 610 * self.factor, + self.layout_area_h_mid - 143 * self.factor, + 375 * self.factor, + 375 * self.factor, + ) + + @property + def clear_status(self): + w = 550 * self.factor + h = 60 * self.factor + return ( + self.w_mid - w / 2, + self.layout_area_h_mid - 155 * self.factor - h, + w, + h, + ) + + @property + def partner_icon(self): + w = 90 * self.factor + h = 75 * self.factor + return (self.w_mid - w / 2, 0, w, h) + + +class DeviceRoisAutoT2(DeviceRoisAuto): + @property + def factor(self): + return ( + ((self.w / 16) * 9) / 1080 + if (self.w / self.h) < (16 / 9) + else self.h / 1080 + ) + + @property + def w_mid(self): + return self.w / 2 + + @property + def h_mid(self): + return self.h / 2 + + @property + def top_bar(self): + return (0, 0, self.w, 75 * self.factor) + + @property + def layout_area_h_mid(self): + return self.h / 2 + self.top_bar[3] + + @property + def pfl_mid_from_w_mid(self): + return 60 * self.factor + + @property + def pfl_x(self): + return self.w_mid + 10 * self.factor + + @property + def pfl_w(self): + return 100 * self.factor + + @property + def pfl_h(self): + return 24 * self.factor + + @property + def pure(self): + return ( + self.pfl_x, + self.layout_area_h_mid + 175 * self.factor, + self.pfl_w, + self.pfl_h, + ) + + @property + def far(self): + return ( + self.pfl_x, + self.pure[1] + self.pure[3] + 30 * self.factor, + self.pfl_w, + self.pfl_h, + ) + + @property + def lost(self): + return ( + self.pfl_x, + self.far[1] + self.far[3] + 35 * self.factor, + self.pfl_w, + self.pfl_h, + ) + + @property + def score(self): + w = 420 * self.factor + h = 70 * self.factor + return ( + self.w_mid - w / 2, + self.layout_area_h_mid - 110 * self.factor - h, + w, + h, + ) + + @property + def rating_class(self): + return ( + max(0, self.w_mid - 965 * self.factor), + self.layout_area_h_mid - 330 * self.factor, + 350 * self.factor, + 110 * self.factor, + ) + + @property + def max_recall(self): + return ( + self.w_mid - 625 * self.factor, + self.layout_area_h_mid - 275 * self.factor, + 150 * self.factor, + 50 * self.factor, + ) + + @property + def jacket(self): + return ( + self.w_mid - 915 * self.factor, + self.layout_area_h_mid - 215 * self.factor, + 565 * self.factor, + 565 * self.factor, + ) + + @property + def clear_status(self): + w = 825 * self.factor + h = 90 * self.factor + return ( + self.w_mid - w / 2, + self.layout_area_h_mid - 235 * self.factor - h, + w, + h, + ) + + @property + def partner_icon(self): + w = 135 * self.factor + h = 110 * self.factor + return (self.w_mid - w / 2, 0, w, h) diff --git a/src/arcaea_offline_ocr/device/roi/definitions/common.py b/src/arcaea_offline_ocr/device/rois/definition/common.py similarity index 91% rename from src/arcaea_offline_ocr/device/roi/definitions/common.py rename to src/arcaea_offline_ocr/device/rois/definition/common.py index f4ef4a1..96512c4 100644 --- a/src/arcaea_offline_ocr/device/roi/definitions/common.py +++ b/src/arcaea_offline_ocr/device/rois/definition/common.py @@ -3,7 +3,7 @@ from typing import Tuple Rect = Tuple[int, int, int, int] -class DeviceRoiSizes: +class DeviceRois: pure: Rect far: Rect lost: Rect diff --git a/src/arcaea_offline_ocr/device/roi/definitions/custom.py b/src/arcaea_offline_ocr/device/rois/definition/custom.py similarity index 100% rename from src/arcaea_offline_ocr/device/roi/definitions/custom.py rename to src/arcaea_offline_ocr/device/rois/definition/custom.py diff --git a/src/arcaea_offline_ocr/device/rois/extractor/__init__.py b/src/arcaea_offline_ocr/device/rois/extractor/__init__.py new file mode 100644 index 0000000..1b6ae1d --- /dev/null +++ b/src/arcaea_offline_ocr/device/rois/extractor/__init__.py @@ -0,0 +1 @@ +from .common import DeviceRoisExtractor diff --git a/src/arcaea_offline_ocr/device/roi/extractor/common.py b/src/arcaea_offline_ocr/device/rois/extractor/common.py similarity index 90% rename from src/arcaea_offline_ocr/device/roi/extractor/common.py rename to src/arcaea_offline_ocr/device/rois/extractor/common.py index d9365e2..e672e8b 100644 --- a/src/arcaea_offline_ocr/device/roi/extractor/common.py +++ b/src/arcaea_offline_ocr/device/rois/extractor/common.py @@ -1,11 +1,11 @@ import cv2 from ....crop import crop_xywh -from ..definitions.common import DeviceRoiSizes +from ..definition.common import DeviceRois -class DeviceRoiExtractor: - def __init__(self, img: cv2.Mat, sizes: DeviceRoiSizes): +class DeviceRoisExtractor: + def __init__(self, img: cv2.Mat, sizes: DeviceRois): self.img = img self.sizes = sizes diff --git a/src/arcaea_offline_ocr/device/rois/masker/__init__.py b/src/arcaea_offline_ocr/device/rois/masker/__init__.py new file mode 100644 index 0000000..ced796d --- /dev/null +++ b/src/arcaea_offline_ocr/device/rois/masker/__init__.py @@ -0,0 +1,2 @@ +from .auto import * +from .common import DeviceRoisMasker diff --git a/src/arcaea_offline_ocr/device/rois/masker/auto.py b/src/arcaea_offline_ocr/device/rois/masker/auto.py new file mode 100644 index 0000000..77f0696 --- /dev/null +++ b/src/arcaea_offline_ocr/device/rois/masker/auto.py @@ -0,0 +1,254 @@ +import cv2 +import numpy as np + +from .common import DeviceRoisMasker + + +class DeviceRoisMaskerAuto(DeviceRoisMasker): + ... + + +class DeviceRoisMaskerAutoT1(DeviceRoisMaskerAuto): + GRAY_BGR_MIN = np.array([50] * 3, np.uint8) + GRAY_BGR_MAX = np.array([160] * 3, np.uint8) + + WHITE_HSV_MIN = np.array([0, 0, 240], np.uint8) + WHITE_HSV_MAX = np.array([179, 10, 255], np.uint8) + + PST_HSV_MIN = np.array([100, 50, 80], np.uint8) + PST_HSV_MAX = np.array([100, 255, 255], np.uint8) + + PRS_HSV_MIN = np.array([43, 40, 75], np.uint8) + PRS_HSV_MAX = np.array([50, 155, 190], np.uint8) + + FTR_HSV_MIN = np.array([149, 30, 0], np.uint8) + FTR_HSV_MAX = np.array([155, 181, 150], np.uint8) + + BYD_HSV_MIN = np.array([170, 50, 50], np.uint8) + BYD_HSV_MAX = np.array([179, 210, 198], np.uint8) + + TRACK_LOST_HSV_MIN = np.array([170, 75, 90], np.uint8) + TRACK_LOST_HSV_MAX = np.array([175, 170, 160], np.uint8) + + TRACK_COMPLETE_HSV_MIN = np.array([140, 0, 50], np.uint8) + TRACK_COMPLETE_HSV_MAX = np.array([145, 50, 130], np.uint8) + + FULL_RECALL_HSV_MIN = np.array([140, 60, 80], np.uint8) + FULL_RECALL_HSV_MAX = np.array([150, 130, 145], np.uint8) + + PURE_MEMORY_HSV_MIN = np.array([90, 70, 80], np.uint8) + PURE_MEMORY_HSV_MAX = np.array([110, 200, 175], np.uint8) + + @classmethod + def gray(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + bgr_value_equal_mask = np.max(roi_bgr, axis=2) - np.min(roi_bgr, axis=2) <= 5 + img_bgr = roi_bgr.copy() + img_bgr[~bgr_value_equal_mask] = np.array([0, 0, 0], roi_bgr.dtype) + img_bgr = cv2.erode(img_bgr, cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))) + img_bgr = cv2.dilate(img_bgr, cv2.getStructuringElement(cv2.MORPH_RECT, (1, 1))) + return cv2.inRange(img_bgr, cls.GRAY_BGR_MIN, cls.GRAY_BGR_MAX) + + @classmethod + def pure(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cls.gray(roi_bgr) + + @classmethod + def far(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cls.gray(roi_bgr) + + @classmethod + def lost(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cls.gray(roi_bgr) + + @classmethod + def score(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.WHITE_HSV_MIN, + cls.WHITE_HSV_MAX, + ) + + @classmethod + def rating_class_pst(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), cls.PST_HSV_MIN, cls.PST_HSV_MAX + ) + + @classmethod + def rating_class_prs(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), cls.PRS_HSV_MIN, cls.PRS_HSV_MAX + ) + + @classmethod + def rating_class_ftr(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), cls.FTR_HSV_MIN, cls.FTR_HSV_MAX + ) + + @classmethod + def rating_class_byd(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), cls.BYD_HSV_MIN, cls.BYD_HSV_MAX + ) + + @classmethod + def max_recall(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cls.gray(roi_bgr) + + @classmethod + def clear_status_track_lost(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.TRACK_LOST_HSV_MIN, + cls.TRACK_LOST_HSV_MAX, + ) + + @classmethod + def clear_status_track_complete(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.TRACK_COMPLETE_HSV_MIN, + cls.TRACK_COMPLETE_HSV_MAX, + ) + + @classmethod + def clear_status_full_recall(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.FULL_RECALL_HSV_MIN, + cls.FULL_RECALL_HSV_MAX, + ) + + @classmethod + def clear_status_pure_memory(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.PURE_MEMORY_HSV_MIN, + cls.PURE_MEMORY_HSV_MAX, + ) + + +class DeviceRoisMaskerAutoT2(DeviceRoisMaskerAuto): + PFL_HSV_MIN = np.array([0, 0, 248], np.uint8) + PFL_HSV_MAX = np.array([179, 10, 255], np.uint8) + + WHITE_HSV_MIN = np.array([0, 0, 240], np.uint8) + WHITE_HSV_MAX = np.array([179, 10, 255], np.uint8) + + PST_HSV_MIN = np.array([100, 50, 80], np.uint8) + PST_HSV_MAX = np.array([100, 255, 255], np.uint8) + + PRS_HSV_MIN = np.array([43, 40, 75], np.uint8) + PRS_HSV_MAX = np.array([50, 155, 190], np.uint8) + + FTR_HSV_MIN = np.array([149, 30, 0], np.uint8) + FTR_HSV_MAX = np.array([155, 181, 150], np.uint8) + + BYD_HSV_MIN = np.array([170, 50, 50], np.uint8) + BYD_HSV_MAX = np.array([179, 210, 198], np.uint8) + + MAX_RECALL_HSV_MIN = np.array([125, 0, 0], np.uint8) + MAX_RECALL_HSV_MAX = np.array([130, 100, 150], np.uint8) + + TRACK_LOST_HSV_MIN = np.array([170, 75, 90], np.uint8) + TRACK_LOST_HSV_MAX = np.array([175, 170, 160], np.uint8) + + TRACK_COMPLETE_HSV_MIN = np.array([140, 0, 50], np.uint8) + TRACK_COMPLETE_HSV_MAX = np.array([145, 50, 130], np.uint8) + + FULL_RECALL_HSV_MIN = np.array([140, 60, 80], np.uint8) + FULL_RECALL_HSV_MAX = np.array([150, 130, 145], np.uint8) + + PURE_MEMORY_HSV_MIN = np.array([90, 70, 80], np.uint8) + PURE_MEMORY_HSV_MAX = np.array([110, 200, 175], np.uint8) + + @classmethod + def pfl(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), cls.PFL_HSV_MIN, cls.PFL_HSV_MAX + ) + + @classmethod + def pure(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cls.pfl(roi_bgr) + + @classmethod + def far(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cls.pfl(roi_bgr) + + @classmethod + def lost(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cls.pfl(roi_bgr) + + @classmethod + def score(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.WHITE_HSV_MIN, + cls.WHITE_HSV_MAX, + ) + + @classmethod + def rating_class_pst(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), cls.PST_HSV_MIN, cls.PST_HSV_MAX + ) + + @classmethod + def rating_class_prs(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), cls.PRS_HSV_MIN, cls.PRS_HSV_MAX + ) + + @classmethod + def rating_class_ftr(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), cls.FTR_HSV_MIN, cls.FTR_HSV_MAX + ) + + @classmethod + def rating_class_byd(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), cls.BYD_HSV_MIN, cls.BYD_HSV_MAX + ) + + @classmethod + def max_recall(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.MAX_RECALL_HSV_MIN, + cls.MAX_RECALL_HSV_MAX, + ) + + @classmethod + def clear_status_track_lost(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.TRACK_LOST_HSV_MIN, + cls.TRACK_LOST_HSV_MAX, + ) + + @classmethod + def clear_status_track_complete(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.TRACK_COMPLETE_HSV_MIN, + cls.TRACK_COMPLETE_HSV_MAX, + ) + + @classmethod + def clear_status_full_recall(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.FULL_RECALL_HSV_MIN, + cls.FULL_RECALL_HSV_MAX, + ) + + @classmethod + def clear_status_pure_memory(cls, roi_bgr: cv2.Mat) -> cv2.Mat: + return cv2.inRange( + cv2.cvtColor(roi_bgr, cv2.COLOR_BGR2HSV), + cls.PURE_MEMORY_HSV_MIN, + cls.PURE_MEMORY_HSV_MAX, + ) diff --git a/src/arcaea_offline_ocr/device/roi/masker/common.py b/src/arcaea_offline_ocr/device/rois/masker/common.py similarity index 98% rename from src/arcaea_offline_ocr/device/roi/masker/common.py rename to src/arcaea_offline_ocr/device/rois/masker/common.py index 39bbaf6..f877e2c 100644 --- a/src/arcaea_offline_ocr/device/roi/masker/common.py +++ b/src/arcaea_offline_ocr/device/rois/masker/common.py @@ -1,7 +1,7 @@ import cv2 -class DeviceRoiMasker: +class DeviceRoisMasker: @classmethod def pure(cls, roi_bgr: cv2.Mat) -> cv2.Mat: raise NotImplementedError()