Search code examples
pythonopencvedge-detectionconnected-components

Extracting components from an edge image and storing for further processing


1Input

Input

Given an edge image, I want to retrieve components in it one by one and store each component as an image so that I can use it later for processing. I guess this is called connected component labeling.

For example, in the input image, there are 2 lines , 1 circle ,2 curves I want to 5 image files containing these 5 components.

I was able to come up with code as below, but I do not know how to proceed further. Currently I am getting all the components coloured in different colours in output.

      import scipy
      from skimage import io
      from scipy import ndimage
      import matplotlib.pyplot as plt
      import cv2
      import numpy as np

    fname='..//Desktop//test1.png'
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    #canny
   img_canny = cv2.Canny(img,100,200)

   threshold = 50

   # find connected components
   labeled, nr_objects = ndimage.label(img_canny) 
   print('Number of objects is %d'% nr_objects)

   plt.imsave('..//Desktop//out.png', labeled)

Output

output

New output


Solution

  • You may not need to use cv2.canny() to segment the contours, you can simply use binary thresholding technique as:

    img = cv2.imread("/path/to/img.png")
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(img_gray, 130, 255, cv2.THRESH_BINARY_INV)
    
    # Opencv v3.x
    im, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    
    for i in xrange(len(contours)):
        rect = cv2.boundingRect(contours[i])
        contour_component = img[rect[1]:rect[1] + rect[3], rect[0]:rect[0] + rect[2]]
    
        cv2.imwrite("component_{}.png".format(i), contour_component)