Module compoelem.detect.openpose_common_utils
Expand source code
import cv2
from enum import Enum
class CocoPart(Enum):
Nose = 0
Neck = 1
RShoulder = 2
RElbow = 3
RWrist = 4
LShoulder = 5
LElbow = 6
LWrist = 7
RHip = 8
RKnee = 9
RAnkle = 10
LHip = 11
LKnee = 12
LAnkle = 13
REye = 14
LEye = 15
REar = 16
LEar = 17
Background = 18
class Human:
"""
body_parts: list of BodyPart
"""
__slots__ = ('body_parts', 'pairs', 'uidx_list', 'score')
def __init__(self, pairs):
self.pairs = []
self.uidx_list = set()
self.body_parts = {}
for pair in pairs:
self.add_pair(pair)
self.score = 0.0
@staticmethod
def _get_uidx(part_idx, idx):
return '%d-%d' % (part_idx, idx)
def add_pair(self, pair):
self.pairs.append(pair)
self.body_parts[pair.part_idx1] = BodyPart(Human._get_uidx(pair.part_idx1, pair.idx1),
pair.part_idx1,
pair.coord1[0], pair.coord1[1], pair.score)
self.body_parts[pair.part_idx2] = BodyPart(Human._get_uidx(pair.part_idx2, pair.idx2),
pair.part_idx2,
pair.coord2[0], pair.coord2[1], pair.score)
self.uidx_list.add(Human._get_uidx(pair.part_idx1, pair.idx1))
self.uidx_list.add(Human._get_uidx(pair.part_idx2, pair.idx2))
def is_connected(self, other):
return len(self.uidx_list & other.uidx_list) > 0
def merge(self, other):
for pair in other.pairs:
self.add_pair(pair)
def part_count(self):
return len(self.body_parts.keys())
def get_max_score(self):
return max([x.score for _, x in self.body_parts.items()])
def get_face_box(self, img_w, img_h, mode=0):
"""
Get Face box compared to img size (w, h)
:param img_w:
:param img_h:
:param mode:
:return:
"""
# SEE : https://github.com/ildoonet/tf-pose-estimation/blob/master/tf_pose/common.py#L13
_NOSE = CocoPart.Nose.value
_NECK = CocoPart.Neck.value
_REye = CocoPart.REye.value
_LEye = CocoPart.LEye.value
_REar = CocoPart.REar.value
_LEar = CocoPart.LEar.value
_THRESHOLD_PART_CONFIDENCE = 0.2
parts = [part for idx, part in self.body_parts.items() if part.score > _THRESHOLD_PART_CONFIDENCE]
is_nose, part_nose = _include_part(parts, _NOSE)
if not is_nose:
return None
size = 0
is_neck, part_neck = _include_part(parts, _NECK)
if is_neck:
size = max(size, img_h * (part_neck.y - part_nose.y) * 0.8)
is_reye, part_reye = _include_part(parts, _REye)
is_leye, part_leye = _include_part(parts, _LEye)
if is_reye and is_leye:
size = max(size, img_w * (part_reye.x - part_leye.x) * 2.0)
size = max(size,
img_w * math.sqrt((part_reye.x - part_leye.x) ** 2 + (part_reye.y - part_leye.y) ** 2) * 2.0)
if mode == 1:
if not is_reye and not is_leye:
return None
is_rear, part_rear = _include_part(parts, _REar)
is_lear, part_lear = _include_part(parts, _LEar)
if is_rear and is_lear:
size = max(size, img_w * (part_rear.x - part_lear.x) * 1.6)
if size <= 0:
return None
if not is_reye and is_leye:
x = part_nose.x * img_w - (size // 3 * 2)
elif is_reye and not is_leye:
x = part_nose.x * img_w - (size // 3)
else: # is_reye and is_leye:
x = part_nose.x * img_w - size // 2
x2 = x + size
if mode == 0:
y = part_nose.y * img_h - size // 3
else:
y = part_nose.y * img_h - _round(size / 2 * 1.2)
y2 = y + size
# fit into the image frame
x = max(0, x)
y = max(0, y)
x2 = min(img_w - x, x2 - x) + x
y2 = min(img_h - y, y2 - y) + y
if _round(x2 - x) == 0.0 or _round(y2 - y) == 0.0:
return None
if mode == 0:
return {"x": _round((x + x2) / 2),
"y": _round((y + y2) / 2),
"w": _round(x2 - x),
"h": _round(y2 - y)}
else:
return {"x": _round(x),
"y": _round(y),
"w": _round(x2 - x),
"h": _round(y2 - y)}
def get_upper_body_box(self, img_w, img_h):
"""
Get Upper body box compared to img size (w, h)
:param img_w:
:param img_h:
:return:
"""
if not (img_w > 0 and img_h > 0):
raise Exception("img size should be positive")
_NOSE = CocoPart.Nose.value
_NECK = CocoPart.Neck.value
_RSHOULDER = CocoPart.RShoulder.value
_LSHOULDER = CocoPart.LShoulder.value
_THRESHOLD_PART_CONFIDENCE = 0.3
parts = [part for idx, part in self.body_parts.items() if part.score > _THRESHOLD_PART_CONFIDENCE]
part_coords = [(img_w * part.x, img_h * part.y) for part in parts if
part.part_idx in [0, 1, 2, 5, 8, 11, 14, 15, 16, 17]]
if len(part_coords) < 5:
return None
# Initial Bounding Box
x = min([part[0] for part in part_coords])
y = min([part[1] for part in part_coords])
x2 = max([part[0] for part in part_coords])
y2 = max([part[1] for part in part_coords])
# # ------ Adjust heuristically +
# if face points are detcted, adjust y value
is_nose, part_nose = _include_part(parts, _NOSE)
is_neck, part_neck = _include_part(parts, _NECK)
torso_height = 0
if is_nose and is_neck:
y -= (part_neck.y * img_h - y) * 0.8
torso_height = max(0, (part_neck.y - part_nose.y) * img_h * 2.5)
#
# # by using shoulder position, adjust width
is_rshoulder, part_rshoulder = _include_part(parts, _RSHOULDER)
is_lshoulder, part_lshoulder = _include_part(parts, _LSHOULDER)
if is_rshoulder and is_lshoulder:
half_w = x2 - x
dx = half_w * 0.15
x -= dx
x2 += dx
elif is_neck:
if is_lshoulder and not is_rshoulder:
half_w = abs(part_lshoulder.x - part_neck.x) * img_w * 1.15
x = min(part_neck.x * img_w - half_w, x)
x2 = max(part_neck.x * img_w + half_w, x2)
elif not is_lshoulder and is_rshoulder:
half_w = abs(part_rshoulder.x - part_neck.x) * img_w * 1.15
x = min(part_neck.x * img_w - half_w, x)
x2 = max(part_neck.x * img_w + half_w, x2)
# ------ Adjust heuristically -
# fit into the image frame
x = max(0, x)
y = max(0, y)
x2 = min(img_w - x, x2 - x) + x
y2 = min(img_h - y, y2 - y) + y
if _round(x2 - x) == 0.0 or _round(y2 - y) == 0.0:
return None
return {"x": _round((x + x2) / 2),
"y": _round((y + y2) / 2),
"w": _round(x2 - x),
"h": _round(y2 - y)}
def __str__(self):
return ' '.join([str(x) for x in self.body_parts.values()])
def __repr__(self):
return self.__str__()
def draw_humans(npimg, humans, imgcopy=False):
if imgcopy:
npimg = np.copy(npimg)
image_h, image_w = npimg.shape[:2]
centers = {}
for human in humans:
# draw point
for i in range(CocoPart.Background.value):
if i not in human.body_parts.keys():
continue
body_part = human.body_parts[i]
center = (int(body_part.x * image_w + 0.5), int(body_part.y * image_h + 0.5))
centers[i] = center
cv2.circle(npimg, center, 3, CocoColors[i], thickness=3, lineType=8, shift=0)
# draw line
for pair_order, pair in enumerate(CocoPairsRender):
if pair[0] not in human.body_parts.keys() or pair[1] not in human.body_parts.keys():
continue
# npimg = cv2.line(npimg, centers[pair[0]], centers[pair[1]], common.CocoColors[pair_order], 3)
cv2.line(npimg, centers[pair[0]], centers[pair[1]], CocoColors[pair_order], 3)
return npimg
class BodyPart:
"""
part_idx : part index(eg. 0 for nose)
x, y: coordinate of body part
score : confidence score
"""
__slots__ = ('uidx', 'part_idx', 'x', 'y', 'score')
def __init__(self, uidx, part_idx, x, y, score):
self.uidx = uidx
self.part_idx = part_idx
self.x, self.y = x, y
self.score = score
def get_part_name(self):
return CocoPart(self.part_idx)
def __str__(self):
return 'BodyPart:%d-(%.2f, %.2f) score=%.2f' % (self.part_idx, self.x, self.y, self.score)
def __repr__(self):
return self.__str__()
CocoColors = [[255, 0, 0], [255, 85, 0], [255, 170, 0], [255, 255, 0], [170, 255, 0], [85, 255, 0], [0, 255, 0],
[0, 255, 85], [0, 255, 170], [0, 255, 255], [0, 170, 255], [0, 85, 255], [0, 0, 255], [85, 0, 255],
[170, 0, 255], [255, 0, 255], [255, 0, 170], [255, 0, 85]]
CocoPairs = [
(1, 2), (1, 5), (2, 3), (3, 4), (5, 6), (6, 7), (1, 8), (8, 9), (9, 10), (1, 11),
(11, 12), (12, 13), (1, 0), (0, 14), (14, 16), (0, 15), (15, 17), (2, 16), (5, 17)
] # = 19
CocoPairsRender = CocoPairs[:-2]
Functions
def draw_humans(npimg, humans, imgcopy=False)
-
Expand source code
def draw_humans(npimg, humans, imgcopy=False): if imgcopy: npimg = np.copy(npimg) image_h, image_w = npimg.shape[:2] centers = {} for human in humans: # draw point for i in range(CocoPart.Background.value): if i not in human.body_parts.keys(): continue body_part = human.body_parts[i] center = (int(body_part.x * image_w + 0.5), int(body_part.y * image_h + 0.5)) centers[i] = center cv2.circle(npimg, center, 3, CocoColors[i], thickness=3, lineType=8, shift=0) # draw line for pair_order, pair in enumerate(CocoPairsRender): if pair[0] not in human.body_parts.keys() or pair[1] not in human.body_parts.keys(): continue # npimg = cv2.line(npimg, centers[pair[0]], centers[pair[1]], common.CocoColors[pair_order], 3) cv2.line(npimg, centers[pair[0]], centers[pair[1]], CocoColors[pair_order], 3) return npimg
Classes
class BodyPart (uidx, part_idx, x, y, score)
-
part_idx : part index(eg. 0 for nose) x, y: coordinate of body part score : confidence score
Expand source code
class BodyPart: """ part_idx : part index(eg. 0 for nose) x, y: coordinate of body part score : confidence score """ __slots__ = ('uidx', 'part_idx', 'x', 'y', 'score') def __init__(self, uidx, part_idx, x, y, score): self.uidx = uidx self.part_idx = part_idx self.x, self.y = x, y self.score = score def get_part_name(self): return CocoPart(self.part_idx) def __str__(self): return 'BodyPart:%d-(%.2f, %.2f) score=%.2f' % (self.part_idx, self.x, self.y, self.score) def __repr__(self): return self.__str__()
Instance variables
var part_idx
-
Return an attribute of instance, which is of type owner.
var score
-
Return an attribute of instance, which is of type owner.
var uidx
-
Return an attribute of instance, which is of type owner.
var x
-
Return an attribute of instance, which is of type owner.
var y
-
Return an attribute of instance, which is of type owner.
Methods
def get_part_name(self)
-
Expand source code
def get_part_name(self): return CocoPart(self.part_idx)
class CocoPart (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
An enumeration.
Expand source code
class CocoPart(Enum): Nose = 0 Neck = 1 RShoulder = 2 RElbow = 3 RWrist = 4 LShoulder = 5 LElbow = 6 LWrist = 7 RHip = 8 RKnee = 9 RAnkle = 10 LHip = 11 LKnee = 12 LAnkle = 13 REye = 14 LEye = 15 REar = 16 LEar = 17 Background = 18
Ancestors
- enum.Enum
Class variables
var Background
var LAnkle
var LEar
var LElbow
var LEye
var LHip
var LKnee
var LShoulder
var LWrist
var Neck
var Nose
var RAnkle
var REar
var RElbow
var REye
var RHip
var RKnee
var RShoulder
var RWrist
class Human (pairs)
-
body_parts: list of BodyPart
Expand source code
class Human: """ body_parts: list of BodyPart """ __slots__ = ('body_parts', 'pairs', 'uidx_list', 'score') def __init__(self, pairs): self.pairs = [] self.uidx_list = set() self.body_parts = {} for pair in pairs: self.add_pair(pair) self.score = 0.0 @staticmethod def _get_uidx(part_idx, idx): return '%d-%d' % (part_idx, idx) def add_pair(self, pair): self.pairs.append(pair) self.body_parts[pair.part_idx1] = BodyPart(Human._get_uidx(pair.part_idx1, pair.idx1), pair.part_idx1, pair.coord1[0], pair.coord1[1], pair.score) self.body_parts[pair.part_idx2] = BodyPart(Human._get_uidx(pair.part_idx2, pair.idx2), pair.part_idx2, pair.coord2[0], pair.coord2[1], pair.score) self.uidx_list.add(Human._get_uidx(pair.part_idx1, pair.idx1)) self.uidx_list.add(Human._get_uidx(pair.part_idx2, pair.idx2)) def is_connected(self, other): return len(self.uidx_list & other.uidx_list) > 0 def merge(self, other): for pair in other.pairs: self.add_pair(pair) def part_count(self): return len(self.body_parts.keys()) def get_max_score(self): return max([x.score for _, x in self.body_parts.items()]) def get_face_box(self, img_w, img_h, mode=0): """ Get Face box compared to img size (w, h) :param img_w: :param img_h: :param mode: :return: """ # SEE : https://github.com/ildoonet/tf-pose-estimation/blob/master/tf_pose/common.py#L13 _NOSE = CocoPart.Nose.value _NECK = CocoPart.Neck.value _REye = CocoPart.REye.value _LEye = CocoPart.LEye.value _REar = CocoPart.REar.value _LEar = CocoPart.LEar.value _THRESHOLD_PART_CONFIDENCE = 0.2 parts = [part for idx, part in self.body_parts.items() if part.score > _THRESHOLD_PART_CONFIDENCE] is_nose, part_nose = _include_part(parts, _NOSE) if not is_nose: return None size = 0 is_neck, part_neck = _include_part(parts, _NECK) if is_neck: size = max(size, img_h * (part_neck.y - part_nose.y) * 0.8) is_reye, part_reye = _include_part(parts, _REye) is_leye, part_leye = _include_part(parts, _LEye) if is_reye and is_leye: size = max(size, img_w * (part_reye.x - part_leye.x) * 2.0) size = max(size, img_w * math.sqrt((part_reye.x - part_leye.x) ** 2 + (part_reye.y - part_leye.y) ** 2) * 2.0) if mode == 1: if not is_reye and not is_leye: return None is_rear, part_rear = _include_part(parts, _REar) is_lear, part_lear = _include_part(parts, _LEar) if is_rear and is_lear: size = max(size, img_w * (part_rear.x - part_lear.x) * 1.6) if size <= 0: return None if not is_reye and is_leye: x = part_nose.x * img_w - (size // 3 * 2) elif is_reye and not is_leye: x = part_nose.x * img_w - (size // 3) else: # is_reye and is_leye: x = part_nose.x * img_w - size // 2 x2 = x + size if mode == 0: y = part_nose.y * img_h - size // 3 else: y = part_nose.y * img_h - _round(size / 2 * 1.2) y2 = y + size # fit into the image frame x = max(0, x) y = max(0, y) x2 = min(img_w - x, x2 - x) + x y2 = min(img_h - y, y2 - y) + y if _round(x2 - x) == 0.0 or _round(y2 - y) == 0.0: return None if mode == 0: return {"x": _round((x + x2) / 2), "y": _round((y + y2) / 2), "w": _round(x2 - x), "h": _round(y2 - y)} else: return {"x": _round(x), "y": _round(y), "w": _round(x2 - x), "h": _round(y2 - y)} def get_upper_body_box(self, img_w, img_h): """ Get Upper body box compared to img size (w, h) :param img_w: :param img_h: :return: """ if not (img_w > 0 and img_h > 0): raise Exception("img size should be positive") _NOSE = CocoPart.Nose.value _NECK = CocoPart.Neck.value _RSHOULDER = CocoPart.RShoulder.value _LSHOULDER = CocoPart.LShoulder.value _THRESHOLD_PART_CONFIDENCE = 0.3 parts = [part for idx, part in self.body_parts.items() if part.score > _THRESHOLD_PART_CONFIDENCE] part_coords = [(img_w * part.x, img_h * part.y) for part in parts if part.part_idx in [0, 1, 2, 5, 8, 11, 14, 15, 16, 17]] if len(part_coords) < 5: return None # Initial Bounding Box x = min([part[0] for part in part_coords]) y = min([part[1] for part in part_coords]) x2 = max([part[0] for part in part_coords]) y2 = max([part[1] for part in part_coords]) # # ------ Adjust heuristically + # if face points are detcted, adjust y value is_nose, part_nose = _include_part(parts, _NOSE) is_neck, part_neck = _include_part(parts, _NECK) torso_height = 0 if is_nose and is_neck: y -= (part_neck.y * img_h - y) * 0.8 torso_height = max(0, (part_neck.y - part_nose.y) * img_h * 2.5) # # # by using shoulder position, adjust width is_rshoulder, part_rshoulder = _include_part(parts, _RSHOULDER) is_lshoulder, part_lshoulder = _include_part(parts, _LSHOULDER) if is_rshoulder and is_lshoulder: half_w = x2 - x dx = half_w * 0.15 x -= dx x2 += dx elif is_neck: if is_lshoulder and not is_rshoulder: half_w = abs(part_lshoulder.x - part_neck.x) * img_w * 1.15 x = min(part_neck.x * img_w - half_w, x) x2 = max(part_neck.x * img_w + half_w, x2) elif not is_lshoulder and is_rshoulder: half_w = abs(part_rshoulder.x - part_neck.x) * img_w * 1.15 x = min(part_neck.x * img_w - half_w, x) x2 = max(part_neck.x * img_w + half_w, x2) # ------ Adjust heuristically - # fit into the image frame x = max(0, x) y = max(0, y) x2 = min(img_w - x, x2 - x) + x y2 = min(img_h - y, y2 - y) + y if _round(x2 - x) == 0.0 or _round(y2 - y) == 0.0: return None return {"x": _round((x + x2) / 2), "y": _round((y + y2) / 2), "w": _round(x2 - x), "h": _round(y2 - y)} def __str__(self): return ' '.join([str(x) for x in self.body_parts.values()]) def __repr__(self): return self.__str__()
Instance variables
var body_parts
-
Return an attribute of instance, which is of type owner.
var pairs
-
Return an attribute of instance, which is of type owner.
var score
-
Return an attribute of instance, which is of type owner.
var uidx_list
-
Return an attribute of instance, which is of type owner.
Methods
def add_pair(self, pair)
-
Expand source code
def add_pair(self, pair): self.pairs.append(pair) self.body_parts[pair.part_idx1] = BodyPart(Human._get_uidx(pair.part_idx1, pair.idx1), pair.part_idx1, pair.coord1[0], pair.coord1[1], pair.score) self.body_parts[pair.part_idx2] = BodyPart(Human._get_uidx(pair.part_idx2, pair.idx2), pair.part_idx2, pair.coord2[0], pair.coord2[1], pair.score) self.uidx_list.add(Human._get_uidx(pair.part_idx1, pair.idx1)) self.uidx_list.add(Human._get_uidx(pair.part_idx2, pair.idx2))
def get_face_box(self, img_w, img_h, mode=0)
-
Get Face box compared to img size (w, h) :param img_w: :param img_h: :param mode: :return:
Expand source code
def get_face_box(self, img_w, img_h, mode=0): """ Get Face box compared to img size (w, h) :param img_w: :param img_h: :param mode: :return: """ # SEE : https://github.com/ildoonet/tf-pose-estimation/blob/master/tf_pose/common.py#L13 _NOSE = CocoPart.Nose.value _NECK = CocoPart.Neck.value _REye = CocoPart.REye.value _LEye = CocoPart.LEye.value _REar = CocoPart.REar.value _LEar = CocoPart.LEar.value _THRESHOLD_PART_CONFIDENCE = 0.2 parts = [part for idx, part in self.body_parts.items() if part.score > _THRESHOLD_PART_CONFIDENCE] is_nose, part_nose = _include_part(parts, _NOSE) if not is_nose: return None size = 0 is_neck, part_neck = _include_part(parts, _NECK) if is_neck: size = max(size, img_h * (part_neck.y - part_nose.y) * 0.8) is_reye, part_reye = _include_part(parts, _REye) is_leye, part_leye = _include_part(parts, _LEye) if is_reye and is_leye: size = max(size, img_w * (part_reye.x - part_leye.x) * 2.0) size = max(size, img_w * math.sqrt((part_reye.x - part_leye.x) ** 2 + (part_reye.y - part_leye.y) ** 2) * 2.0) if mode == 1: if not is_reye and not is_leye: return None is_rear, part_rear = _include_part(parts, _REar) is_lear, part_lear = _include_part(parts, _LEar) if is_rear and is_lear: size = max(size, img_w * (part_rear.x - part_lear.x) * 1.6) if size <= 0: return None if not is_reye and is_leye: x = part_nose.x * img_w - (size // 3 * 2) elif is_reye and not is_leye: x = part_nose.x * img_w - (size // 3) else: # is_reye and is_leye: x = part_nose.x * img_w - size // 2 x2 = x + size if mode == 0: y = part_nose.y * img_h - size // 3 else: y = part_nose.y * img_h - _round(size / 2 * 1.2) y2 = y + size # fit into the image frame x = max(0, x) y = max(0, y) x2 = min(img_w - x, x2 - x) + x y2 = min(img_h - y, y2 - y) + y if _round(x2 - x) == 0.0 or _round(y2 - y) == 0.0: return None if mode == 0: return {"x": _round((x + x2) / 2), "y": _round((y + y2) / 2), "w": _round(x2 - x), "h": _round(y2 - y)} else: return {"x": _round(x), "y": _round(y), "w": _round(x2 - x), "h": _round(y2 - y)}
def get_max_score(self)
-
Expand source code
def get_max_score(self): return max([x.score for _, x in self.body_parts.items()])
def get_upper_body_box(self, img_w, img_h)
-
Get Upper body box compared to img size (w, h) :param img_w: :param img_h: :return:
Expand source code
def get_upper_body_box(self, img_w, img_h): """ Get Upper body box compared to img size (w, h) :param img_w: :param img_h: :return: """ if not (img_w > 0 and img_h > 0): raise Exception("img size should be positive") _NOSE = CocoPart.Nose.value _NECK = CocoPart.Neck.value _RSHOULDER = CocoPart.RShoulder.value _LSHOULDER = CocoPart.LShoulder.value _THRESHOLD_PART_CONFIDENCE = 0.3 parts = [part for idx, part in self.body_parts.items() if part.score > _THRESHOLD_PART_CONFIDENCE] part_coords = [(img_w * part.x, img_h * part.y) for part in parts if part.part_idx in [0, 1, 2, 5, 8, 11, 14, 15, 16, 17]] if len(part_coords) < 5: return None # Initial Bounding Box x = min([part[0] for part in part_coords]) y = min([part[1] for part in part_coords]) x2 = max([part[0] for part in part_coords]) y2 = max([part[1] for part in part_coords]) # # ------ Adjust heuristically + # if face points are detcted, adjust y value is_nose, part_nose = _include_part(parts, _NOSE) is_neck, part_neck = _include_part(parts, _NECK) torso_height = 0 if is_nose and is_neck: y -= (part_neck.y * img_h - y) * 0.8 torso_height = max(0, (part_neck.y - part_nose.y) * img_h * 2.5) # # # by using shoulder position, adjust width is_rshoulder, part_rshoulder = _include_part(parts, _RSHOULDER) is_lshoulder, part_lshoulder = _include_part(parts, _LSHOULDER) if is_rshoulder and is_lshoulder: half_w = x2 - x dx = half_w * 0.15 x -= dx x2 += dx elif is_neck: if is_lshoulder and not is_rshoulder: half_w = abs(part_lshoulder.x - part_neck.x) * img_w * 1.15 x = min(part_neck.x * img_w - half_w, x) x2 = max(part_neck.x * img_w + half_w, x2) elif not is_lshoulder and is_rshoulder: half_w = abs(part_rshoulder.x - part_neck.x) * img_w * 1.15 x = min(part_neck.x * img_w - half_w, x) x2 = max(part_neck.x * img_w + half_w, x2) # ------ Adjust heuristically - # fit into the image frame x = max(0, x) y = max(0, y) x2 = min(img_w - x, x2 - x) + x y2 = min(img_h - y, y2 - y) + y if _round(x2 - x) == 0.0 or _round(y2 - y) == 0.0: return None return {"x": _round((x + x2) / 2), "y": _round((y + y2) / 2), "w": _round(x2 - x), "h": _round(y2 - y)}
def is_connected(self, other)
-
Expand source code
def is_connected(self, other): return len(self.uidx_list & other.uidx_list) > 0
def merge(self, other)
-
Expand source code
def merge(self, other): for pair in other.pairs: self.add_pair(pair)
def part_count(self)
-
Expand source code
def part_count(self): return len(self.body_parts.keys())