13

I am using openCV with python to extract contours from an image. Now I need to export these contour paths (list) as an svg paths. How can I achieve this ?

code:

ret,thresh = cv2.threshold(imgray,27,25,0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL , cv2.CHAIN_APPROX_TC89_L1)
print(type(contours)) #type list
Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
Laxman
  • 1,149
  • 2
  • 11
  • 17
  • 2
    What is the the aspect you are having difficulties with exactly? You have a vector of contours, you iterate through them converting them to SVG `path` statements and writing them to a text file https://www.w3schools.com/graphics/svg_path.asp You may need to make an initial pass to know the maximum dimensions for your page-size, or you just use the dimensions of your original image on which you found the contours. – Mark Setchell Mar 30 '17 at 08:35
  • @MarkSetchell Thank you for the hint. I was being too lazy :) – Laxman Mar 30 '17 at 10:28

2 Answers2

20

the problem has been solved as follows:

c = max(contours, key=cv2.contourArea) #max contour
f = open('path.svg', 'w+')
f.write('<svg width="'+str(width)+'" height="'+str(height)+'" xmlns="http://www.w3.org/2000/svg">')
f.write('<path d="M')

for i in xrange(len(c)):
    #print(c[i][0])
    x, y = c[i][0]
    print(x)
    f.write(str(x)+  ' ' + str(y)+' ')

f.write('"/>')
f.write('</svg>')
f.close()
Laxman
  • 1,149
  • 2
  • 11
  • 17
  • Well done - and thank you for sharing back your code with the community. – Mark Setchell Mar 30 '17 at 09:38
  • @MarkSetchell, I also reduced the vertices of the contours using cv2.approxPolyDP() , now I need to find a way to smoothed the lines. – Laxman Mar 30 '17 at 10:04
  • A (not very elegant) possibility may be to draw the paths into an image and the use `potrace` to smooth that... http://potrace.sourceforge.net – Mark Setchell Mar 30 '17 at 10:09
  • @MarkSetchell I am not trying to draw paths 'over' and image. For my problem, I need to extract the paths as a vector format so that I can use it elsewhere as an svg. – Laxman Mar 30 '17 at 10:27
  • I was suggesting you create a *temporary* image with the unsmoothed contours on it and then let `potrace` convert that to a smoothed SVG file. – Mark Setchell Mar 30 '17 at 13:05
  • in my case i had to add the first point at the end to close the contour. – Moshel Jul 03 '20 at 09:39
4

The other answer only save the outmost contour in svg file, which is not my case. To save all the contours found by opencv, you could instead do this:

with open("path.svg", "w+") as f:
    f.write(f'<svg width="{w}" height="{h}" xmlns="http://www.w3.org/2000/svg">')

    for c in contours:
        f.write('<path d="M')
        for i in range(len(c)):
            x, y = c[i][0]
            f.write(f"{x} {y} ")
        f.write('" style="stroke:pink"/>')
    f.write("</svg>")
ospider
  • 9,334
  • 3
  • 46
  • 46