Search code examples
pythonimage-processingconnected-components

Replacement of circular spots by respective colors


My objective here is to replace the spot in mask_image by a color corresponding to the spot in original_image. What I did here is to find connected components and labeling them, but I can't figure out how to find the corresponding labeled spot and replace it. How can i put the n circles in n objects and fill them by the corresponding intensities? Any help would be appreciated.

For example, if spot in (2, 1) in mask image should be painted by color of corresponding spot in this image below.

mask image http://myfair.software/goethe/images/mask.jpg

mask

original image http://myfair.software/goethe/images/original.jpg original image

def thresh(img):
    ret , threshold = cv2.threshold(img,5,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    return threshold

def spot_id(img):
    seed_pt = (5, 5)
    fill_color = 0
    mask = np.zeros_like(img)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    for th in range(5, 255):
        prev_mask = mask.copy()
        mask = cv2.threshold(img, th, 255, cv2.THRESH_BINARY)[1]
        mask = cv2.floodFill(mask, None, seed_pt, fill_color)[1]

        mask = cv2.bitwise_or(mask, prev_mask)

        mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

    #here I labelled them
    n_centers, labels = cv2.connectedComponents(mask)
    label_hue = np.uint8(892*labels/np.max(labels))
    blank_ch = 255*np.ones_like(label_hue)
    labeled_img = cv2.merge([label_hue, blank_ch, blank_ch])
    labeled_img = cv2.cvtColor(labeled_img, cv2.COLOR_HSV2BGR)
    labeled_img[label_hue==0] = 0

    print('There are %d bright spots in the image.'%n_centers)

    cv2.imshow("labeled_img",labeled_img)
    return mask, n_centers

image_thresh = thresh(img_greyscaled)
mask, centers = spot_id(img_greyscaled)

Solution

  • There is one very simple way of accomplishing this task. First one needs to sample the value at the center of each dot in mask_image. Next, one expands this color to fill the dot in that same image.

    Here is some code using PyDIP (because I know it better than OpenCV, I'm an author), I'm sure something similar can be done with OpenCV alone:

    import PyDIP as dip
    import cv2
    import numpy as np
    
    # Load the color image shown in the question
    original_image = cv2.imread('/home/cris/tmp/BxW25.png')
    # Load the mask image shown in the question
    mask_image = cv2.imread('/home/cris/tmp/aqf3Z.png')[:,:,0]
    
    # Get a single colored pixel in the middle of each spot of the mask
    colors = dip.EuclideanSkeleton(mask_image > 50, 'loose ends away') * original_image
    
    # Spread that color across the full spot
    # (dilation and similar operators like this one don't work with color images,
    #  so we apply the operation on each channel separately)
    for t in range(colors.TensorElements()):
       colors.TensorElement(t).Copy(dip.MorphologicalReconstruction(colors.TensorElement(t), mask_image))
    
    # Save the result
    cv2.imwrite('/home/cris/tmp/so.png', np.array(colors))
    

    output of code above