Skip to content
Snippets Groups Projects
Select Git revision
  • d5fd2917993cf529720b6f9a7d65ee84e1cc04b9
  • main default protected
  • GUI
  • christian_test
4 results

live_wire.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    live_wire.py 5.38 KiB
    import time
    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    from skimage import exposure
    from skimage.filters import gaussian
    from skimage.feature import canny
    from skimage.graph import route_through_array
    from scipy.signal import convolve2d
    
    '''
    ### Canny Edge cost image
    def compute_cost_image(path, sigma=3):
    
        ### Load image
        image = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
        
        # Apply histogram equalization
        image_contrasted = exposure.equalize_adapthist(image, clip_limit=0.01)
    
        # Apply smoothing
        smoothed_img = gaussian(image_contrasted, sigma=sigma)
    
        # Apply Canny edge detection
        canny_img = canny(smoothed_img)
    
        # Create cost image
        cost_img = 1.0 / (canny_img + 1e-5)  # Invert edges: higher cost where edges are stronger
    
        return cost_img
    
    def find_path(cost_image, points):
    
        if len(points) != 2:
            raise ValueError("Points should be a list of 2 points: seed and target.")
        
        seed_rc, target_rc = points
    
        path_rc, cost = route_through_array(
            cost_image, 
            start=seed_rc, 
            end=target_rc, 
            fully_connected=True
        )
    
        return path_rc
    '''
    
    ### Disk live wire cost image
    def compute_cost_image(path, sigma=3, disk_size=15):
    
        ### Load image
        image = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
    
        # Apply histogram equalization
        image_contrasted = exposure.equalize_adapthist(image, clip_limit=0.01)
    
        # Apply smoothing
        smoothed_img = gaussian(image_contrasted, sigma=sigma)
    
        # Apply Canny edge detection
        canny_img = canny(smoothed_img)
    
        # Do disk thing
        binary_img = canny_img
        k_size = 17
        kernel = circle_edge_kernel(k_size=disk_size)
        convolved = convolve2d(binary_img, kernel, mode='same', boundary='fill')
    
        # Create cost image
        cost_img = (convolved.max() - convolved)**4  # Invert edges: higher cost where edges are stronger
    
        return cost_img
    
    
    def find_path(cost_image, points):
    
        if len(points) != 2:
            raise ValueError("Points should be a list of 2 points: seed and target.")
        
        seed_rc, target_rc = points
    
        path_rc, cost = route_through_array(
            cost_image, 
            start=seed_rc, 
            end=target_rc, 
            fully_connected=True
        )
    
        return path_rc
    
    
    def circle_edge_kernel(k_size=5, radius=None):
        """
        Create a k_size x k_size array whose values increase linearly
        from 0 at the center to 1 at the circle boundary (radius).
    
        Parameters
        ----------
        k_size : int
            The size (width and height) of the kernel array.
        radius : float, optional
            The circle's radius. By default, set to (k_size-1)/2.
    
        Returns
        -------
        kernel : 2D numpy array of shape (k_size, k_size)
            The circle-edge-weighted kernel.
        """
        if radius is None:
            # By default, let the radius be half the kernel size
            radius = (k_size - 1) / 2
    
        # Create an empty kernel
        kernel = np.zeros((k_size, k_size), dtype=float)
    
        # Coordinates of the center
        center = radius  # same as (k_size-1)/2 if radius is default
    
        # Fill the kernel
        for y in range(k_size):
            for x in range(k_size):
                dist = np.sqrt((x - center)**2 + (y - center)**2)
                if dist <= radius:
                    # Weight = distance / radius => 0 at center, 1 at boundary
                    kernel[y, x] = dist / radius
    
        return kernel
    
    
    
    
    
    
    
    # Other functions 
    def downscale(img, points, scale_percent):
        """
        Downsample `img` to `scale_percent` size and scale the given points accordingly.
        Returns (downsampled_img, (scaled_seed, scaled_target)).
        """
        if scale_percent == 100:
            return img, (tuple(points[0]), tuple(points[1]))
        else:
            # Compute new dimensions
            width = int(img.shape[1] * scale_percent / 100)
            height = int(img.shape[0] * scale_percent / 100)
            new_dimensions = (width, height)
    
            # Downsample
            downsampled_img = cv2.resize(img, new_dimensions, interpolation=cv2.INTER_AREA)
    
            # Scaling factors
            scale_x = width / img.shape[1]
            scale_y = height / img.shape[0]
    
            # Scale the points (x, y)
            seed_xy = tuple(points[0])
            target_xy = tuple(points[1])
            scaled_seed_xy = (int(seed_xy[0] * scale_x), int(seed_xy[1] * scale_y))
            scaled_target_xy = (int(target_xy[0] * scale_x), int(target_xy[1] * scale_y))
    
            return downsampled_img, (scaled_seed_xy, scaled_target_xy)
    
    def compute_cost(image, sigma=3.0, epsilon=1e-5):
        """
        Smooth the image, run Canny edge detection, then invert the edge map into a cost image.
        """
    
        # Apply histogram equalization
        image_contrasted = exposure.equalize_adapthist(image, clip_limit=0.01)
    
        # Apply smoothing
        smoothed_img = gaussian(image_contrasted, sigma=sigma)
    
        # Apply Canny edge detection
        canny_img = canny(smoothed_img)
    
        # Create cost image
        cost_img = 1.0 / (canny_img + epsilon)  # Invert edges: higher cost where edges are stronger
    
        return cost_img, canny_img
    
    def backtrack_pixels_on_image(img_color, path_coords, bgr_color=(0, 0, 255)):
        """
        Color the path on the (already converted BGR) image in the specified color.
        `path_coords` should be a list of (row, col) or (y, x).
        """
        for (row, col) in path_coords:
            img_color[row, col] = bgr_color
        return img_color
    
    def export_path(path_coords, path_name):
        """
        Export the path to a np array.
        """
        np.save(path_name, path_coords)
        return None