158 lines
4.7 KiB
Python
158 lines
4.7 KiB
Python
from concurrent.futures import ThreadPoolExecutor
|
|
from functools import partial
|
|
|
|
import cv2
|
|
import numpy as np
|
|
|
|
from mower.models import avatar, portrait
|
|
from mower.utils import config
|
|
from mower.utils import typealias as tp
|
|
from mower.utils.image import cropimg, thres2
|
|
from mower.utils.log import logger
|
|
from mower.utils.matcher import GOOD_DISTANCE_LIMIT, flann, keypoints
|
|
from mower.utils.vector import in_scope, va
|
|
|
|
|
|
def segment_room_select(img: tp.Image) -> list[tp.Scope]:
|
|
"基建房间内选干员"
|
|
line1 = cropimg(img, ((600, 519), (1920, 520)))
|
|
hsv = cv2.cvtColor(line1, cv2.COLOR_RGB2HSV)
|
|
mask = cv2.inRange(hsv, (98, 140, 200), (102, 255, 255))
|
|
line1 = cv2.cvtColor(line1, cv2.COLOR_RGB2GRAY)
|
|
line1[mask > 0] = (255,)
|
|
line1 = thres2(line1, 140)
|
|
|
|
last_line = line1[-1]
|
|
prev = last_line[0]
|
|
start = None
|
|
name_x = []
|
|
for i in range(1, line1.shape[1]):
|
|
curr = last_line[i]
|
|
if prev == 0 and curr == 255 and start and i - start > 186:
|
|
name_x.append((i + 415, i + 585))
|
|
elif prev == 255 and curr == 0:
|
|
start = i
|
|
prev = curr
|
|
|
|
avatar_y = ((205, 320), (625, 740))
|
|
avatar_p = []
|
|
for x in name_x:
|
|
for y in avatar_y:
|
|
avatar_p.append(tuple(zip(x, y)))
|
|
|
|
logger.debug(avatar_p)
|
|
return avatar_p
|
|
|
|
|
|
def segment_team(img: tp.Image) -> list[tp.Scope]:
|
|
"编队界面"
|
|
# TODO: 利用img判断编队缺人的情况
|
|
result = []
|
|
for i in range(6):
|
|
x = 283 + 232 * i
|
|
for y in [204, 637]:
|
|
result.append(((x, y), va((x, y), (180, 110))))
|
|
logger.debug(result)
|
|
return result
|
|
|
|
|
|
def segment_team_select(img: tp.Image) -> list[tp.Scope]:
|
|
"作战编队和训练位选干员"
|
|
line1 = cropimg(img, ((540, 513), (1920, 514)))
|
|
hsv = cv2.cvtColor(line1, cv2.COLOR_RGB2HSV)
|
|
mask = cv2.inRange(hsv, (98, 150, 200), (102, 255, 255))
|
|
line1 = cv2.cvtColor(line1, cv2.COLOR_RGB2GRAY)
|
|
line1[mask > 0] = (255,)
|
|
line1 = thres2(line1, 140)
|
|
last_line = line1[-1]
|
|
prev = last_line[0]
|
|
start = None
|
|
name_x = []
|
|
for i in range(1, line1.shape[1]):
|
|
curr = last_line[i]
|
|
if prev == 255 and curr == 0 and start and i - start > 90:
|
|
name_x.append((i + 450, i + 630))
|
|
elif prev == 0 and curr == 255:
|
|
start = i
|
|
prev = curr
|
|
|
|
avatar_y = ((200, 310), (620, 725))
|
|
avatar_p = []
|
|
for x in name_x:
|
|
for y in avatar_y:
|
|
avatar_p.append(tuple(zip(x, y)))
|
|
|
|
logger.debug(avatar_p)
|
|
return avatar_p
|
|
|
|
|
|
def match_operator(
|
|
gray: tp.GrayImage, segment: list[tp.Scope], model: list
|
|
) -> tuple[tuple[str, tp.Scope]]:
|
|
if len(segment) == 0:
|
|
logger.debug(f"{len(segment)=}")
|
|
return ()
|
|
|
|
avatar_p = [[None, 0]] * len(segment)
|
|
|
|
mask = np.zeros(gray.shape, dtype=np.uint8)
|
|
for pt1, pt2 in segment:
|
|
cv2.rectangle(mask, pt1, pt2, (255,), -1)
|
|
|
|
ori_kp, ori_des = keypoints(gray, mask)
|
|
|
|
def match(item):
|
|
name, des = item
|
|
return name, flann.knnMatch(des, ori_des, k=2)
|
|
|
|
if config.conf.max_workers > 1:
|
|
with ThreadPoolExecutor(max_workers=config.conf.max_workers) as executor:
|
|
result = executor.map(match, model)
|
|
else:
|
|
result = [match(i) for i in model]
|
|
|
|
for name, matches in result:
|
|
good = []
|
|
for pair in matches:
|
|
if len(pair) == 2:
|
|
x, y = pair
|
|
if x.distance < GOOD_DISTANCE_LIMIT * y.distance:
|
|
good.append(ori_kp[x.trainIdx].pt)
|
|
elif len(pair) == 1:
|
|
x = pair[0]
|
|
good.append(ori_kp[x.trainIdx].pt)
|
|
count = [0] * len(segment)
|
|
for i, scope in enumerate(segment):
|
|
for g in good:
|
|
if in_scope(scope, g):
|
|
count[i] += 1
|
|
for i, c in enumerate(count):
|
|
if c > avatar_p[i][1]:
|
|
avatar_p[i] = name, c
|
|
|
|
op_name = [p[0] for p in avatar_p]
|
|
logger.debug(op_name)
|
|
|
|
return tuple(zip(op_name, segment))
|
|
|
|
|
|
match_portrait = partial(match_operator, model=portrait)
|
|
match_avatar = partial(match_operator, model=avatar)
|
|
|
|
|
|
def operator_room_select(img: tp.Image) -> tuple[tuple[str, tp.Scope]]:
|
|
"基建房间内选干员"
|
|
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
|
|
return match_portrait(gray, segment_room_select(img))
|
|
|
|
|
|
def operator_team(img: tp.Image) -> tuple[tuple[str, tp.Scope]]:
|
|
"编队界面"
|
|
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
|
|
return match_portrait(gray, segment_team(img))
|
|
|
|
|
|
def operator_team_select(img: tp.Image) -> tuple[tuple[str, tp.Scope]]:
|
|
"作战编队和训练位选干员"
|
|
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
|
|
return match_portrait(gray, segment_team_select(img))
|