Circle the segmented image to the original

57 views Asked by At

I am new to Python. I have read this (How to overlay segmented image on top of main image in python) but unfortunately I cannot get to the desired result for the example provided below. The three following images are:

  1. The main image.
  2. The segmented image.
  3. The result of overlaying and circling (which isn't working). The code is below.

enter image description here

enter image description here

enter image description here

os.chdir('/home/.../Desktop/python question')

import cv2
import matplotlib.pyplot as plt
import numpy as np
from skimage.segmentation import clear_border
from skimage import measure
import pandas as pd

import numpy as np
import cv2


# main image:
main = cv2.imread('main.png', cv2.IMREAD_GRAYSCALE)
plt.imshow(main, cmap='gray')
#cv2.imshow("main", main)

# segmented image:
seg = cv2.imread('seg.png', cv2.IMREAD_GRAYSCALE)
plt.imshow(seg, cmap='gray')
#cv2.imshow("seg", seg)

# Dictionary giving RGB colour for label (segment label) - label 1 in red, label 2 in yellow
RGBforLabel = {1:(0,0,255),
               2:(0,555,255)}


# Find external contours

contours, _ = cv2.findContours(main, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

from statistics import mean

# Iterate over all contours
for i, c in enumerate(contours):
    # Find mean colour inside this contour by doing a masked mean
    mask = np.zeros(seg.shape[:2], np.uint8) # add [:2] after shape if bug
    #cv2.drawContours(mask,[c],-1,255, -1)
    cv2.drawContours(mask,[c], -1,(255,0,0), -1)
    # DEBUG: cv2.imwrite(f"mask-{i}.png",mask)
    mean,_, _, _ = cv2.mean(seg, mask=mask)
    # DEBUG: print(f"i: {i}, mean: {mean}")
    #print(f"i: {i}, mean: {mean}")


    # Get appropriate colour for this label
    label = 2 if mean > 1.0 else 1
    colour = RGBforLabel.get(label)
    # DEBUG: print(f"Colour: {colour}")

    # Outline contour in that colour on main image, line thickness=1
    #cv2.drawContours(main,[c],-1,colour,33)
    main2 = cv2.drawContours(main,[c],-1,(0, 255, 0),3)

# Save result
cv2.imwrite('result.png', main)

This doesn't produce the desired result. I want only the triangle to be circled all around its shape (whatever the colour, for example in red).

Please, can you point me in the right direction?

Thank you in advance.

1

There are 1 answers

5
Bill Horvath On

It looks to me like you're not converting the main image back into a color image, which I'd presume is what you need to do to overlay a colored outline on the perimeter of the triangle. In the answer you cited, they did so by re-defining the value of main after it was read in grayscale:

main = cv2.imread('main.png',cv2.IMREAD_GRAYSCALE)
main = cv2.cvtColor(main,cv2.COLOR_GRAY2BGR)

You may need to do the same thing.