Esempio n. 1
0
    def refineBorder(self, box, blob, img, mask, grow):
        try:
            from coraline.Coraline import segment
            segment(img, mask, 0.0, conservative=0.07, grow=grow, radius=30)

        except Exception as e:
            msgBox = QMessageBox()
            msgBox.setText(str(e))
            msgBox.exec()
            return

        #TODO this should be moved to a function!
        area_th = 30
        created_blobs = []
        first = True
        label_image = measure.label(mask, connectivity=1)
        for region in measure.regionprops(label_image):
            if region.area > area_th:
                b = Blob(region, box[1], box[0], self.progressive_id)
                self.progressive_id += 1
                b.class_color = blob.class_color
                b.class_name = blob.class_name
                created_blobs.append(b)

        return created_blobs
Esempio n. 2
0
    def apply(self):
        if len(self.edit_points.points) == 0:
            self.infoMessage.emit(
                "You need to draw something for this operation.")
            return

        blob = Blob(None, 0, 0, 0)

        try:
            flagValid = blob.createFromClosedCurve(self.edit_points.points)
        except Exception:
            self.infoMessage.emit("Failed creating area.")
            self.log.emit(
                "[TOOL][FREEHAND] FREEHAND operation not done (invalid snap).")
            return

        if flagValid is True:
            blob.setId(self.viewerplus.annotations.getFreeId())

            self.viewerplus.resetSelection()
            self.viewerplus.addBlob(blob, selected=True)
            self.blobInfo.emit(blob, "[TOOL][FREEHAND][BLOB-CREATED]")
            self.viewerplus.saveUndo()

            self.log.emit("[TOOL][FREEHAND] Operation ends.")

        else:
            self.log.emit("[TOOL][FREEHAND] Operation ends (INVALID SNAP!).")
            return

        self.viewerplus.resetTools()
Esempio n. 3
0
    def import_label_map(self,
                         filename,
                         labels_info,
                         w_target,
                         h_target,
                         create_holes=False):
        """
        It imports a label map and create the corresponding blobs.
        The label map is rescaled such that it coincides with the reference map.
        """

        qimg_label_map = QImage(filename)
        qimg_label_map = qimg_label_map.convertToFormat(QImage.Format_RGB32)

        if w_target > 0 and h_target > 0:
            qimg_label_map = qimg_label_map.scaled(w_target, h_target,
                                                   Qt.IgnoreAspectRatio,
                                                   Qt.FastTransformation)

        label_map = utils.qimageToNumpyArray(qimg_label_map)
        label_map = label_map.astype(np.int32)

        # RGB -> label code association (ok, it is a dirty trick but it saves time..)
        label_coded = label_map[:, :, 0] + (label_map[:, :, 1] << 8) + (
            label_map[:, :, 2] << 16)

        labels = measure.label(label_coded, connectivity=1)

        too_much_small_area = 50
        region_big = None

        created_blobs = []
        for region in measure.regionprops(labels):
            if region.area > too_much_small_area:
                id = len(self.seg_blobs)
                blob = Blob(region, 0, 0, self.getFreeId())

                # assign class
                row = region.coords[0, 0]
                col = region.coords[0, 1]
                color = label_map[row, col]

                for label_name in labels_info.keys():
                    c = labels_info[label_name]
                    if c[0] == color[0] and c[1] == color[1] and c[2] == color[
                            2]:
                        blob.class_name = label_name
                        blob.class_color = c
                        break
                if create_holes or blob.class_name is not 'Empty':
                    created_blobs.append(blob)

        return created_blobs
Esempio n. 4
0
    def autoMatch(self, blobs1, blobs2):
        self.correspondences.clear()
        for blob1 in blobs1:
            for blob2 in blobs2:
                # use bb to quickly calculate intersection
                x1 = max(blob1.bbox[0], blob2.bbox[0])
                y1 = max(blob1.bbox[1], blob2.bbox[1])
                x2 = min(blob1.bbox[0] + blob1.bbox[3],
                         blob2.bbox[0] + blob2.bbox[3])
                y2 = min(blob1.bbox[1] + blob1.bbox[2],
                         blob2.bbox[1] + blob2.bbox[2])
                # compute the area of intersection rectangle
                interArea = abs(max((x2 - x1, 0)) * max((y2 - y1), 0))

                if interArea != 0 and blob2.class_name == blob1.class_name and blob1.class_name != 'Empty':
                    # this is the get mask function for the outer contours, I put it here using two different if conditions so getMask just runs just on intersections
                    mask1 = Blob.getMask(blob1)
                    sizeblob1 = np.count_nonzero(mask1)
                    mask2 = Blob.getMask(blob2)
                    sizeblob2 = np.count_nonzero(mask2)
                    minblob = min(sizeblob1, sizeblob2)
                    mask, bbox = intersectMask(mask1, blob1.bbox, mask2,
                                               blob2.bbox)
                    intersectionArea = np.count_nonzero(mask)

                    if (intersectionArea < (0.6 * minblob)):
                        continue
                    if (sizeblob2 > sizeblob1 * self.threshold):
                        self.correspondences.append([
                            blob1.id, blob2.id, blob1.area, blob2.area,
                            blob1.class_name, 'grow', 'none'
                        ])

                    elif (sizeblob2 < sizeblob1 / self.threshold):
                        self.correspondences.append([
                            blob1.id, blob2.id, blob1.area, blob2.area,
                            blob1.class_name, 'shrink', 'none'
                        ])

                    else:
                        self.correspondences.append([
                            blob1.id, blob2.id, blob1.area, blob2.area,
                            blob1.class_name, 'same', 'none'
                        ])

        # operates on the correspondences found and update them
        self.assignSplit()
        self.assignFuse()

        # fill self.born and self.dead blob lists
        self.assignDead(blobs1)
        self.assignBorn(blobs2)
Esempio n. 5
0
    def import_label_map(self, filename, reference_map):
        """
        It imports a label map and create the corresponding blobs.
        The label map is rescaled such that it coincides with the reference map.
        """

        qimg_label_map = QImage(filename)
        qimg_label_map = qimg_label_map.convertToFormat(QImage.Format_RGB32)

        w = reference_map.width()
        h = reference_map.height()
        qimg_label_map = qimg_label_map.scaled(w, h, Qt.IgnoreAspectRatio,
                                               Qt.SmoothTransformation)

        label_map = utils.qimageToNumpyArray(qimg_label_map)
        label_map = label_map.astype(np.int32)

        # RGB -> label code association (ok, it is a dirty trick but it saves time..)
        label_coded = label_map[:, :, 0] + (label_map[:, :, 1] << 8) + (
            label_map[:, :, 2] << 16)

        labels = measure.label(label_coded, connectivity=1)

        label_info = Labels()

        too_much_small_area = 10
        region_big = None

        created_blobs = []
        for region in measure.regionprops(labels):
            if region.area > too_much_small_area:
                id = len(self.seg_blobs)
                blob = Blob(region, 0, 0, id + 1)

                # assign class
                row = region.coords[0, 0]
                col = region.coords[0, 1]
                color = label_map[row, col]

                index = label_info.searchColor(color)

                if index >= 0:

                    blob.class_name = label_info.getClassName(index)
                    blob.class_color = label_info.getColorByIndex(index)

                    created_blobs.append(blob)

        return created_blobs
Esempio n. 6
0
    def import_label_map(self, filename, reference_map):
        """
        It imports a label map and create the corresponding blobs.
        The label map is rescaled such that it coincides with the reference map.
        """

        qimg_label_map = QImage(filename)
        qimg_label_map = qimg_label_map.convertToFormat(QImage.Format_RGB32)

        w = reference_map.width()
        h = reference_map.height()
        qimg_label_map = qimg_label_map.scaled(w, h, Qt.IgnoreAspectRatio,
                                               Qt.SmoothTransformation)

        label_map = utils.qimageToNumpyArray(qimg_label_map)
        label_map = label_map.astype(np.int32)

        # RGB -> label code association (ok, it is a dirty trick but it saves time..)
        label_coded = label_map[:, :, 0] + (label_map[:, :, 1] << 8) + (
            label_map[:, :, 2] << 16)

        labels = measure.label(label_coded, connectivity=1)

        too_much_small_area = 1000
        region_big = None

        created_blobs = []
        for region in measure.regionprops(labels):
            if region.area > too_much_small_area:
                id = len(self.seg_blobs)
                blob = Blob(region, 0, 0, self.progressive_id)
                self.progressive_id += 1

                # assign class
                row = region.coords[0, 0]
                col = region.coords[0, 1]
                color = label_map[row, col]

                for label_name in self.labels_info.keys():
                    c = self.labels_info[label_name]
                    if c[0] == color[0] and c[1] == color[1] and c[2] == color[
                            2]:
                        blob.class_name = label_name
                        blob.class_color = c
                        break

                created_blobs.append(blob)

        return created_blobs
Esempio n. 7
0
    def cut(self, blob, lines):
        """
        Given a curve specified as a set of points and a selected blob, the operation cuts it in several separed new blobs
        """
        points = blob.lineToPoints(lines, snap=False)

        mask = blob.getMask()
        original = mask.copy()
        box = blob.bbox
        #box is y, x, w, h
        Mask.paintPoints(mask, box, points, 0)

        label_image = measure.label(mask, connectivity=1)
        for point in points:
            x = point[0] - box[1]
            y = point[1] - box[0]

            if x <= 0 or y <= 0 or x >= box[2] - 1 or y >= box[3] - 1:
                continue

            if original[y][x] == 0:
                continue
            largest = 0
            largest = max(label_image[y + 1][x], largest)
            largest = max(label_image[y - 1][x], largest)
            largest = max(label_image[y][x + 1], largest)
            largest = max(label_image[y][x - 1], largest)
            label_image[y][x] = largest

        area_th = 30
        created_blobs = []
        first = True
        for region in measure.regionprops(label_image):

            if region.area > area_th:
                b = Blob(region, box[1], box[0], self.progressive_id)
                self.progressive_id += 1
                b.class_color = blob.class_color
                b.class_name = blob.class_name
                created_blobs.append(b)

        return created_blobs
Esempio n. 8
0
    def refineBorder(self, box, blob, img, depth, mask, grow, lastedit):
        clippoints = None

        if lastedit is not None:
            points = [blob.drawLine(line) for line in lastedit]
            if points is not None and len(points) > 0:
                clippoints = np.empty(shape=(0, 2), dtype=int)
                for arc in points:
                    clippoints = np.append(clippoints, arc, axis=0)
                origin = np.array([box[1], box[0]])
                clippoints = clippoints - origin
        try:
            from coraline.Coraline import segment
            segment(img,
                    depth,
                    mask,
                    clippoints,
                    0.0,
                    conservative=self.refine_conservative,
                    grow=grow,
                    radius=30,
                    depth_weight=self.refine_depth_weight)

        except Exception as e:
            print(e, flush=True)
            #msgBox = QMessageBox()
            #msgBox.setText(str(e))
            #msgBox.exec()
#            return

#TODO this should be moved to a function!
        area_th = 2
        created_blobs = []
        first = True
        label_image = measure.label(mask, connectivity=1)
        for region in measure.regionprops(label_image):
            if region.area > area_th:
                b = Blob(region, box[1], box[0], self.getFreeId())
                b.class_color = blob.class_color
                b.class_name = blob.class_name
                created_blobs.append(b)
        return created_blobs
Esempio n. 9
0
    def __init__(self,
                 rect=[0.0, 0.0, 0.0, 0.0],
                 map_px_to_mm_factor=1.0,
                 width=None,
                 height=None,
                 channels=[],
                 id=None,
                 name=None,
                 acquisition_date="",
                 georef_filename="",
                 workspace=[],
                 metadata={},
                 annotations={},
                 working_area=[]):

        #we have to select a standanrd enforced!
        #in image standard (x, y, width height)
        #in numpy standard (y, x, height, width) #no the mixed format we use now I REFUSE to use it.
        #in range np format: (top, left, bottom, right)
        #in GIS standard (bottom, left, top, right)
        self.rect = rect  #coordinates of the image. (in the spatial reference system)
        self.map_px_to_mm_factor = map_px_to_mm_factor  #if we have a references system we should be able to recover this numner
        # otherwise we need to specify it.
        self.width = width
        self.height = height  #in pixels!

        self.annotations = Annotation()
        for data in annotations:
            blob = Blob(None, 0, 0, 0)
            blob.fromDict(data)
            self.annotations.addBlob(blob)

        self.channels = list(map(lambda c: Channel(**c), channels))

        self.id = id  # internal id used in correspondences it will never changes
        self.name = name  # a label for an annotated image
        self.workspace = workspace  # a polygon in spatial reference system
        self.working_area = working_area  # this is the working area of data exports for training
        self.acquisition_date = acquisition_date  # acquisition date is mandatory (format YYYY-MM-DD)
        self.georef_filename = georef_filename  # image file (GeoTiff) contained the georeferencing information
        self.metadata = metadata  # this follows image_metadata_template, do we want to allow freedom to add custome values?
Esempio n. 10
0
def loadOldProject(data, labels_dict):

    project = Project()
    project.importLabelsFromConfiguration(labels_dict)
    map_filename = data["Map File"]

    #convert to relative paths in case:
    dir = QDir(os.getcwd())
    map_filename = dir.relativeFilePath(map_filename)
    image_name = os.path.basename(map_filename)
    image_name = image_name[:-4]
    image = Image(id=image_name)
    image.map_px_to_mm_factor = data["Map Scale"]
    image.acquisition_date = "1955-11-05"
    channel = Channel(filename=map_filename, type="RGB")
    image.channels.append(channel)

    for blob_data in data["Segmentation Data"]:
        blob = Blob(None, 0, 0, 0)
        blob.fromDict(blob_data)
        blob.setId(int(
            blob.id))  # id should be set again to update related info
        image.annotations.addBlob(blob)

    project.images.append(image)
    return project
Esempio n. 11
0
    def createCrack(self, blob, input_arr, x, y, tolerance, preview=True):
        """
        Given a inner blob point (x,y), the function use it as a seed for a paint butcket tool and create
        a correspondent blob hole
        """

        box = blob.bbox
        x_crop = x - box[1]
        y_crop = y - box[0]

        input_arr = gaussian(input_arr, 2)
        # input_arr = segmentation.inverse_gaussian_gradient(input_arr, alpha=1, sigma=1)

        blob_mask = blob.getMask()

        crack_mask = flood(input_arr, (int(y_crop), int(x_crop)),
                           tolerance=tolerance).astype(int)
        cracked_blob = np.logical_and((blob_mask > 0), (crack_mask < 1))
        cracked_blob = cracked_blob.astype(int)

        if preview:
            return cracked_blob

        regions = measure.regionprops(measure.label(cracked_blob))

        area_th = 1000
        created_blobs = []

        for region in regions:
            if region.area > area_th:
                id = len(self.seg_blobs)
                b = Blob(region, box[1], box[0], self.progressive_id)
                self.progressive_id += 1
                b.class_color = blob.class_color
                b.class_name = blob.class_name
                created_blobs.append(b)

        return created_blobs
Esempio n. 12
0
    def cut(self, blob, lines):
        """
        Given a curve specified as a set of points and a selected blob, the operation cuts it in several separed new blobs
        """
        points = blob.lineToPoints(lines)

        mask = blob.getMask()
        box = blob.bbox
        Mask.paintPoints(mask, box, points, 0)

        label_image = measure.label(mask)
        area_th = 30
        created_blobs = []
        for region in measure.regionprops(label_image):

            if region.area > area_th:
                id = len(self.seg_blobs)
                b = Blob(region, box[1], box[0], id + 1)
                b.class_color = blob.class_color
                b.class_name = blob.class_name
                created_blobs.append(b)

        return created_blobs
Esempio n. 13
0
    def splitBlob(self, map, blob, seeds):

        seeds = np.asarray(seeds)
        seeds = seeds.astype(int)
        mask = blob.getMask()
        box = blob.bbox
        cropimg = utils.cropQImage(map, box)
        cropimgnp = rgb2gray(utils.qimageToNumpyArray(cropimg))

        edges = sobel(cropimgnp)

        # x,y
        seeds_matrix = np.zeros_like(mask)

        size = 40
        #
        for i in range(0, seeds.shape[0]):
            #y,x
            seeds_matrix[seeds[i, 1] - box[0] - (size - 1):seeds[i, 1] -
                         box[0] + (size - 1), seeds[i, 0] - box[1] -
                         (size - 1):seeds[i, 0] - box[1] + (size - 1)] = 1

        distance = ndi.distance_transform_edt(mask)
        # distance = ndi.distance_transform_edt(cropimg)
        seeds_matrix = seeds_matrix > 0.5
        markers = ndi.label(seeds_matrix)[0]
        # labels = watershed(-distance, markers, mask=mask)
        labels = watershed((-distance + 100 * edges) / 2, markers, mask=mask)
        created_blobs = []
        for region in measure.regionprops(labels):
            b = Blob(region, box[1], box[0], self.progressive_id)
            self.progressive_id += 1
            b.class_color = blob.class_color
            b.class_name = blob.class_name
            created_blobs.append(b)

        return created_blobs
Esempio n. 14
0
    def blobsFromMask(self, seg_mask, map_pos_x, map_pos_y, area_mask):
        # create the blobs from the segmentation mask

        last_blobs_added = []

        seg_mask = ndi.binary_fill_holes(seg_mask).astype(int)
        label_image = measure.label(seg_mask)

        area_th = area_mask * 0.2

        for region in measure.regionprops(label_image):

            if region.area > area_th:

                blob = Blob(region, map_pos_x, map_pos_y, self.getFreeId())

                last_blobs_added.append(blob)

        return last_blobs_added
Esempio n. 15
0
    def segmentation(self):

        # compute bbox of scribbles (working area)
        bboxes = []
        for i, curve in enumerate(self.scribbles.points):
            bbox = Mask.pointsBox(curve, int(self.scribbles.size[i] / 2))
            bboxes.append(bbox)
        working_area = Mask.jointBox(bboxes)

        if working_area[0] < 0:
            working_area[0] = 0

        if working_area[1] < 0:
            working_area[1] = 0

        if working_area[0] + working_area[3] > self.viewerplus.img_map.height(
        ) - 1:
            working_area[3] = self.viewerplus.img_map.height(
            ) - 1 - working_area[0]

        if working_area[1] + working_area[2] > self.viewerplus.img_map.width(
        ) - 1:
            working_area[2] = self.viewerplus.img_map.width(
            ) - 1 - working_area[1]

        crop_img = utils.cropQImage(self.viewerplus.img_map, working_area)
        crop_imgnp = utils.qimageToNumpyArray(crop_img)

        # create markers
        mask = np.zeros((working_area[3], working_area[2], 3), dtype=np.int32)

        color_codes = dict()
        counter = 1
        for i, curve in enumerate(self.scribbles.points):

            col = self.scribbles.label[i].fill
            b = col[2]
            g = col[1]
            r = col[0]
            color = (b, g, r)

            color_code = b + 256 * g + 65536 * r
            color_key = str(color_code)
            if color_codes.get(color_key) is None:
                name = self.scribbles.label[i].name
                color_codes[color_key] = (counter, name)
                counter = counter + 1

            curve = np.int32(curve)

            curve[:, 0] = curve[:, 0] - working_area[1]
            curve[:, 1] = curve[:, 1] - working_area[0]

            curve = curve.reshape((-1, 1, 2))
            mask = cv2.polylines(mask,
                                 pts=[curve],
                                 isClosed=False,
                                 color=color,
                                 thickness=self.scribbles.size[i],
                                 lineType=cv2.LINE_8)

        mask = np.uint8(mask)

        markers = np.zeros((working_area[3], working_area[2]), dtype='int32')
        for label in self.scribbles.label:
            col = label.fill
            b = col[2]
            g = col[1]
            r = col[0]
            color_code = b + 256 * g + 65536 * r
            color_key = str(color_code)

            idx = np.where((mask[:, :, 0] == b) & (mask[:, :, 1] == g)
                           & (mask[:, :, 2] == r))
            (value, name) = color_codes[color_key]
            markers[idx] = value

        # markers = np.int32(255*rgb2gray(mask))
        # markersprint = 255*rgb2gray(mask)
        markersprint = markers
        cv2.imwrite('mask.png', markersprint)

        # watershed segmentation
        segmentation = cv2.watershed(crop_imgnp, markers)
        segmentation = filters.median(segmentation, disk(5), mode="mirror")
        cv2.imwrite('segmentation.png', segmentation)

        # the result of the segmentation must be converted into labels again
        lbls = measure.label(segmentation)

        blobs = []
        for region in measure.regionprops(lbls):
            blob = Blob(region, working_area[1], working_area[0],
                        self.viewerplus.annotations.getFreeId())
            color_index = segmentation[region.coords[0][0],
                                       region.coords[0][1]]
            data = list(color_codes.items())
            index = 0
            for i in range(len(data)):
                (color_code, t) = data[i]
                if t[0] == color_index:
                    color_code = int(color_code)
                    r = int(color_code / 65536)
                    g = int(int(color_code - r * 65536) / 256)
                    b = int(color_code - r * 65536 - g * 256)
                    color = [r, g, b]
                    name = t[1]
                    break

            blob.class_color = color
            blob.class_name = name

            blobs.append(blob)

        return blobs