LittleApple-fp16's picture
Upload 88 files
4f8ad24
import os
from typing import Iterator, Optional
from imgutils.detect import detect_person, detect_heads, detect_halfbody, detect_eyes
from .base import BaseAction
from ..model import ImageItem
class PersonSplitAction(BaseAction):
def __init__(self, keep_original: bool = False, level: str = 'm', version: str = 'v1.1',
conf_threshold: float = 0.3, iou_threshold: float = 0.5, keep_origin_tags: bool = False):
self.keep_original = keep_original
self.level = level
self.version = version
self.conf_threshold = conf_threshold
self.iou_threshold = iou_threshold
self.keep_origin_tags = keep_origin_tags
def iter(self, item: ImageItem) -> Iterator[ImageItem]:
detection = detect_person(item.image, self.level, self.version,
conf_threshold=self.conf_threshold, iou_threshold=self.iou_threshold)
if 'filename' in item.meta:
filename = item.meta['filename']
filebody, ext = os.path.splitext(filename)
else:
filebody, ext = None, None
if self.keep_original:
yield item
for i, (area, type_, score) in enumerate(detection):
new_meta = {
**item.meta,
'crop': {'type': type_, 'score': score},
}
if 'tags' in new_meta and not self.keep_origin_tags:
del new_meta['tags']
if filebody is not None:
new_meta['filename'] = f'{filebody}_person{i}{ext}'
yield ImageItem(item.image.crop(area), new_meta)
def reset(self):
pass
class ThreeStageSplitAction(BaseAction):
def __init__(self, person_conf: Optional[dict] = None, halfbody_conf: Optional[dict] = None,
head_conf: Optional[dict] = None, head_scale: float = 1.5,
split_eyes: bool = False, eye_conf: Optional[dict] = None, eye_scale: float = 2.4,
split_person: bool = True, keep_origin_tags: bool = False):
self.person_conf = dict(person_conf or {})
self.halfbody_conf = dict(halfbody_conf or {})
self.head_conf = dict(head_conf or {})
self.eye_conf = dict(eye_conf or {})
self.head_scale = head_scale
self.eye_scale = eye_scale
self.split_eyes = split_eyes
self.split_person = split_person
self.keep_origin_tags = keep_origin_tags
def _split_person(self, item: ImageItem, filebody, ext):
if self.split_person:
for i, (px, type_, score) in enumerate(detect_person(item.image, **self.person_conf), start=1):
person_image = item.image.crop(px)
person_meta = {
**item.meta,
'crop': {'type': type_, 'score': score},
}
if 'tags' in person_meta and not self.keep_origin_tags:
del person_meta['tags']
if filebody is not None:
person_meta['filename'] = f'{filebody}_person{i}{ext}'
yield i, ImageItem(person_image, person_meta)
else:
yield 1, item
def iter(self, item: ImageItem) -> Iterator[ImageItem]:
if 'filename' in item.meta:
filename = item.meta['filename']
filebody, ext = os.path.splitext(filename)
else:
filebody, ext = None, None
for i, person_item in self._split_person(item, filebody, ext):
person_image = person_item.image
yield person_item
half_detects = detect_halfbody(person_image, **self.halfbody_conf)
if half_detects:
halfbody_area, halfbody_type, halfbody_score = half_detects[0]
halfbody_image = person_image.crop(halfbody_area)
halfbody_meta = {
**item.meta,
'crop': {'type': halfbody_type, 'score': halfbody_score},
}
if 'tags' in halfbody_meta and not self.keep_origin_tags:
del halfbody_meta['tags']
if filebody is not None:
halfbody_meta['filename'] = f'{filebody}_person{i}_halfbody{ext}'
yield ImageItem(halfbody_image, halfbody_meta)
head_detects = detect_heads(person_image, **self.head_conf)
if head_detects:
(hx0, hy0, hx1, hy1), head_type, head_score = head_detects[0]
cx, cy = (hx0 + hx1) / 2, (hy0 + hy1) / 2
width, height = hx1 - hx0, hy1 - hy0
width = height = max(width, height) * self.head_scale
x0, y0 = int(max(cx - width / 2, 0)), int(max(cy - height / 2, 0))
x1, y1 = int(min(cx + width / 2, person_image.width)), int(min(cy + height / 2, person_image.height))
head_image = person_image.crop((x0, y0, x1, y1))
head_meta = {
**item.meta,
'crop': {'type': head_type, 'score': head_score},
}
if 'tags' in head_meta and not self.keep_origin_tags:
del head_meta['tags']
if filebody is not None:
head_meta['filename'] = f'{filebody}_person{i}_head{ext}'
yield ImageItem(head_image, head_meta)
if self.split_eyes:
eye_detects = detect_eyes(head_image, **self.eye_conf)
for j, ((ex0, ey0, ex1, ey1), eye_type, eye_score) in enumerate(eye_detects):
cx, cy = (ex0 + ex1) / 2, (ey0 + ey1) / 2
width, height = ex1 - ex0, ey1 - ey0
width = height = max(width, height) * self.eye_scale
x0, y0 = int(max(cx - width / 2, 0)), int(max(cy - height / 2, 0))
x1, y1 = int(min(cx + width / 2, head_image.width)), \
int(min(cy + height / 2, head_image.height))
eye_image = head_image.crop((x0, y0, x1, y1))
eye_meta = {
**item.meta,
'crop': {'type': eye_type, 'score': eye_score},
}
if 'tags' in eye_meta and not self.keep_origin_tags:
del eye_meta['tags']
if filebody is not None:
eye_meta['filename'] = f'{filebody}_person{i}_head_eye{j}{ext}'
yield ImageItem(eye_image, eye_meta)
def reset(self):
pass