Georgia
Georgia

Reputation: 109

Find the intersection line between two colors

I'm trying to find the intersection between color green and blue of a set of images that are similar to this one:

enter image description here

So what I need is something is something like this:

enter image description here

And because I need to use the contours for some calculus after that I would like to know if it's possible to have the points of the curve in an array or something... but I have no idea if this is possible. I tried to do the mask but I don't think it's going to work... here's the code:

        lower_val = np.array([0, 0, 0])

        upper_val = np.array([150, 255, 150])

        mask = cv2.inRange(image, lower_val, upper_val)
        only_lumen = cv2.bitwise_and(image, image, mask=mask)
        gray = cv2.cvtColor(only_lumen, cv2.COLOR_BGR2GRAY)
        blur = cv2.GaussianBlur(gray, (3, 3), 0)
        thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
        thresh = 255 - thresh

This is how I'm trying to display the points:

    x, y = [i[0] for i in pts_list], [i[1] for i in pts_list]
    max_x, max_y = max(x), max(y)

    image = np.zeros((max_y + 1, max_x + 1))

    for i in range(len(pts_list)):
        image[max_y - y[i], x[i]] = 1

And this is the image I obtain: enter image description here

I don't understand why the dots meet in a corner and why the background is violet... The lines where supposed to be in the middel

Upvotes: 2

Views: 1096

Answers (1)

the23Effect
the23Effect

Reputation: 580

For now, I will give you the simplest of solutions you can try (can be improved a lot):

Boundary pixels (after getting the masks) will be adjacent to each other but you have to pick a side if you want 1 pixel width boundary as minimum. Alternative to this is to set search kernel and use morphology to dilate your color masks according to your search kernel. The common points in the dilated masks will be the neighborhood points which you can extract by simply doing a Bitwise AND.

# Define the color ranges for each color of interest for creating masks.
COLOR1_RANGE = [(30, 0, 0), (255, 50, 50)]  # Blue in BGR, [(low), (high)].
COLOR2_RANGE = [(0, 30, 0), (50, 255, 50)]  # Green in BGR, [(low), (high)].

# Create masks:
color1_mask = cv2.inRange(self.img, COLOR1_RANGE[0], COLOR1_RANGE[1])
color2_mask = cv2.inRange(self.img, COLOR2_RANGE[0], COLOR2_RANGE[1])

# Adjust according to your adjacency requirement.
kernel = np.ones((3, 3), dtype=np.uint8)

# Dilating masks to expand boundary.
color1_mask = cv2.dilate(color1_mask, kernel, iterations=1)
color2_mask = cv2.dilate(color2_mask, kernel, iterations=1)

# Required points now will have both color's mask val as 255.
common = cv2.bitwise_and(color1_mask, color2_mask)

# Common is binary np.uint8 image, min = 0, max = 255.
# SOME_THRESHOLD can be anything within the above range. (not needed though)
# Extract/Use it in whatever way you want it.
intersection_points = np.where(common > SOME_THRESHOLD)

# Say you want these points in a list form, then you can do this.
pts_list = [[r, c] for r, c in zip(*intersection_points)]
print(pts_list)

Some Sample Outputs:

Input 01 (Simple):
Simple Input

Output 01 (Simple):
Simple Output

Output Points as List (Partial):

pts_list = [[99, 104], [99, 105], [100, 104], [100, 105], [100, 106], ...]

Input 02 (Complex):
Complex Input

Output 02 (Complex):
Complex Output

Output Points as List (Partial):

pts_list = [[127, 309], [127, 310], [127, 311], [127, 312], [127, 313], ...]

Update 1:
I made a small change in the code comments to make it more understandable.

Upvotes: 2

Related Questions