def split_on_lines(regions, frame): rois = [] for region in regions: roi = Rectangle.from_bbox(region.bbox) fragment = Rectangle.from_bbox(region.bbox).sample_from_image(frame) lines = lines_y(fragment) if not len(lines): rois.append(roi) continue distances = [] line_midpoints = list(map(lambda line: Point((line[0] + line[2]) // 2, (line[1] + line[3]) // 2), lines)) center = Point(roi.w // 2, roi.h // 2) dist_from_center = lambda point: Point.point_distance(center, point) distances = list(map(dist_from_center, line_midpoints)) _, central_line_midpoint = min(zip(distances, line_midpoints), key= lambda pair: pair[0]) mid_x = central_line_midpoint.x left_w = mid_x right_w = roi.w - mid_x if (left_w / right_w > 0.5 and left_w / right_w < 2): left = Rectangle(roi.x, roi.y, left_w, roi.h) right = Rectangle(roi.x + left_w, roi.y, right_w, roi.h) rois.extend([left, right]) else: rois.append(roi) return rois
def detect(frame): img_hsv = bgr_to_equalized_hsv(frame) mask = cv2.inRange(img_hsv, (10, 0, 0), (80, 360, 360)) cleared = remove_large_border_segments(mask) regions = select_regions(cleared) center = Point(cleared.shape[0] // 2, cleared.shape[1] // 2) dist_from_center = lambda region: Point.point_distance(center, Point(*region.centroid)) sorted_regions = sorted(regionprops(label(regions)), key=dist_from_center) vertical = filter(lambda region: abs(region.orientation - sorted_regions[0].orientation) < 1.5, sorted_regions) close_to_center = filter(lambda region: dist_from_center(region) < frame.shape[1]/3.2, vertical) split = split_on_lines(close_to_center, frame) if len(split) < 2: return split upper, lower = split[:2] if upper.x > lower.x: lower, upper = upper, lower return [upper, lower]