0

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

TylerH
  • 20,799
  • 66
  • 75
  • 101
Azhar
  • 29
  • 5

2 Answers2

1

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)
ZdaR
  • 22,343
  • 7
  • 66
  • 87
0

This:

   num=nr_objects
   i=0
   while i<num:
      plt.imshow(labeled)
      i=i+1

Does not loop over different labels, it just shows the same image num times. You need to do something like:

   for i in range(num):
      tmp = np.zeros(labeled.shape)
      tmp[labeled == i] = 255
      plt.imshow(tmp)

Then you will see one for each label. Also you can use a for loop... If you have any questions leave a comment.

api55
  • 11,070
  • 4
  • 41
  • 57
  • Thank you @api55 Output: Number of objects is 149( i guess i have to store 149 components) Getting only one image like this https://i.stack.imgur.com/FD7wZ.jpg – Azhar Jan 01 '19 at 12:03
  • @Azhar That's because you are using canny and not all the components are touching each other. You can try using connected components and then canny or findContours, that is what ZdaR suggests :) – api55 Jan 01 '19 at 13:26