예제 #1
0
파일: geoutil.py 프로젝트: QhelDIV/xgutils
def morph_voxelization(vert,
                       face,
                       sampleN=1000000,
                       grid_dim=128,
                       selem_size=6):
    """ Morphological voxelization. Given arbitrary triangle soup, return the watertight voxelization of it.
        First sample cloud from mesh, voxelize the cloud, dilate, floodfill, erose. Note that dilate+erose=closing
    """
    vmin, vmax = np.abs(vert).min(), np.abs(vert).max()
    if vmax > 1.:
        print(
            f"Warning: Mesh should be fallen into [-1,1]^3 bounding box! vmin:{vmin} vmax:{vmax}"
        )
    samples = sampleMesh(vert, face, sampleN)
    voxel, coords = ptutil.ths2nps(
        ptutil.point2voxel(samples[None, ...],
                           grid_dim=grid_dim,
                           ret_coords=True))
    voxel, coords = voxel[0], coords[0]
    if selem_size == 0:
        water_tight_voxel = 1 - morphology.flood(voxel, (0, 0, 0))
    else:
        selem = morphology.ball(selem_size)
        dilated = morphology.binary_dilation(voxel, selem)
        mask = 1 - morphology.flood(dilated, (0, 0, 0))
        erosed = morphology.binary_erosion(mask, selem)
        water_tight_voxel = erosed
    return water_tight_voxel, coords
예제 #2
0
def test_empty_input():
    # Test shortcut
    output = flood_fill(np.empty(0), (), 2)
    assert output.size == 0

    # Boolean output type
    assert flood(np.empty(0), ()).dtype == np.bool

    # Maintain shape, even with zero size present
    assert flood(np.empty((20, 0, 4)), ()).shape == (20, 0, 4)
예제 #3
0
def test_empty_input():
    # Test shortcut
    output = flood_fill(np.empty(0), (), 2)
    assert output.size == 0

    # Boolean output type
    assert flood(np.empty(0), ()).dtype == np.bool

    # Maintain shape, even with zero size present
    assert flood(np.empty((20, 0, 4)), ()).shape == (20, 0, 4)
def fill(im_sd, t=0.05):
    from skimage.morphology import flood
    im_sd[0, 0] = 0
    im_sd[0, -1] = 0
    im_sd[-1, 0] = 0
    im_sd[-1, -1] = 0
    mask = flood(im_sd, (0, 0), tolerance=t) | \
           flood(im_sd, (im_sd.shape[0] - 1, 0), tolerance=t) | \
           flood(im_sd, (0, im_sd.shape[1] - 1), tolerance=t) | \
           flood(im_sd, (im_sd.shape[0] - 1, im_sd.shape[1] - 1), tolerance=t)
    return mask
예제 #5
0
def apply_flood_fill(image, starting_coordinates, tolerance):
    upper_bound = np.max(image)
    img_as_float = image / upper_bound
    mask = flood(img_as_float, starting_coordinates, tolerance=tolerance)
    mask = mask.astype('uint16')

    return mask
예제 #6
0
def global_both_line(img, r, c, color):
    img = img.reshape((img.shape + (1, ))[:3])
    msk = np.ones(img.shape[:2], dtype=np.bool)
    for i in range(img.shape[2]):
        msk &= flood(img[:, :, i], (r, c), connectivity=2)
    dilation = binary_dilation(msk, np.ones((3, 3)))
    dilation ^= msk
    img[dilation] = color
예제 #7
0
def global_in_fill(img, r, c, color):
    img = img.reshape((img.shape + (1, ))[:3])
    msk = np.ones(img.shape[:2], dtype=np.bool)
    for i in range(img.shape[2]):
        msk &= flood(img[:, :, i], (r, c), connectivity=2)
    filled = binary_fill_holes(msk)
    filled ^= msk
    img[filled] = color
예제 #8
0
def test_f_order(tolerance):
    image = np.array([
        [0, 0, 0, 0],
        [1, 0, 0, 0],
        [0, 1, 0, 0],
    ], order="F")
    expected = np.array([
        [0, 0, 0, 0],
        [1, 0, 0, 0],
        [0, 1, 0, 0],
    ], dtype=bool)

    mask = flood(image, seed_point=(1, 0), tolerance=tolerance)
    np.testing.assert_array_equal(expected, mask)

    mask = flood(image, seed_point=(2, 1), tolerance=tolerance)
    np.testing.assert_array_equal(expected, mask)
예제 #9
0
def global_in_line(img, r, c, color):
    img = img.reshape((img.shape + (1, ))[:3])
    msk = np.ones(img.shape[:2], dtype=np.bool)
    for i in range(img.shape[2]):
        msk &= flood(img[:, :, i], (r, c), connectivity=2)
    inarea = binary_fill_holes(msk)
    inarea ^= msk
    inarea ^= binary_erosion(inarea, np.ones((3, 3)))
    img[inarea] = color
예제 #10
0
 def mouse_down(self, ips, x, y, btn, **key):
     ips.snapshot()
     img, color = ips.img, ColorManager.get_front()
     connectivity=(self.para['con']=='8-connect')+1
     img = ips.img.reshape((ips.img.shape+(1,))[:3])
     msk = np.ones(img.shape[:2], dtype=np.bool)
     for i in range(img.shape[2]):
         msk &= flood(img[:,:,i], (int(y),int(x)), 
             connectivity=connectivity, tolerance=self.para['tor'])
     img[msk] = np.mean(color) if img.shape[2]==1 else color
     ips.update()
예제 #11
0
    def mouse_down(self, ips, x, y, btn, **key): 
        lim = 5.0/key['canvas'].get_scale() 
        if btn==1 or btn==3:
            if ips.roi!= None:
                self.curobj = ips.roi.pick(x, y, ips.cur, lim)
                ips.roi.info(ips, self.curobj)
            if not self.curobj in (None,True):return
            if ips.roi == None:
                connectivity=(self.para['con']=='8-connect')+1
                img = ips.img.reshape((ips.img.shape+(1,))[:3])
                msk = np.ones(img.shape[:2], dtype=np.bool)
                for i in range(img.shape[2]):
                    msk &= flood(img[:,:,i], (int(y),int(x)), 
                        connectivity=connectivity, tolerance=self.para['tor'])
                conts = find_contours(msk, 0, 'high')
                ips.roi = shape2roi(polygonize(conts, btn==3))
            elif hasattr(ips.roi, 'topolygon'):
                shp = roi2shape(ips.roi.topolygon())
                oper = ''
                if key['shift']: oper = '+'
                elif key['ctrl']: oper = '-'
                elif self.curobj: return
                else: ips.roi=None

                connectivity=(self.para['con']=='8-connect')+1
                img = ips.img.reshape((ips.img.shape+(1,))[:3])
                msk = np.ones(img.shape[:2], dtype=np.bool)
                for i in range(img.shape[2]):
                    msk &= flood(img[:,:,i], (int(y),int(x)), 
                        connectivity=connectivity, tolerance=self.para['tor'])
                conts = find_contours(msk, 0, 'high')
                cur = polygonize(conts, btn==3)
                if oper == '+':
                    ips.roi = shape2roi(shp.union(cur))
                elif oper == '-':
                    ips.roi = shape2roi(shp.difference(cur))
                else: ips.roi = shape2roi(cur)

            else: ips.roi = None

        ips.update()
예제 #12
0
def global_out_fill(img, r, c, color):
    img = img.reshape((img.shape + (1, ))[:3])
    ori = np.ones(img.shape[:2], dtype=np.bool)
    for i in range(img.shape[2]):
        ori &= flood(img[:, :, i], (r, c), connectivity=2)
    filled = binary_fill_holes(ori)
    dilation = binary_dilation(ori)
    dilation ^= filled
    rs, cs = np.where(dilation)
    if len(rs) == 0: return
    msk = ((img == img[r, c]).min(axis=2)).astype(np.uint8)
    flood_fill(msk, (rs[0], cs[0]), 2, connectivity=2, inplace=True)
    img[msk == 2] = color
예제 #13
0
    def action_trim_pixels(self, label, frame, x_location, y_location):
        '''
        get rid of any stray pixels of selected label; pixels of value label
        that are not connected to the cell selected will be removed from annotation in that frame
        '''

        img_ann = self.tracked[frame,:,:,0]
        contig_cell = flood(image = img_ann, seed_point = (int(y_location/self.scale_factor), int(x_location/self.scale_factor)))
        img_trimmed = np.where(np.logical_and(np.invert(contig_cell), img_ann == label), 0, img_ann)

        comparison = np.where(img_trimmed != img_ann)
        self.frames_changed = np.any(comparison)

        self.tracked[frame,:,:,0] = img_trimmed
예제 #14
0
def region_growing(img, seed_point, tolerance=20):
    """
    Args:
        img (ndarray): image
        seed_point (tuple): define the seed point.
        tolerance: a float or int value to define the maximal difference of grayvalues in the region. According to the
                   documentation in scikit-image, if tolerance is provided, adjacent points with values within plus 
                   or minus tolerance from the seed point are filled (inclusive).

    Returns:
        mask (ndarray): output binary image
    """
    mask = flood(img, seed_point, tolerance=tolerance)
    mask = binary_dilation(mask, np.ones((3, 3)))

    return mask
예제 #15
0
    def mouse_move(self, ips, x, y, btn, **key):
        if self.status == None: return
        img, color = ips.img, (255, 255, 0)
        rs, cs = line(*[int(round(i)) for i in self.oldp + (y, x)])
        np.clip(rs, 0, img.shape[0] - 1, out=rs)
        np.clip(cs, 0, img.shape[1] - 1, out=cs)
        color = (np.mean(color), color)[img.ndim == 3]
        w = self.para['win']

        for r, c in zip(rs, cs):
            sr = (max(0, r - w), min(img.shape[0], r + w))
            sc = (max(0, c - w), min(img.shape[1], c + w))
            r, c = min(r, w), min(c, w)
            clip = img[slice(*sr), slice(*sc)]
            if (clip[r, c] - color).sum() == 0: continue
            lab = felzenszwalb(clip, 1, 0, self.para['ms'])
            clip[flood(lab, (r, c), connectivity=2)] = color

        self.oldp = (y, x)
        ips.update()
예제 #16
0
def get_houses(target_image: np.array) -> list:
    """Cut out houses from target data
        Parameters:
        target_image: np.array
            2 D Matrix with target values with values either 0 or 1

        Returns:
        coordiantes_list: list
            Each element represents a bounding box around a house
            (xmin, ymin, xmax, ymax)
    """
    # Clip target_image to values 0, 1
    target_image = np.clip(target_image, a_min=0, a_max=1)

    coordinates_list = []

    # Starting from the top left, search the image for a house
    for i in range(0, len(target_image)):
        for j in range(0, len(target_image[0])):
            if target_image[i][j] == 1:
                # Flood and overlay selected house
                seed_point = (i, j)
                mask = flood(target_image, seed_point)
                mask_int = mask.astype(int)

                # Find X,Y coordinates of all pixels with value 1
                coordinates = np.argwhere(mask_int == 1)
                # print('Number of Pixels: ', len(coordinates))

                # Find min and max values for x and y
                y_min, x_min = np.min(coordinates, axis=0)
                y_max, x_max = np.max(coordinates, axis=0)

                # Remove flood filled building from original image
                target_image[mask] = 0

                # Only select larger houses
                if len(coordinates) > 50:
                    coordinates_list.append([(x_min, y_min), (x_max, y_max)])

    return coordinates_list
예제 #17
0
    def mouse_down(self, ips, x, y, btn, **key):
        if btn != 1: return
        msk = flood(ips.img, (int(y), int(x)), connectivity=0, tolerance=0)
        conts = find_contours(msk, 0.5, 'high')
        conts = conts[0][:, ::-1]
        ips.mark = Mark(conts)

        trans = ips.img.mat
        jw = np.dot(trans[:, 1:], conts.T).T + trans[:, 0]

        osrprj = osr.SpatialReference()
        osrprj.ImportFromWkt(ips.img.crs)
        osrgeo = osr.SpatialReference()
        osrgeo.ImportFromEPSG(3857)
        ct = osr.CoordinateTransformation(osrprj, osrgeo)

        xy = ct.TransformPoints(jw)
        polygon = Polygon(xy)
        c = polygon.centroid
        IPy.set_info('At N:%.4f, E:%.4f  Area:%.4f' % (c.x, c.y, polygon.area))
        ips.update()
예제 #18
0
    def action_trim_pixels(self, label, x_location, y_location):
        """
        Remove any pixels with value label that are not connected to the
        selected cell in the given frame.

        Args:
            label (int): label to trim
            x_location (int): x position of seed
                              remove label that is not connect to this seed
            y_location (int): y position of seed
        """
        img_ann = self.frame[..., self.feature]

        seed_point = (int(y_location), int(x_location))
        contig_cell = flood(image=img_ann, seed_point=seed_point)
        stray_pixels = np.logical_and(np.invert(contig_cell), img_ann == label)
        img_trimmed = np.where(stray_pixels, 0, img_ann)

        self.y_changed = np.any(np.where(img_trimmed != img_ann))

        self.frame[..., self.feature] = img_trimmed
예제 #19
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
예제 #20
0
파일: Blob.py 프로젝트: whuchenlin/TagLab
    def createCrack(self, 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
        """

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

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

        blob_mask = self.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 not preview:
            self.updateUsingMask(self.bbox, cracked_blob)

        return cracked_blob
예제 #21
0
def local_brush(img, back, r, c, color, sigma, msize):
    lab = felzenszwalb(back, 1, sigma, msize)
    msk = flood(lab, (r, c), connectivity=2)
    img[msk] = color
예제 #22
0
from functions import *
from skimage.morphology import flood
from matplotlib import pyplot as plt
from scipy import ndimage
allpost, allpre, basenames = load("DATA")

for image, name in zip(allpre, basenames):
    # load ground truth
    ground_truth = gt(name)

    x, y = ground_truth[0][1:3]
    mask = flood(image, (y, x), connectivity=5, tolerance=5)
    for n, x, y in ground_truth[1:]:
        mask_temp = flood(image, (y, x), connectivity=5, tolerance=5)
        mask = np.logical_or(mask_temp, mask)

    fig, ax = plt.subplots(1, 1, figsize=(9, 3), sharex=True, sharey=True)
    title = 'Laplacian of Gaussian'
    ax.set_title(title)
    ax.imshow(mask)
    for n, x, y in ground_truth:
        c = plt.Circle((x, y), 20, color='red', linewidth=2, fill=False)
        ax.add_patch(c)

    plt.show()
예제 #23
0
 if resize:
     iris_prediction = cv2.resize(
         iris_prediction, (original_shape[1], original_shape[0]),
         interpolation=cv2.INTER_LINEAR)
 else:
     iris_prediction = iris_prediction[pads[0]:pads[0] +
                                       transformed_shape[0],
                                       pads[1]:pads[1] +
                                       transformed_shape[1]]
     iris_prediction = cv2.resize(
         iris_prediction, (original_shape[1], original_shape[0]),
         interpolation=cv2.INTER_LINEAR)
 _, iris_prediction = cv2.threshold(iris_prediction, 0.5, 1, 0)
 iris_prediction = keep_large_area(iris_prediction,
                                   top_n_large=1).astype(np.uint8)
 outer_prediction = (1 - flood(iris_prediction,
                               (0, 0))).astype(np.uint8)
 inner_prediction = (outer_prediction - iris_prediction).astype(
     np.uint8)
 if args.ellipse:
     inner_prediction = fit_Ellipse(inner_prediction).astype(np.uint8)
     outer_prediction = fit_Ellipse(outer_prediction).astype(np.uint8)
 Dice = compute_dice(outer_prediction - inner_prediction,
                     local_outer - local_inner)
 HD = hd(outer_prediction - inner_prediction, local_outer - local_inner)
 print(i, img_name, Dice, HD)
 name_all.append(path)
 Dice_all.append(Dice)
 HD_all.append(HD)
 inner_save = np.zeros(inner_prediction.shape)
 contours, _ = cv2.findContours(inner_prediction, cv2.RETR_TREE,
                                cv2.CHAIN_APPROX_NONE)
예제 #24
0
def fill_normal(img, r, c, color, con, tor):
    img = img.reshape((img.shape + (1, ))[:3])
    msk = np.ones(img.shape[:2], dtype=np.bool)
    for i in range(img.shape[2]):
        msk &= flood(img[:, :, i], (r, c), connectivity=con, tolerance=tor)
    img[msk] = color
예제 #25
0
    def action_active_contour(self, label, min_pixels=20, iterations=100):
        label_img = np.copy(self.frame[..., self.feature])

        # get centroid of selected label
        props = regionprops(np.where(label_img == label, label, 0))[0]

        # make bounding box size to encompass some background
        box_height = props['bbox'][2] - props['bbox'][0]
        y1 = max(0, props['bbox'][0] - box_height // 2)
        y2 = min(self.project.height, props['bbox'][2] + box_height // 2)

        box_width = props['bbox'][3] - props['bbox'][1]
        x1 = max(0, props['bbox'][1] - box_width // 2)
        x2 = min(self.project.width, props['bbox'][3] + box_width // 2)

        # relevant region of label image to work on
        label_img = label_img[y1:y2, x1:x2]

        # use existing label as initial level set for contour calculations
        level_set = np.where(label_img == label, 1, 0)

        # normalize input 2D frame data values to range [0.0, 1.0]
        adjusted_raw_frame = Normalize()(self.raw_frame[..., self.channel])
        predict_area = adjusted_raw_frame[y1:y2, x1:x2]

        # returns 1 where label is predicted to be based on contouring, 0 background
        contoured = morphological_chan_vese(
            predict_area, iterations, init_level_set=level_set
        )

        # contoured area should get original label value
        contoured_label = contoured * label
        # contours tend to fit very tightly, a small expansion here works well
        contoured_label = dilation(contoured_label, disk(3))

        # don't want to leave the original (un-contoured) label in the image
        # never overwrite other labels with new contoured label
        cond = np.logical_or(label_img == label, label_img == 0)
        safe_overlay = np.where(cond, contoured_label, label_img)

        # label must be present in safe_overlay for this to be a valid contour result
        # very few pixels of contoured label indicate contour prediction not worth keeping
        pixel_count = np.count_nonzero(safe_overlay == label)
        if pixel_count < min_pixels:
            safe_overlay = np.copy(self.frame[y1:y2, x1:x2, self.feature])

        # put it back in the full image so can use centroid coords for post-contour cleanup
        full_frame = np.copy(self.frame[..., self.feature])
        full_frame[y1:y2, x1:x2] = safe_overlay

        # avoid automated label cleanup if centroid (flood seed point) is not the right label
        if full_frame[int(props['centroid'][0]), int(props['centroid'][1])] != label:
            img_trimmed = full_frame
        else:
            # morphology and logic used by pixel-trimming action, with object centroid as seed
            contig_cell = flood(
                image=full_frame,
                seed_point=(int(props['centroid'][0]), int(props['centroid'][1])),
            )

            # any pixels in img_ann that have value 'label' and are NOT connected to
            # hole_fill_seed get changed to 0, all other pixels retain their original value
            img_trimmed = np.where(
                np.logical_and(np.invert(contig_cell), full_frame == label),
                0,
                full_frame,
            )

        # update image; cell_info should never change as a result of this
        self.frame[y1:y2, x1:x2, self.feature] = img_trimmed[y1:y2, x1:x2]
        self.y_changed = True