Python skimage.draw.line() Examples

The following are 23 code examples of skimage.draw.line(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module skimage.draw , or try the search function .
Example #1
Source File: dataset.py    From deep-high-resolution-net.TensorFlow with MIT License 6 votes vote down vote up
def draw_lines_on_img(img, point_ver, point_hor, point_class):
    line_list = [[0, 1], [1, 2], [3, 4], [4, 5], [6, 7], [7, 8], [9, 10],
               [10, 11], [12, 13], [13, 6], [13, 9], [13, 0], [13, 3]]

    # key point class: 1:visible, 2: not visible, 3: not marked
    for start_point_id in range(len(point_class)):
        if point_class[start_point_id] == 3:
            continue
        for end_point_id in range(len(point_class)):
            if point_class[end_point_id] == 3:
                continue

            if [start_point_id, end_point_id] in line_list:
                rr, cc = draw.line(int(point_ver[start_point_id]), int(point_hor[start_point_id]),
                                   int(point_ver[end_point_id]), int(point_hor[end_point_id]))
                draw.set_color(img, [rr, cc], [255, 0, 0])

    return img 
Example #2
Source File: segmentation.py    From kraken with Apache License 2.0 6 votes vote down vote up
def _find_superpixels(skeleton, heatmap, min_sp_dist):
    logger.debug('Finding superpixels')
    conf_map = heatmap * skeleton
    sp_idx = np.unravel_index(np.argsort(1.-conf_map, axis=None), conf_map.shape)
    if not sp_idx[0].any():
        logger.info('No superpixel candidates found for line vectorizer. Likely empty page.')
        return np.empty(0)
    zeroes_idx = conf_map[sp_idx].argmin()
    if not zeroes_idx:
        logger.info('No superpixel candidates found for line vectorizer. Likely empty page.')
        return np.empty(0)
    sp_idx = sp_idx[0][:zeroes_idx], sp_idx[1][:zeroes_idx]
    sp_can = [(sp_idx[0][0], sp_idx[1][0])]
    for x in range(len(sp_idx[0])):
        loc = np.array([[sp_idx[0][x], sp_idx[1][x]]])
        if min(cdist(sp_can, loc)) > min_sp_dist:
            sp_can.extend(loc.tolist())
    return np.array(sp_can) 
Example #3
Source File: LinearMotionBlur.py    From pyblur with MIT License 6 votes vote down vote up
def LineKernel(dim, angle, linetype):
    kernelwidth = dim
    kernelCenter = int(math.floor(dim/2))
    angle = SanitizeAngleValue(kernelCenter, angle)
    kernel = np.zeros((kernelwidth, kernelwidth), dtype=np.float32)
    lineAnchors = lineDict.lines[dim][angle]
    if(linetype == 'right'):
        lineAnchors[0] = kernelCenter
        lineAnchors[1] = kernelCenter
    if(linetype == 'left'):
        lineAnchors[2] = kernelCenter
        lineAnchors[3] = kernelCenter
    rr,cc = line(lineAnchors[0], lineAnchors[1], lineAnchors[2], lineAnchors[3])
    kernel[rr,cc]=1
    normalizationFactor = np.count_nonzero(kernel)
    kernel = kernel / normalizationFactor        
    return kernel 
Example #4
Source File: anno_helper.py    From lost with MIT License 5 votes vote down vote up
def to_abs(annos, types, img_size):
    '''Convert relative annotation coordinates to absolute ones
    
    Args:
        annos (list of list):
        types (list of str):
        img_size (tuple): (width, height) of the image in pixels.
    
    Returns:
        list of list: Annotations in absolute format.
    '''
    w, h = img_size
    new = []
    for twod, t in zip(annos,types):
        if t == 'bbox':
            new.append([
                twod[0]*w, twod[1]*h,
                twod[2]*w, twod[3]*h
            ])
        elif t == 'line' or t == 'polygon':
            lp = np.array(twod)
            lp[:,0] = lp[:,0]*w
            lp[:,1] = lp[:,1]*h
            new.append(lp.tolist())
        elif t=='point':
            new.append([twod[0]*w, twod[1]*h])
        else:
            raise Exception('Unknown annotation type: {}'.format(t))
    return np.array(new, dtype=int).tolist() 
Example #5
Source File: visualisation.py    From DeepVOG with GNU General Public License v3.0 5 votes vote down vote up
def draw_line(output_frame, frame_shape, o, l, color=[255, 0, 0]):
    """

    Parameters
    ----------
    output_frame : numpy.darray
        Video frame to draw the circle. The value of video frame should be of type int [0, 255]
    frame_shape : list or tuple or numpy.darray
        Shape of the frame. For example, (240, 320)
    o : list or tuple or numpy.darray
        Origin of the line, with shape (2,) denoting (x, y).
    l : list or tuple or numpy.darray
        Vector with length. Body of the line. Shape = (2, ), denoting (x, y)
    color : tuple or list or numpy.darray
        RBG colors, e.g. [255, 0, 0] (red color), values of type int [0, 255]

    Returns
    -------
    output frame : numpy.darray
        Frame with the ellipse drawn.
    """
    R, G, B = color
    rr, cc = line(int(np.round(o[0])), int(np.round(o[1])), int(np.round(o[0] + l[0])), int(np.round(o[1] + l[1])))
    rr[rr > int(frame_shape[1]) - 1] = frame_shape[1] - 1
    cc[cc > int(frame_shape[0]) - 1] = frame_shape[0] - 1
    rr[rr < 0] = 0
    cc[cc < 0] = 0
    output_frame[cc, rr, 0] = R
    output_frame[cc, rr, 1] = G
    output_frame[cc, rr, 2] = B
    return output_frame 
Example #6
Source File: predict.py    From Convolutional-Pose-Machine-tf with GNU Lesser General Public License v3.0 5 votes vote down vote up
def joints_plot_image(joints, weight, img, radius=3, thickness=2):
    """ Plot the joints on image

    :param joints:      (np.array)Assuming input of shape (num, joint_num, dim)
    :param img:         (image)Assuming input of shape (num, w, h, c)
    :param weight:      (np.array)Assuming input of shape (num, joint_num)
    :param radius:      (int)Radius
    :param thickness:   (int)Thickness
    :return:            set of RGB image (num, w, h, c)
    """
    assert len(joints.shape) == 3 and len(img.shape) == 4 and len(weight.shape) == 2
    assert joints.shape[0] == img.shape[0] == weight.shape[0]
    colors = [(241, 242, 224), (196, 203, 128), (136, 150, 0), (64, 77, 0),
              (201, 230, 200), (132, 199, 129), (71, 160, 67), (32, 94, 27),
              (130, 224, 255), (7, 193, 255), (0, 160, 255), (0, 111, 255),
              (220, 216, 207), (174, 164, 144), (139, 125, 96), (100, 90, 69),
              (252, 229, 179), (247, 195, 79), (229, 155, 3), (155, 87, 1),
              (231, 190, 225), (200, 104, 186), (176, 39, 156), (162, 31, 123),
              (210, 205, 255), (115, 115, 229), (80, 83, 239), (40, 40, 198)]
    ret = np.zeros(img.shape, np.uint8)
    assert len(joints.shape) == 3 and len(img.shape) == 4
    assert img.shape[-1] == 3
    ret = img.copy()
    for num in range(joints.shape[0]):
        for jnum in range(joints.shape[1]):
            if weight[num, jnum] == 1:
                rr, cc = draw.circle(
                    int(joints[num, jnum, 0]), int(joints[num, jnum, 1]), radius)
                ret[num, rr, cc] = colors[jnum]
    for num in range(joints.shape[0]):
        for lnk in range(len(LINKS)):
            if weight[num, LINKS[lnk][0]] == 1 and weight[num, LINKS[lnk][1]] == 1:
                rr, cc = draw.line(int(joints[num, LINKS[lnk][0], 0]), int(joints[num, LINKS[lnk][0], 1]),
                                int(joints[num, LINKS[lnk][1], 0]), int(joints[num, LINKS[lnk][1], 1]))
                ret[num, rr, cc] = colors[lnk]
    return ret 
Example #7
Source File: line_dataset.py    From DSACLine with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def draw_models(self, labels, data=None, correct=None):
		'''
		Draw lines for a batch of images.
	
		labels -- line parameters, array shape (Nx2) where 
			N is the number of images in the batch
			2 is the number of line parameters (intercept, slope)
		data -- batch of images to draw to, if empty a new batch wil be created according to the shape of labels 
			and lines will be green, lines will be blue otherwise
		correct -- array of shape (N) indicating whether a line estimate is correct 
		'''

		n = labels.shape[0]
		if data is None: 
			data = np.zeros((n, self.imgH, self.imgW, 3), dtype=np.float32)
			data.fill(self.bg_clr)
			clr = (0, 1, 0)
		else:
			clr = (0, 0, 1)

		for i in range (0, n):
			lY1 = int(labels[i, 0] * self.imgH)
			lY2 = int(labels[i, 1] * self.imgW + labels[i, 0] * self.imgH)
			self.draw_line(data[i], 0, lY1, self.imgW, lY2, clr)

			if correct is not None:
				
				# draw border green if estiamte is correct, red otherwise
				if correct[i]: borderclr = (0, 1, 0)
				else: borderclr = (1, 0, 0)
				
				set_color(data[i], line(0, 0, 0, self.imgW-1), borderclr)			
				set_color(data[i], line(0, 0, self.imgH-1, 0), borderclr)			
				set_color(data[i], line(self.imgH-1, 0, self.imgH-1, self.imgW-1), borderclr)			
				set_color(data[i], line(0, self.imgW-1, self.imgH-1, self.imgW-1), borderclr)			

		return data 
Example #8
Source File: line_dataset.py    From DSACLine with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def draw_hyps(self, labels, scores, data=None):
		'''
		Draw a set of line hypothesis for a batch of images.
		
		labels -- line parameters, array shape (NxMx2) where 
			N is the number of images in the batch
			M is the number of hypotheses per image
			2 is the number of line parameters (intercept, slope)
		scores -- hypotheses scores, array shape (NxM), see above, higher score will be drawn with higher opacity
		data -- batch of images to draw to, if empty a new batch wil be created according to the shape of labels
		
		'''

		n = labels.shape[0] # number of images
		m = labels.shape[1] # number of hypotheses

		if data is None: # create new batch of images
			data = np.zeros((n, self.imgH, self.imgW, 3), dtype=np.float32)
			data.fill(self.bg_clr)

		clr = (0, 0, 1)

		for i in range (0, n):
			for j in range (0, m):
				lY1 = int(labels[i, j, 0] * self.imgH)
				lY2 = int(labels[i, j, 1] * self.imgW + labels[i, j, 0] * self.imgH)
				self.draw_line(data[i], 0, lY1, self.imgW, lY2, clr, scores[i, j])

		return data 
Example #9
Source File: line_dataset.py    From DSACLine with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def draw_line(self, data, lX1, lY1, lX2, lY2, clr, alpha=1.0):
		'''
		Draw a line with the given color and opacity.

		data -- image to draw to
		lX1 -- x value of line segment start point
		lY1 -- y value of line segment start point
		lX2 -- x value of line segment end point
		lY2 -- y value of line segment end point
		clr -- line color, triple of values
		alpha -- opacity (default 1.0)
		'''

		rr, cc, val = line_aa(lY1, lX1, lY2, lX2)
		set_color(data, (rr, cc), clr, val*alpha) 
Example #10
Source File: drawing.py    From pyImSegm with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def closest_point_on_line(start, end, point):
    """ projection of the point to the line

    :param list(int) start: line starting point
    :param list(int) end: line ending point
    :param list(int) point: point for extimation
    :return list(int): point on the line

    >>> closest_point_on_line([0, 0], [1, 2], [0, 2])
    array([ 0.8,  1.6])
    """
    start, end, point = [np.array(a) for a in [start, end, point]]
    line = pl_line.Line(start, (end - start))
    proj = np.array(line.project(point))
    return proj 
Example #11
Source File: line_dataset.py    From DSACLine with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def __init__(self, imgW = 64, imgH = 64, margin = -5, bg_clr = 0.5):
		'''
		Constructor. 

		imgW -- image width (default 64)
		imgH -- image height (default 64)
		margin -- lines segments are sampled within this margin, negative value means that a line segment can start or end outside the image (default -5)
		bg_clr -- background intensity (default 0.5)
		'''
		
		self.imgW = imgW
		self.imgH = imgH
		self.margin = margin
		self.bg_clr = bg_clr 
Example #12
Source File: missing_parts.py    From pytorch_connectomics with MIT License 4 votes vote down vote up
def prepare_deform_slice(self, slice_shape, random_state):
        # grow slice shape by 2 x deformation strength
        grow_by = 2 * self.deformation_strength
        #print ('sliceshape: '+str(slice_shape[0])+' growby: '+str(grow_by)+ ' strength: '+str(deformation_strength))
        shape = (slice_shape[0] + grow_by, slice_shape[1] + grow_by)
        # randomly choose fixed x or fixed y with p = 1/2
        fixed_x = random_state.rand() < 0.5
        if fixed_x:
            x0, y0 = 0, np.random.randint(1, shape[1] - 2)
            x1, y1 = shape[0] - 1, np.random.randint(1, shape[1] - 2)
        else:
            x0, y0 = np.random.randint(1, shape[0] - 2), 0
            x1, y1 = np.random.randint(1, shape[0] - 2), shape[1] - 1

        ## generate the mask of the line that should be blacked out
        #print (shape)
        line_mask = np.zeros(shape, dtype='bool')
        rr, cc = line(x0, y0, x1, y1)
        line_mask[rr, cc] = 1

        # generate vectorfield pointing towards the line to compress the image
        # first we get the unit vector representing the line
        line_vector = np.array([x1 - x0, y1 - y0], dtype='float32')
        line_vector /= np.linalg.norm(line_vector)
        # next, we generate the normal to the line
        normal_vector = np.zeros_like(line_vector)
        normal_vector[0] = - line_vector[1]
        normal_vector[1] = line_vector[0]

        # make meshgrid
        x, y = np.meshgrid(np.arange(shape[1]), np.arange(shape[0]))
        # generate the vector field
        flow_x, flow_y = np.zeros(shape), np.zeros(shape)

        # find the 2 components where coordinates are bigger / smaller than the line
        # to apply normal vector in the correct direction
        components, n_components = label(np.logical_not(line_mask).view('uint8'))
        assert n_components == 2, "%i" % n_components
        neg_val = components[0, 0] if fixed_x else components[-1, -1]
        pos_val = components[-1, -1] if fixed_x else components[0, 0]

        flow_x[components == pos_val] = self.deformation_strength * normal_vector[1]
        flow_y[components == pos_val] = self.deformation_strength * normal_vector[0]
        flow_x[components == neg_val] = - self.deformation_strength * normal_vector[1]
        flow_y[components == neg_val] = - self.deformation_strength * normal_vector[0]

        # generate the flow fields
        flow_x, flow_y = (x + flow_x).reshape(-1, 1), (y + flow_y).reshape(-1, 1)

        # dilate the line mask
        line_mask = binary_dilation(line_mask, iterations=self.iterations) #default=10
        
        return flow_x, flow_y, line_mask 
Example #13
Source File: defect_augment.py    From gunpowder with MIT License 4 votes vote down vote up
def __prepare_deform_slice(self, slice_shape):

        # grow slice shape by 2 x deformation strength
        grow_by = 2 * self.deformation_strength
        shape = (slice_shape[0] + grow_by, slice_shape[1] + grow_by)

        # randomly choose fixed x or fixed y with p = 1/2
        fixed_x = random.random() < .5
        if fixed_x:
            x0, y0 = 0, np.random.randint(1, shape[1] - 2)
            x1, y1 = shape[0] - 1, np.random.randint(1, shape[1] - 2)
        else:
            x0, y0 = np.random.randint(1, shape[0] - 2), 0
            x1, y1 = np.random.randint(1, shape[0] - 2), shape[1] - 1

        ## generate the mask of the line that should be blacked out
        line_mask = np.zeros(shape, dtype='bool')
        rr, cc = line(x0, y0, x1, y1)
        line_mask[rr, cc] = 1

        # generate vectorfield pointing towards the line to compress the image
        # first we get the unit vector representing the line
        line_vector = np.array([x1 - x0, y1 - y0], dtype='float32')
        line_vector /= np.linalg.norm(line_vector)
        # next, we generate the normal to the line
        normal_vector = np.zeros_like(line_vector)
        normal_vector[0] = - line_vector[1]
        normal_vector[1] = line_vector[0]

        # make meshgrid
        x, y = np.meshgrid(np.arange(shape[1]), np.arange(shape[0]))
        # generate the vector field
        flow_x, flow_y = np.zeros(shape), np.zeros(shape)

        # find the 2 components where coordinates are bigger / smaller than the line
        # to apply normal vector in the correct direction
        components, n_components = label(np.logical_not(line_mask).view('uint8'))
        assert n_components == 2, "%i" % n_components
        neg_val = components[0, 0] if fixed_x else components[-1, -1]
        pos_val = components[-1, -1] if fixed_x else components[0, 0]

        flow_x[components == pos_val] = self.deformation_strength * normal_vector[1]
        flow_y[components == pos_val] = self.deformation_strength * normal_vector[0]
        flow_x[components == neg_val] = - self.deformation_strength * normal_vector[1]
        flow_y[components == neg_val] = - self.deformation_strength * normal_vector[0]

        # generate the flow fields
        flow_x, flow_y = (x + flow_x).reshape(-1, 1), (y + flow_y).reshape(-1, 1)

        # dilate the line mask
        line_mask = binary_dilation(line_mask, iterations=10)

        return flow_x, flow_y, line_mask 
Example #14
Source File: line_dataset.py    From DSACLine with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def sample_lines(self, n):
		'''
		Create new input images of random line segments and distractors along with ground truth parameters.

		n -- number of images to create
		'''

		data = np.zeros((n, self.imgH, self.imgW, 3), dtype=np.float32)
		data.fill(self.bg_clr)
		labels = np.ndarray((n, 2, 1, 1), dtype=np.float32)

		for i in range (0, n): # for each image

			# create a random number of distractor circles
			nC = random.randint(2, 5)
			for c in range(0, nC):

				cR = random.randint(int(0.1 * self.imgW), int(1 * self.imgW))			
				cX1 = random.randint(int(-0.5 * cR), int(self.imgW+0.5*cR+1))
				cY1 = random.randint(int(-0.5 * cR), int(self.imgH+0.5*cR+1))	

				clr = (random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1))

				rr, cc, val =  circle_perimeter_aa(cY1, cX1, cR)
				set_color(data[i], (rr, cc), clr, val)

			# create line segment
			while True:

				# sample segment end points
				lX1 = random.randint(self.margin, self.imgW-self.margin+1)
				lX2 = random.randint(self.margin, self.imgW-self.margin+1)
				lY1 = random.randint(self.margin, self.imgH-self.margin+1)
				lY2 = random.randint(self.margin, self.imgH-self.margin+1)

				# check min length
				length = math.sqrt((lX1 - lX2) * (lX1 - lX2) + (lY1 - lY2) * (lY1 - lY2))
				if length < minLength: continue

				# random color
				clr = (random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1))

				# calculate line ground truth parameters
				delta = lX2 - lX1
				if delta == 0: delta = 1 

				slope = (lY2 - lY1) / delta
				intercept = lY1 - slope * lX1

				# not too steep for stability
				if abs(slope) < maxSlope: break

			labels[i, 0] = intercept / self.imgH
			labels[i, 1] = slope

			self.draw_line(data[i], lX1, lY1, lX2, lY2, clr)

			# apply some noise on top
			data[i] = random_noise(data[i], mode='speckle')

		return data, labels 
Example #15
Source File: imgOp.py    From TextDetector with GNU General Public License v3.0 4 votes vote down vote up
def drawbb(img, coor, color):
	'''  drawbb(canvas, coor, color)

	draw bounding box on canvas
	cavas: grey-scale image to draw on
	coor: coordinates of bounding box (tuple contains: x, y, w, h)
	color: the bounding box color '''

	def rect_draw(canvas, Coor):
		canvas = numpy.uint8(canvas)
		for coor in Coor:
			x1 = coor[0]
			y1 = coor[1]
			x2 = coor[2]
			y2 = coor[3]
			line1 = skimage_line(x1, y1, x2, y1)
			line2 = skimage_line(x1, y1, x1, y2)
			line3 = skimage_line(x1, y2, x2, y2)
			line4 = skimage_line(x2, y1, x2, y2)
			skimage_set_color(canvas, line1, 255)
			skimage_set_color(canvas, line2, 255)
			skimage_set_color(canvas, line3, 255)
			skimage_set_color(canvas, line4, 255)
		return canvas
		
	if len(img.shape) == 3 and img.shape[2] == 3: # if color image
		if color == 'r':
			img[:, :, 0] = rect_draw(img[:, :, 0], coor)
		elif color == 'g':
			img[:, :, 1] = rect_draw(img[:, :, 1], coor)
		elif color == 'b':
			img[:, :, 2] = rect_draw(img[:, :, 2], coor)
		else:
			print 'Error: use only \'r, g, b\' for colors'
			return

	else: # if greyscale image
		canvas = numpy.uint8(img)
		img = numpy.zeros((canvas.shape[0], canvas.shape[1], 3))
		img[:, :, 0] = canvas
		img[:, :, 1] = canvas
		img[:, :, 2] = canvas
		canvas = rect_draw(canvas, coor)
		if color == 'r':
			img[:, :, 0] = canvas
		elif color == 'g':
			img[:, :, 1] = canvas
		elif color == 'b':
			img[:, :, 2] = canvas
		else:
			print 'Error: use only \'r, g, b\' for colors'
			return
	return img 
Example #16
Source File: drawing.py    From pyImSegm with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def draw_graphcut_weighted_edges(segments, centers, edges, edge_weights,
                                 img_bg=None, img_alpha=0.5):
    """ visualise the edges on the overlapping a background image

    :param [tuple(int,int)] centers: list of centers
    :param ndarray segments: np.array<height, width>
    :param ndarray edges: list of edges of shape <nb_edges, 2>
    :param ndarray edge_weights: weight per edge <nb_edges, 1>
    :param ndarray img_bg: image background
    :param float img_alpha: transparency
    :return ndarray: np.array<height, width, 3>

    >>> slic = np.array([[0] * 3 + [1] * 3 + [2] * 3+ [3] * 3] * 4 +
    ...                 [[4] * 3 + [5] * 3 + [6] * 3 + [7] * 3] * 4)
    >>> centres = [[1, 1], [1, 4], [1, 7], [1, 10],
    ...            [5, 1], [5, 4], [5, 7], [5, 10]]
    >>> edges = [[0, 1], [1, 2], [2, 3], [0, 4], [1, 5],
    ...          [4, 5], [2, 6], [5, 6], [3, 7], [6, 7]]
    >>> img = np.random.randint(0, 256, slic.shape + (3,))
    >>> edge_weights = np.ones(len(edges))
    >>> edge_weights[0] = 0
    >>> img = draw_graphcut_weighted_edges(slic, centres, edges, edge_weights, img_bg=img)
    >>> img.shape
    (8, 12, 3)
    """
    if img_bg is not None:
        if img_bg.ndim == 2:
            # duplicate channels to be like RGB
            img_bg = np.rollaxis(np.tile(img_bg, (3, 1, 1)), 0, 3)
        # convert to range 0,1 so the drawing is correct
        max_val = 1.
        if img_bg.dtype != np.float:
            max_val = max(255., img_bg.max())
        img = img_bg.astype(np.float) / max_val
        # make it partialy transparent
        img = (1. - img_alpha) + img * img_alpha
    else:
        img = np.zeros(segments.shape + (3,))
    clrs = plt.get_cmap('Greens')
    diff = (edge_weights.max() - edge_weights.min())
    if diff > 0:
        edge_ratio = (edge_weights - edge_weights.min()) / diff
    else:
        edge_ratio = np.zeros(edge_weights.shape)
    for i, edge in enumerate(edges):
        n1, n2 = edge
        y1, x1 = map(int, centers[n1])
        y2, x2 = map(int, centers[n2])

        # line = draw.line(y1, x1, y2, x2)  # , shape=img.shape[:2]
        # img[line] = clrs(edge_ratio[i])[:3]

        # using anti-aliasing
        rr, cc, val = draw.line_aa(y1, x1, y2, x2)  # , shape=img.shape[:2]
        color_w = np.tile(val, (3, 1)).T
        img[rr, cc, :] = color_w * clrs(edge_ratio[i])[:3] + (1 - color_w) * img[rr, cc, :]

        circle = draw.circle(y1, x1, radius=2, shape=img.shape[:2])
        img[circle] = 1., 1., 0.
    return img 
Example #17
Source File: segmentation.py    From graph-based-image-classification with MIT License 4 votes vote down vote up
def draw_image(image, segmentation, adjacency, neighborhood):
    neighborhood = list(neighborhood)

    image = mark_boundaries(image, segmentation, (0, 0, 0))

    graph = nx.from_numpy_matrix(adjacency)

    segmentation += np.ones_like(segmentation)
    segments = regionprops(segmentation)

    # Save the centroids in the node properties.
    for (n, data), segment in zip(graph.nodes_iter(data=True), segments):
        data['centroid'] = segment['centroid']

    # Iterate over all edges and draw them.
    for n1, n2, data in graph.edges_iter(data=True):
        y1, x1 = map(int, graph.node[n1]['centroid'])
        y2, x2 = map(int, graph.node[n2]['centroid'])
        line = draw.line(y1, x1, y2, x2)

        n1_idx = neighborhood.index(n1) if n1 in neighborhood else -1
        n2_idx = neighborhood.index(n2) if n2 in neighborhood else -1
        if abs(n1_idx - n2_idx) == 1 and n1_idx != -1 and n2_idx != -1:
            image[line] = [1, 0, 0]
        else:
            image[line] = [0, 1, 0]

    # Draw a circle at the root node.
    for i in range(0, len(neighborhood)):
        if neighborhood[i] < 0:
            continue

        y1, x1 = graph.node[neighborhood[i]]['centroid']
        circle = draw.circle(y1, x1, 2)

        if i == 0:
            image[circle] = [1, 1, 0]
        else:
            j = (i-1)/(len(neighborhood) - 2)
            image[circle] = [j, j, j]

    return image 
Example #18
Source File: segmentation.py    From kraken with Apache License 2.0 4 votes vote down vote up
def polygonal_reading_order(lines: Sequence[Tuple[List, List]],
                            text_direction: str = 'lr',
                            regions: Optional[Sequence[List[Tuple[int, int]]]] = None) -> Sequence[Tuple[List, List]]:
    """
    Given a list of baselines and regions, calculates the correct reading order
    and applies it to the input.

    Args:
        lines (Sequence): List of tuples containing the baseline and its
                          polygonization.
        regions (Sequence): List of region polygons.
        text_direction (str): Set principal text direction for column ordering.
                              Can be 'lr' or 'rl'

    Returns:
        A reordered input.
    """
    bounds = []
    if regions is not None:
        r = [geom.Polygon(reg) for reg in regions]
    else:
        r = []
    region_lines = [[] for _ in range(len(r))]
    indizes = {}
    for line_idx, line in enumerate(lines):
        l = geom.LineString(line[1])
        is_in_region = False
        for idx, reg in enumerate(r):
            if reg.contains(l):
                region_lines[idx].append((line_idx, (slice(l.bounds[1], l.bounds[0]), slice(l.bounds[3], l.bounds[2]))))
                is_in_region = True
                break
        if not is_in_region:
            bounds.append((slice(l.bounds[1], l.bounds[0]), slice(l.bounds[3], l.bounds[2])))
            indizes[line_idx] = ('line', line)
    # order everything in regions
    intra_region_order = [[] for _ in range(len(r))]
    for idx, reg in enumerate(r):
        if len(region_lines[idx]) > 0:
            order = reading_order([x[1] for x in region_lines[idx]], text_direction)
            lsort = topsort(order)
            intra_region_order[idx] = [region_lines[idx][i][0] for i in lsort]
            reg = reg.bounds
            bounds.append((slice(reg[1], reg[0]), slice(reg[3], reg[2])))
            indizes[line_idx+idx+1] = ('region', idx)
    # order unassigned lines and regions
    order = reading_order(bounds, text_direction)
    lsort = topsort(order)
    sidz = sorted(indizes.keys())
    lsort = [sidz[i] for i in lsort]
    ordered_lines = []
    for i in lsort:
        if indizes[i][0] == 'line':
            ordered_lines.append(indizes[i][1])
        else:
            ordered_lines.extend(lines[x] for x in intra_region_order[indizes[i][1]])
    return ordered_lines 
Example #19
Source File: segmentation.py    From kraken with Apache License 2.0 4 votes vote down vote up
def _interpolate_lines(clusters, elongation_offset, extent, st_map, end_map):
    """
    Interpolates the baseline clusters and sets the correct line direction.
    """
    logger.debug('Reticulating splines')
    lines = []
    extent = geom.Polygon([(0, 0), (extent[1]-1, 0), (extent[1]-1, extent[0]-1), (0, extent[0]-1), (0, 0)])
    f_st_map = maximum_filter(st_map, size=20)
    f_end_map = maximum_filter(end_map, size=20)
    for cluster in clusters[1:]:
        # find start-end point
        points = [point for edge in cluster for point in edge]
        dists = squareform(pdist(points))
        i, j = np.unravel_index(dists.argmax(), dists.shape)
        # build adjacency matrix for shortest path algo
        adj_mat = np.full_like(dists, np.inf)
        for l, r in cluster:
            idx_l = points.index(l)
            idx_r = points.index(r)
            adj_mat[idx_l, idx_r] = dists[idx_l, idx_r]
        # shortest path
        _, pr = shortest_path(adj_mat, directed=False, return_predecessors=True, indices=i)
        k = j
        line = [points[j]]
        while pr[k] != -9999:
            k = pr[k]
            line.append(points[k])
        # smooth line
        line = np.array(line[::-1])
        line = approximate_polygon(line[:,[1,0]], 1)
        lr_dir = line[0] - line[1]
        lr_dir = (lr_dir.T  / np.sqrt(np.sum(lr_dir**2,axis=-1))) * elongation_offset/2
        line[0] = line[0] + lr_dir
        rr_dir = line[-1] - line[-2]
        rr_dir = (rr_dir.T  / np.sqrt(np.sum(rr_dir**2,axis=-1))) * elongation_offset/2
        line[-1] = line[-1] + rr_dir
        ins = geom.LineString(line).intersection(extent)
        if ins.type == 'MultiLineString':
            ins = linemerge(ins)
            # skip lines that don't merge cleanly
            if ins.type != 'LineString':
                continue
        line = np.array(ins, dtype='uint')
        l_end = tuple(line[0])[::-1]
        r_end = tuple(line[-1])[::-1]
        if f_st_map[l_end] - f_end_map[l_end] > 0.2 and f_st_map[r_end] - f_end_map[r_end] < -0.2:
            pass
        elif f_st_map[l_end] - f_end_map[l_end] < -0.2 and f_st_map[r_end] - f_end_map[r_end] > 0.2:
            line = line[::-1]
        else:
            logger.debug('Insufficient marker confidences in output. Defaulting to upright line.')
            if line[0][0] > line[-1][0]:
                line = line[::-1]
        lines.append(line.tolist())
    return lines 
Example #20
Source File: segmentation.py    From kraken with Apache License 2.0 4 votes vote down vote up
def _compute_sp_states(sp_can, bl_map, st_map, end_map):
    """
    Estimates the superpixel state information.
    """
    sep_map = st_map + end_map
    logger.debug('Triangulating superpixels')
    # some pages might not contain
    if len(sp_can) < 2:
        logger.warning('Less than 2 superpixels in image. Nothing to vectorize.')
        return {}
    elif len(sp_can) < 3:
        logger.warning('Less than 3 superpixels in image. Skipping triangulation')
        key = tuple([tuple(sp_can[0]), tuple(sp_can[1])])
        line_locs = draw.line(*(key[0] + key[1]))
        intensities = {key: (bl_map[line_locs].mean(), bl_map[line_locs].var(), sep_map[line_locs].mean(), sep_map[line_locs].max())}
        return intensities
    tri = Delaunay(sp_can, qhull_options="QJ Pp")
    indices, indptr = tri.vertex_neighbor_vertices
    # dict mapping each edge to its intensity. Needed for subsequent clustering step.
    intensities = {}
    logger.debug('Computing superpixel state information')
    for vertex in range(len(sp_can)):
        # look up neighboring indices
        neighbors = tri.points[indptr[indices[vertex]:indices[vertex+1]]]
        # calculate intensity of line segments to neighbors in both bl map and separator map
        intensity = []
        for nb in neighbors.astype('int'):
            key = [tuple(sp_can[vertex]), tuple(nb)]
            key.sort()
            key = tuple(key)
            line_locs = draw.line(*(key[0] + key[1]))
            intensities[key] = (bl_map[line_locs].mean(), bl_map[line_locs].var(), sep_map[line_locs].mean(), sep_map[line_locs].max())
            intensity.append(intensities[key][0])

    logger.debug('Filtering triangulation')
    # filter edges in triangulation
    for k, v in list(intensities.items()):
        if v[0] < 0.4:
            del intensities[k]
            continue
        if v[1] > 5e-02:
            del intensities[k]
            continue
        # filter edges with high separator affinity
        if v[2] > 0.125 or v[3] > 0.25 or v[0] < 0.5:
            del intensities[k]
            continue

    return intensities 
Example #21
Source File: segmentation.py    From kraken with Apache License 2.0 4 votes vote down vote up
def reading_order(lines: Sequence, text_direction: str = 'lr') -> List:
    """Given the list of lines (a list of 2D slices), computes
    the partial reading order.  The output is a binary 2D array
    such that order[i,j] is true if line i comes before line j
    in reading order."""

    logger.info('Compute reading order on {} lines in {} direction'.format(len(lines), text_direction))

    order = np.zeros((len(lines), len(lines)), 'B')

    def _x_overlaps(u, v):
        return u[1].start < v[1].stop and u[1].stop > v[1].start

    def _above(u, v):
        return u[0].start < v[0].start

    def _left_of(u, v):
        return u[1].stop < v[1].start

    def _separates(w, u, v):
        if w[0].stop < min(u[0].start, v[0].start):
            return 0
        if w[0].start > max(u[0].stop, v[0].stop):
            return 0
        if w[1].start < u[1].stop and w[1].stop > v[1].start:
            return 1
        return 0

    if text_direction == 'rl':
        def horizontal_order(u, v):
            return not _left_of(u, v)
    else:
        horizontal_order = _left_of

    for i, u in enumerate(lines):
        for j, v in enumerate(lines):
            if _x_overlaps(u, v):
                if _above(u, v):
                    order[i, j] = 1
            else:
                if [w for w in lines if _separates(w, u, v)] == []:
                    if horizontal_order(u, v):
                        order[i, j] = 1
    return order 
Example #22
Source File: anno_helper.py    From lost with MIT License 4 votes vote down vote up
def draw_annos(annos, types, img, color=(255,0,0), point_r=2):
    '''Draw annotations inside a image

    Args:
        annos (list): List of annotations.
        types (list): List of types.
        img (numpy.array): The image to draw annotations in.
        color (tuple): (R,G,B) color that is used for drawing.
    
    Note:
        The given image will be directly edited!

    Returns:
        numpy.array: Image with drawn annotations
    '''
    if annos:
        if len(img.shape) < 3: 
            img = gray2rgb(img)
        img_h, img_w, _ = img.shape
        for anno, t in zip(annos, types):
            if t == 'bbox':
                anno = trans_boxes_to([anno])[0]
                anno = to_abs([anno], [t], (img_w, img_h))[0]
                xmin, ymin, xmax, ymax = anno
                rr, cc = polygon_perimeter([ymin, ymin, ymax, ymax],
                    [xmin, xmax, xmax, xmin ], shape=img.shape)
            elif t == 'polygon':
                anno = to_abs([anno], [t], (img_w, img_h))[0]
                anno = np.array(anno)
                rr, cc = polygon_perimeter(anno[:,1].tolist(),
                    anno[:,0].tolist(), shape=img.shape)
            elif t == 'point':
                anno = to_abs([anno], [t], (img_w, img_h))[0]
                rr, cc = circle(anno[1], anno[0], point_r, shape=img.shape)
            elif t == 'line':
                anno = to_abs([anno], [t], (img_w, img_h))[0]
                for i, point in enumerate(anno):
                    if i >= (len(anno)-1):
                        break
                    rr, cc = line(point[1], point[0], 
                        anno[i+1][1], anno[i+1][0])
                    img[rr,cc] = color
            else:
                raise ValueError('Unknown annotation type: {}'.format(t))
            img[rr,cc] = color
        return img
    else:
        return [] 
Example #23
Source File: core_annots.py    From ibeis with Apache License 2.0 4 votes vote down vote up
def make_hog_block_image(hog, config=None):
    """
    References:
        https://github.com/scikit-image/scikit-image/blob/master/skimage/feature/_hog.py
    """
    from skimage import draw

    if config is None:
        config = HOGConfig()

    cx, cy = config['pixels_per_cell']

    normalised_blocks = hog
    (n_blocksy, n_blocksx, by, bx, orientations) = normalised_blocks.shape

    n_cellsx = (n_blocksx - 1) + bx
    n_cellsy = (n_blocksy - 1) + by

    # Undo the normalization step
    orientation_histogram = np.zeros((n_cellsy, n_cellsx, orientations))

    for x in range(n_blocksx):
        for y in range(n_blocksy):
            norm_block = normalised_blocks[y, x, :]
            # hack, this only works right for block sizes of 1
            orientation_histogram[y:y + by, x:x + bx, :] = norm_block

    sx = n_cellsx * cx
    sy = n_cellsy * cy

    radius = min(cx, cy) // 2 - 1
    orientations_arr = np.arange(orientations)
    dx_arr = radius * np.cos(orientations_arr / orientations * np.pi)
    dy_arr = radius * np.sin(orientations_arr / orientations * np.pi)
    hog_image = np.zeros((sy, sx), dtype=float)
    for x in range(n_cellsx):
        for y in range(n_cellsy):
            for o, dx, dy in zip(orientations_arr, dx_arr, dy_arr):
                centre = tuple([y * cy + cy // 2, x * cx + cx // 2])
                rr, cc = draw.line(int(centre[0] - dx),
                                   int(centre[1] + dy),
                                   int(centre[0] + dx),
                                   int(centre[1] - dy))
                hog_image[rr, cc] += orientation_histogram[y, x, o]
    return hog_image