1
votes

Hi i want to do something like in this video. with python API in the V-rep system, Right now I have my robot working and only need to process the image that I want to draw.

To do this I need to have a vector of (x,y) coordinates of the path for the pen. So i'm trying with OpenCV findContours function. here is my code:

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

img = cv2.imread('img.jpg', 3)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

edges,contours,hierarchy = cv2.findContours(gray, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)

xList = [x[0][0][0] for x in contours]
yList = [y[0][0][1] for y in contours]

#plot image
plt.subplot(121)
plt.imshow(img,cmap = 'gray')
plt.title('Original Image') 

#plot contour
plt.subplot(122)
plt.plot(xList,yList)
plt.title('Edge Image')

plt.show()

here is my example image:

enter image description here

and the result if I use scatter plot to plot each point individually that shows me the contour of the image.

enter image description here

Ok, maybe its not the best example finding contours with OpenCV its my first.

The if I plot the points using plot function, to see the path thath I want to follow I get this:

enter image description here

So wath I want is to find the way that sort all the point on a consecutive order path to draw the image contour.

The issue here is that the point are unsorted so the don have the relation with its previous and the the next point they are just a cloud of points. So I need to get it sorted to construct the path.

Any idea on how to do this?

2
I think you should post example image in question to make it clear, not just paste the link.(Not every one can login in YTB.)Kinght 金
@Silencer, thank for your suggestion, I update my question to clarify the ideaefirvida
Ok, I see. You want to create a path like that: i.stack.imgur.com/q4SJF.png. ? Convert to gray, threshold to binary image, findContours on binary-imaget, then drawContours is ok.Kinght 金
@Silencer, yes that wht I need, but instead of drawContour, I need the list of the contour pointsefirvida

2 Answers

1
votes

1. You want to create some like that:

Basic steps are:

  1. Read and convert to gray,
  2. Threshold to binary image
  3. Do findContours on binary-imaget
  4. Then drawContours, you'll get it.

2. If you want to get some think like this:

enter image description here

Basic steps are:

  1. Read and convert to gray
  2. Blur and do Canny
  3. Find by connectedComponents
  4. Then set the labels to different colors
  5. You will get like that.

enter image description here


The code to generate the last image:

#!/usr/bin/python3
# 2018.01.23 11:25:35 CST
# 2018.01.23 11:45:22 CST

import numpy as np
import cv2
import myutils

colors = [(0, 0, 255), (0, 43, 255), (0, 85, 255), (0, 128, 255), (0, 170, 255), (0, 213, 255), (0, 255, 255), (0, 255, 212), (0, 255, 170), (0, 255, 127), (0, 255, 85), (0, 255, 42), (0, 255, 0), (43, 255, 0), (85, 255, 0), (128, 255, 0), (170, 255, 0), (213, 255, 0), (255, 255, 0), (255, 212, 0), (255, 170, 0), (255, 127, 0), (255, 85, 0), (255, 42, 0), (255, 0, 0)]

img = cv2.imread("leaf.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.medianBlur(img, 3)
edged = cv2.Canny(gray, 50, 200)

## Find connected edges
ret, labels = cv2.connectedComponents(edged)

## Draw(set to different colors)
canvas = np.zeros_like(img, np.uint8)
for i in range(1,ret):
    pts = labels == i
    canvas[pts] = colors[i%len(colors)]

## Display
cv2.imshow("res", canvas);cv2.waitKey();cv2.destroyAllWindows()
cv2.imwrite("res.png", canvas)

But Notice, I set the edges with different colors, while the points of different colors maybe not the real path.

1
votes

I found this thread that give me the idea to use matplotlib and contour function, I debug it and found the data that it use to plot in the allsegs property, and this solve my problem for now, maybe its not the best solution but for now it works.

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

img = cv2.imread('img.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# gray = cv2.bilateralFilter(gray, 50, 50, 10)
edged = cv2.Canny(gray, 70, 250)

#plot image
plt.subplot(1,3,1)
plt.imshow(img, cmap='gray')

#plot contour
plt.subplot(1,3,2)
a = plt.contour(edged, levels=[255], colors='black', origin='image')

#plot separated contour
plt.subplot(1,3,3)
for i in range(len(a.allsegs[0])):
    x = a.allsegs[0][i][:,0]
    y = a.allsegs[0][i][:,1]
    plt.plot(x,y)

plt.show()

enter image description here