def editBorder(self, blob, lines): points = [blob.drawLine(line) for line in lines] if points is None or len(points) == 0: return # compute the box for the outer contour intersected = False (mask, box, intersected) = self.editBorderContour(blob, blob.contour, points) pointIntersectsContours = intersected for contour in blob.inner_contours: (inner_mask, inner_box, intersected) = self.editBorderContour(blob, contour, points) pointIntersectsContours = pointIntersectsContours or intersected Mask.paintMask(mask, box, inner_mask, inner_box, 0) if not pointIntersectsContours: #probably a hole, draw the points fill the hole and subtract from mask allpoints = np.empty(shape=(0, 2), dtype=int) for arc in points: allpoints = np.append(allpoints, arc, axis=0) points_box = Mask.pointsBox(allpoints, 4) (points_mask, points_box) = Mask.jointMask(points_box, points_box) Mask.paintPoints(points_mask, points_box, allpoints, 1) origin = np.array([points_box[1], points_box[0]]) Mask.paintPoints(points_mask, points_box, allpoints - origin, 1) points_mask = ndi.binary_fill_holes(points_mask) points_mask = binary_erosion(points_mask) Mask.paintMask(mask, box, points_mask, points_box, 0) blob.updateUsingMask(box, mask)
def editBorder(self, blob, lines): #need padding #would be lovely to be able do edit holes too. #the main problem is snapping to the external contour points = blob.lineToPoints(lines, snap=True) if points is None: return if len(points) == 0: return pointsbox = Mask.pointsBox(points, 3) blobmask = blob.getMask() #add to mask painting the points as 1 and filling the holes. (mask, box) = Mask.jointMask(blob.bbox, pointsbox) Mask.paintMask(mask, box, blobmask, blob.bbox, 1) #save holes full = ndi.binary_fill_holes(mask.astype(int)) holes = full & ~mask #cut from mask Mask.paintPoints(mask, box, points, 1) mask = ndi.binary_fill_holes(mask.astype(int)) #erase the points to carve to remove the internal parts. Mask.paintPoints(mask, box, points, 0) #add back holes mask = mask & ~holes regions = measure.regionprops(measure.label(mask)) if len(regions): largest = regions[0] for region in regions: if region.area > largest.area: largest = region #adjust the image bounding box (relative to the region mask) to directly use area.image mask #image box is standard (minx, miny, maxx, maxy) box = np.array([ box[0] + largest.bbox[0], box[1] + largest.bbox[1], largest.bbox[3], largest.bbox[2] ]) blob.updateUsingMask(box, largest.image.astype(int))
def addingIntersection(self, blobA, blobB, blobC): """ Update the blobA by adding to it the intersection between the blobB and the blobC """ mask_intersect, bbox_intersect = Mask.intersectMask( blobB.getMask(), blobB.bbox, blobC.getMask(), blobC.bbox) bbox = Mask.jointBox([blobA.bbox, bbox_intersect]) (mask, bbox) = Mask.jointMask(bbox, bbox) Mask.paintMask(mask, bbox, blobA.getMask(), blobA.bbox, 1) Mask.paintMask(mask, bbox, mask_intersect, bbox_intersect, 1) if mask.any(): blobA.updateUsingMask(bbox, mask.astype(int))
def editBorder(self, blob, lines): points = [blob.drawLine(line) for line in lines] if points is None or len(points) == 0: return # compute the box for the outer contour (mask, box) = self.editBorderContour(blob, blob.contour, points) for contour in blob.inner_contours: (inner_mask, inner_box) = self.editBorderContour(blob, contour, points) Mask.paintMask(mask, box, inner_mask, inner_box, 0) blob.updateUsingMask(box, mask) return
def union(self, blobs): """ Create a new blob that is the union of the (two) blobs given """ #boxs are in image space, masks invert x and y. boxes = [] for blob in blobs: boxes.append(blob.bbox) box = Mask.jointBox(boxes) (mask, box) = Mask.jointMask(box, box) for blob in blobs: Mask.paintMask(mask, box, blob.getMask(), blob.bbox, 1) if mask.any(): # measure is brutally slower with non int types (factor 4), while byte&bool would be faster by 25%, conversion is fast. blob = blobs[0].copy() blob.updateUsingMask(box, mask.astype(int)) return blob return None