Utsav T
Utsav T

Reputation: 1545

Python Open CV - Get coordinates of region

I am a beginner in image processing (and openCV). After applying watershed algorithm to an image, the output that is obtained is something like this -

enter image description here

Is it possible to have the co-ordinates of the regions segmented out ?

The code used is this (in case you wish to have a look) -

import numpy as np
import cv2
from matplotlib import pyplot as plt


img = cv2.imread('input.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# noise removal
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)

# sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=3)

# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening,cv2.cv.CV_DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)

# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)

# Marker labelling
ret, markers = cv2.connectedComponents(sure_fg)

# Add one to all labels so that sure background is not 0, but 1
markers = markers+1

# Now, mark the region of unknown with zero
markers[unknown==255] = 0

markers = cv2.watershed(img,markers)
img[markers == -1] = [255,0,0]

plt.imshow(img)
plt.show()

Is there any function or algorithm to extract the co-ordinates of the coloured regions that are separated out ? Any help would be much appreciated !

Upvotes: 0

Views: 2409

Answers (1)

Miki
Miki

Reputation: 41775

After this line:

markers = cv2.watershed(img,markers)

markers will be an image with all region segmented, and the pixel value in each region will be an integer (label) greater than 0. Background has label 0, boundaries has label -1.

You already know the number of labels from ret returned by connectedComponents.

You need a data structure to contains the points for each region. For example, the points of each region will go in an array of points. You need several of this (for each region), so another array.

So, if you want to find the pixel of each region, you can do:

1) Scan the image and append the point to an array of arrays of points, where each array of points will contains the points of the same region

// Pseudocode

"labels" is an array of an array of points
initialize labels size to "ret", the length of each array of points is 0.

for r = 1 : markers.rows
    for c = 1 : markers.cols
        value = markers(r,c) 
        if(value > 0)
            labels{value-1}.append(Point(c,r)) // r = y, c = x
        end
    end
end

2) Generate a mask for each label value, and collect the points in the mask

// Pseudocode

"labels" is an array of an array of points
initialize labels size to "ret", the length of each array of points is 0.

for value = 1 : ret-1
    mask = (markers == value)
    labels{value-1} = all points in the mask // You can use cv::boxPoints(...) for this
end

The first approach is likely to be much faster, the second is easier to implement. Sorry, but I can't give you Python code (C++ would have been much better :D ), but you should find your way out whit this.

Hope it helps

Upvotes: 1

Related Questions