pythonopencvpathdftcanny-operator

Extracting the outline of an image as a continuous path using opencv


Background

So I am currently working on a project that is an extension of the coding train's Fourier transform series. Huge shoutout to him for inspiring this project!

After watching his video on the Fourier transform of the coding train logo, I thought it would be interesting to try and implement this for any image. My goal is to be able to feed the outline of the subject in any image as a continuous path to the DFT algorithm so I can visualize the Fourier transform of said path.

Link to coding train's video: https://www.youtube.com/watch?v=MY4luNgGfms

My Progress

So far using opencv in python, I have implemented an algorithm to detect the outline of the subject from any image and display the same. I have attached a sample output.

Before Processing Image before processing

After Processing Image after processing

My issue and expected result

Now that I have the edges done, I want to be able to extract this edge as a continuous path represented by (x,y) coordinates. The reason I need it as a continuous path is that I am going to perform a DFT on this path and if it is not continuous my DFT visualization fails.

I have no idea how to order the points so that they don't jump from left to right or from up to down but rather follow a smooth continuous path from left to right or vice versa.

I am a beginner in computer vision and I really hope someone can help me out! Do feel free to let me know if I have messed up somewhere or if I can make my code better. I really want to learn.

Code

Here is my code so far

# read in the image
img = cv2.imread("Images/selfietest.jpeg")


# convert image to gray scale
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
height, width = gray_img.shape

# white_padding = np.zeros((50, width, 3))
# white_padding[:, :] = [255, 255, 255]
# rgb_img = np.row_stack((white_padding, imgOut))

gray_img = 255 - gray_img
gray_img[gray_img > 100] = 255
gray_img[gray_img <= 100] = 0
# black_padding = np.zeros((50, width))
# gray_img = np.row_stack((black_padding, gray_img))

kernel = np.ones((30, 30), np.uint8)

# fill inside of image
filledImage = cv2.morphologyEx(gray_img, cv2.MORPH_CLOSE, kernel)
filledImageNormalized = np.uint8(filledImage)

# Canny edge detection
edges = cv2.Canny(filledImageNormalized, 100, 200)

title = ['edges']
images = [edges]


for i in range(1):
    plt.subplot(1, 1, i + 1), plt.imshow(images[i], 'gray')
    plt.title(title[i])
    plt.xticks([])
    plt.yticks([])
plt.show()

Solution

  • Let me make an assumption: you only work with the provided image. Let say the starting point is the white pixel on the last line. The approach would then be:

    With that said, maybe you are not working only with this image. In that case you have to adapt the way to find the starting pixel to match all possibilities.

    But with this you will get a continuous path on your outline.