Ejemplo n.º 1
0
def watershed_demo(image):
    blurred = cv.pyrMeanShiftFiltering(image, 10, 100)
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow("binary", binary)

    kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
    mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)
    sure_bg = cv.dilate(binary, kernel, iterations=3)
    cv.imshow("mor", sure_bg)

    dist = cv.distanceTransform(mb, cv.DIST_L2, 3)
    dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)
    cv.imshow("dist", dist_output * 50)

    ret, surface = cv.threshold(dist, dist.max() * 0.6, 255, cv.THRESH_BINARY)
    cv.imshow("interface", surface)

    surface_fg = np.uint8(surface)
    unknow = cv.subtract(sure_bg, surface_fg)
    ret, markers = cv.connectedComponents(surface_fg)
    print(ret)

    markers += 1
    markers[unknow == 255] = 0
    markers = cv.watershed(image, markers=markers)
    image[markers == -1] = [0, 0, 255]
    cv.imshow("result", image)
Ejemplo n.º 2
0
def s2(img):  #segmentacionWarershed
    img = img
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 0, 255,
                                cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    # Eliminación del ruido
    kernel = np.ones((3, 3), np.uint8)
    opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
    # Encuentra el área del fondo
    sure_bg = cv2.dilate(opening, kernel, iterations=3)
    # Encuentra el área del primer
    dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
    ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(),
                                 255, 0)
    # Encuentra la región desconocida (bordes)
    sure_fg = np.uint8(sure_fg)
    unknown = cv2.subtract(sure_bg, sure_fg)
    # Etiquetado
    ret, markers = cv2.connectedComponents(sure_fg)
    # Adiciona 1 a todas las etiquetas para asegurra que el fondo sea 1 en lugar de cero
    markers = markers + 1
    # Ahora se marca la región desconocida con ceros
    markers[unknown == 255] = 0
    markers = cv2.watershed(img, markers)
    img[markers == -1] = [255, 0, 0]
    return img
def _evaluate_pose(dist, frame, msp, mtx, rotation_vec, translation_vec):
    image_edges = _extract_edges_image(_convert_grayscale(frame))
    model_plot = np.zeros_like(image_edges)
    utils.plot_dxf_model(
        msp,
        model_plot,
        dist,
        mtx,
        rotation_vec,
        translation_vec,
        colour=(255, ),
        thickness=1,
    )
    distance_transform = cv2.distanceTransform(src=~image_edges,
                                               distanceType=cv2.DIST_L2,
                                               maskSize=3)
    distance_transform = _normalise_img(distance_transform)
    model_plot = _normalise_img(model_plot)
    # The distance transform says 'how far is this pixel from an edge', and we want small
    # distances for the model plot pixels, so we need (1 - distance_transform)
    # We multiply the matrices element-wise, so we only add the distance_loss for the
    # model edge pixels. And we divide by the number of edge pixels, to get a mean.
    edge_to_plot_distance_loss = (model_plot *
                                  distance_transform).sum() / model_plot.sum()
    return edge_to_plot_distance_loss, distance_transform, model_plot, image_edges
Ejemplo n.º 4
0
def update_image(gray: np.ndarray, dist: np.ndarray, coords: Tuple[int, int],
                 radius: int) -> None:
    """
    Delete a circle from gray and updates the dist array accordingly. gray and dist will be modified inplace.

    :param gray: ndarray containing the binary image
    :param dist: ndarray containing the result of the distance transformation on gray
    :param coords: coordinates of the center of the circle that will be removed from gray
    :param radius: radius of that circle
    :return: None
    """
    x, y = (int(z) for z in coords)
    r = int(radius)

    x_low = max(0, x - 4 * r)
    x_high = min(dist.shape[0], x + 4 * r)
    y_low = max(0, y - 4 * r)
    y_high = min(dist.shape[1], y + 4 * r)

    slice_segment = (slice(x_low, x_high), slice(y_low, y_high))

    cv2.circle(gray, (y, x), r, 0, -1)
    sub_gray = gray[slice_segment].copy()

    sub_dist_old = dist[slice_segment]
    sub_dist_new = cv2.distanceTransform(sub_gray, cv2.DIST_L2,
                                         cv2.DIST_MASK_PRECISE)

    dist[slice_segment] = np.minimum(sub_dist_new, sub_dist_old)
Ejemplo n.º 5
0
def distance_transform_weight(x):
    if x.max() == 0:
        return np.ones(x.shape) * 2
    else:
        smooth = 0.0000001
        x = 1 - x
        xD = x * 255
        xD = xD.astype(np.uint8)
        dt = cv2.distanceTransform(xD, cv2.DIST_L2, 3)
        dt = (dt / 255)
        dt = dt**2
        dt = (dt + smooth / dt.max() + smooth)
        dt[x.astype(np.int)] = 0
        return dt
Ejemplo n.º 6
0
    def watershed(self, _img=None):
        # # 灰度和二值转换
        _img = self.img if _img is None else _img
        _gray = cv2.cvtColor(_img, cv2.COLOR_BGR2GRAY)
        _, _binary = cv2.threshold(_gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
        # # 形态学操作
        # # # 形态学操作卷积核
        _kernel = np.ones((3, 3), np.uint8)
        # # # 开运算去噪(去掉椒盐噪声的影响)
        _opening = cv2.morphologyEx(_binary, cv2.MORPH_OPEN, _kernel, iterations=2)
        # # # 如果能画出背景和前景, 分割算法会很好
        # # # 考虑到数据量的原因, 使用程序 机械的找出
        # # # 找出一定是背景的部分 膨胀操作: 扩大图形区的面积
        _sure_bg = cv2.dilate(_opening, _kernel, iterations=3)
        # cv_show(_sure_bg)
        # # 距离变换函数: 对原始图像进行计算 之后二值处理, 获取前景
        # # 该函数的第一个参数只能是单通道的二值的图像, 第二个参数是距离方法
        # # 计算图像上255点与最近的0点之间的距离 DIST_L2应是欧氏距离, 会输出小数
        # # DIST_L1应是哈密顿距离, 不会有小数
        _dist_transform = cv2.distanceTransform(_opening, cv2.DIST_L1, 5)
        # cv_show(_dist_transform)
        # # 距离变换之后做一二值变换, 得到大概率是图像前景的点
        _, _sure_fg = cv2.threshold(_dist_transform, 0.5 * _dist_transform.max(), 255, cv2.THRESH_BINARY)
        # # 转换类型, 否则会很危险
        _sure_fg = np.uint8(_sure_fg)
        # cv_show(_sure_fg)
        # # 绘制unknown区 交给算法, 自下而上的洪泛算法
        _unknown = cv2.subtract(_sure_bg, _sure_fg)
        # cv_show(_unknown)
        _, _markers = cv2.connectedComponents(_sure_fg)
        _markers = _markers + 1
        _markers[_unknown == 255] = 0
        _img1 = _img.copy()
        _markers = cv2.watershed(_img1, _markers)

        # # 圈出来 之后可以根据结果将一部分的值变为黑色
        def random_color(a: int):
            return np.random.randint(0, 255, (a, 3))

        _markers_label = np.unique(_markers)
        _colors = random_color(_markers_label.size)
        for _mark, _color in zip(_markers_label, _colors):
            _img1[_markers == _mark] = _color
        # # 展示
        cv_show(_img1)
Ejemplo n.º 7
0
def watershedAlgorithm(image):

    img = cv.imread(image)
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    ret, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)

    # noise removal
    kernel = np.ones((5, 5), np.uint8)
    opening = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel, iterations=2)

    # sure background area
    sure_bg = cv.dilate(opening, kernel, iterations=3)

    # Finding sure foreground area
    dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5)
    ret, sure_fg = cv.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)

    # Finding unknown region
    sure_fg = np.uint8(sure_fg)
    unknown = cv.subtract(sure_bg, sure_fg)

    # Marker labelling
    ret, markers = cv.connectedComponents(sure_fg)

    # Add one to all labels so that sure background is not 0, but 1
    markers = markers + 1

    # Now, mark the region of unknown with zero
    markers[unknown == 255] = 0

    markers = cv.watershed(img, markers)
    img[markers == -1] = [255, 0, 0]



    return img
Ejemplo n.º 8
0
def watershed(img, img_gray):
#     mean = np.average(img_gray)
#     _, thresh1 = cv2.threshold(img_gray,mean,255,cv2.THRESH_BINARY_INV)
#     _, thresh2 = cv2.threshold(img_gray,200,255,cv2.THRESH_BINARY)
#     thresh = np.bitwise_or(thresh1, thresh2)
    _, thresh = cv2.threshold(img_gray,np.average(img_gray)-40,255,cv2.THRESH_BINARY_INV)

    kernel = np.ones((3,3),np.uint8)
    opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,iterations=2)

    sure_bg = cv2.dilate(opening,kernel,iterations=2)

    dist_transform = cv2.distanceTransform(sure_bg,cv2.DIST_L2,5)
    _, sure_fg = cv2.threshold(dist_transform,0.5*dist_transform.max(),255,0)
    sure_fg = np.uint8(sure_fg)

    unknown = cv2.subtract(sure_fg, sure_bg)

    ret, markers = cv2.connectedComponents(unknown)
    markers = markers + 1
    markers[unknown == 255] = 0

    markers = cv2.watershed(img,markers)
    return dist_transform
Ejemplo n.º 9
0
    # print('image suavizada', calc_min(histograma))
    cv2.waitKey(0)

if __name__ == '__main__':
    img = coin_c
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    cv2.imshow('Image1', thresh)

    kernel = np.ones((3, 3), np.uint8)
    opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
    sure_bg = cv2.dilate(opening, kernel, iterations=3)
    cv2.imshow('Image2 - sure_bg', sure_bg)
    # cv2.imshow('Image2 - opening', opening)

    dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
    ret, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
    cv2.imshow('Image3 - sure_fg', sure_fg)
    cv2.imshow('Image3 - dist_transform', dist_transform)

    sure_fg = np.uint8(sure_fg)
    unknown = cv2.subtract(sure_bg, sure_fg)
    cv2.imshow('Image4', unknown)

    ret, markers = cv2.connectedComponents(sure_fg)

    # markers = markers+1

    markers[unknown == 255] = 0
    markers[markers >= 1] = 255
    cv2.imshow('Image5', markers)
Ejemplo n.º 10
0
ret, thresh1 = cv2.threshold(gray, mean, 255, cv2.THRESH_BINARY_INV)
ret, thresh2 = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)
# thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,15,4)
thresh = np.bitwise_or(thresh1, thresh2)

#Morphology의 opening, closing을 통해서 노이즈나 Hole제거
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)

# dilate를 통해서 확실한 Backgroud
sure_bg = cv2.dilate(opening, kernel, iterations=2)

#distance transform을 적용하면 중심으로 부터 Skeleton Image를 얻을 수 있음.
# 즉, 중심으로 부터 점점 옅어져 가는 영상.
# 그 결과에 thresh를 이용하여 확실한 FG를 파악
dist_transform = cv2.distanceTransform(sure_bg, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.5 * dist_transform.max(), 255,
                             0)
sure_fg = np.uint8(sure_fg)

# Background에서 Foregrand를 제외한 영역을 Unknow영역으로 파악
unknown = cv2.subtract(sure_bg, sure_fg)
# unknown = sure_bg

# FG에 Labelling작업
ret, markers = cv2.connectedComponents(sure_fg)
markers = markers + 1
markers[unknown == 255] = 0

# watershed를 적용하고 경계 영역에 색지정
markers = cv2.watershed(img, markers)
Ejemplo n.º 11
0
def convert(files: List[pathlib.Path], min_radius: float, wiggle_radius: float,
            seeded_radius_factor: float) -> List[nx.Graph]:
    """
    Converts black&white pictures to graphs which nodes cover the foreground (white). The nodes are created in a way
    that there radii are decreasing until no node with a radius greater or equal to the min_radius is found.
    :param files: Paths to the images, will be converted in that order
    :param min_radius: minimum radius for nodes, lower values increase accuracy and runtime
    :param wiggle_radius: radius in which tracked nodes may move to maximize area
    :param seeded_radius_factor: allow the min radius of tracked nodes to be smaller by this factor
    :return: a list with graphs in the same order as the input
    """
    graphs = []
    seeds = set()

    for i, image_path in enumerate(files):
        logging.debug('processing graph {} ({:>4}/{:>4})'.format(
            image_path, i + 1, len(files)))
        graph = nx.Graph()
        graph.name = '{}_{:05}'.format(image_path.stem, i)
        graph.graph['graph_id'] = i
        graph.graph['converted_by'] = 'convert_bw.py'
        graph.graph['converted_date'] = datetime.now()
        graph.graph[
            'nodes_indexed_by'] = 2  # id of the first found node. 0 and 1 are reserved for background and (yet unlabeled foreground)
        graph.graph['min_radius'] = min_radius
        graph.graph['wiggle_radius'] = wiggle_radius
        graphs.append(graph)

        gray = cv2.imread(str(image_path), cv2.IMREAD_GRAYSCALE)
        gray = np.pad(
            gray, 1, mode='constant'
        )  # pad one pixel on each side with default constant being zero
        skeleton = gray.copy()
        thresh = sif.threshold_mean(skeleton)
        skeleton = sim.skeletonize(skeleton > thresh).astype(
            np.int16)  # to allow for more nodes, change to larger type
        # meaning of values in skeleton
        #  0 -> background
        #  1 -> skeleton without attached node
        # >1 -> skeleton pixel attached to node with corresponding id
        # <0 -> visited skeleton pixel attached to node with corresponding id (just negated)
        node_ids = itertools.count(2)

        dist = cv2.distanceTransform(gray, cv2.DIST_L2, cv2.DIST_MASK_PRECISE)
        fixed_seeds = frozenset(seeds)
        seeds.clear()
        for sx, sy, seed_id in sorted(fixed_seeds,
                                      key=lambda e: dist[e[0], e[1]],
                                      reverse=True):

            if wiggle_radius > 0.1:
                mask = circular_mask(sx, sy, wiggle_radius, gray.shape)
                masked_dist = np.ma.array(dist[mask.slice],
                                          mask=np.invert(mask.mask))
                max_coordinates = np.unravel_index(
                    masked_dist.argmax(fill_value=0.0), masked_dist.shape)
                (ax, ay) = mask.mind_offset(max_coordinates)
            else:
                (ax, ay) = (sx, sy)

            radius = dist[ax, ay]
            if radius < min_radius * seeded_radius_factor:
                continue

            mask = circular_mask(ax, ay, radius - 1, gray.shape)
            if skeleton[mask.slice][mask.mask].any():
                node_id = next(node_ids)
                graph.add_node(node_id,
                               x=int(ay) - 1,
                               y=int(ax) - 1,
                               r=float(radius),
                               convert_seed=seed_id)
                node_area = np.ma.masked_array(skeleton[mask.slice],
                                               mask=np.invert(mask.mask))
                node_area[node_area == 1] = node_id
                seeds.add((ax, ay, node_id))
                update_image(gray, dist, (ax, ay), dist[ax, ay])

        while True:
            argmax = np.unravel_index(dist.argmax(), dist.shape)

            if dist[argmax] < min_radius:
                break

            ndx = np.asscalar(argmax[0])
            ndy = np.asscalar(argmax[1])
            ndr = dist[
                argmax] - 1  # reducing the radius prevents pixels associated to multiple nodes
            mask = circular_mask(ndx, ndy, ndr, gray.shape)

            if skeleton[mask.slice][mask.mask].any():
                node_id = next(node_ids)
                graph.add_node(node_id,
                               x=int(ndy) - 1,
                               y=int(ndx) - 1,
                               r=int(dist[argmax]),
                               convert_seed=0)
                node_area = np.ma.masked_array(skeleton[mask.slice],
                                               mask=np.invert(mask.mask))
                node_area[node_area == 1] = node_id
                seeds.add((ndx, ndy, node_id))

            update_image(gray, dist, argmax, dist[argmax])

        logging.debug('{} node(s) found'.format(graph.number_of_nodes()))

        max_id = graph.number_of_nodes() + 2
        assert np.all(
            skeleton <= max_id
        ), 'maximal value in skeleton is {}, while max_id={}'.format(
            skeleton.max(), max_id)

        for node_id in graph.nodes(data=False):
            neighbors = explore_neighbors(node_id, skeleton)
            assert all(
                id > 1
                for id in neighbors), 'Found neighbor with id <= 1 {}'.format(
                    neighbors)
            graph.add_edges_from(
                (node_id, int(neighbor)) for neighbor in neighbors)

    return graphs