I have a number of black and white images and would like to convert them to a set of lines, such that I can fully, or at least close to fully, reconstruct the original image from the lines. In other words I'm trying to vectorize the image to a set of lines.
I have already looked at the HoughLinesTransform, however this does not cover every part of the image and is more about finding the lines in the image rather than fully converting the image to a line representation. In addition the line transform does not encode the actual width of the lines leaving me guessing at how to reconstruct the images back (which I need to do as this is a preproccesing step towards training a machine learning algorithm).
So far I tried the following code using the houghLineTransform:
import numpy as np
import cv2
MetersPerPixel=0.1
def loadImageGray(path):
img=(cv2.imread(path,0))
return img
def LineTransform(img):
edges = cv2.Canny(img,50,150,apertureSize = 3)
minLineLength = 10
maxLineGap = 20
lines = cv2.HoughLines(edges,1,np.pi/180,100,minLineLength,maxLineGap)
return lines;
def saveLines(liness):
img=np.zeros((2000,2000,3), np.uint8)
for lines in liness:
for x1,y1,x2,y2 in lines:
print(x1,y1,x2,y2)
img=cv2.line(img,(x1,y1),(x2,y2),(0,255,0),3)
cv2.imwrite('houghlines5.jpg',img)
def main():
img=loadImageGray("loadtest.png")
lines=LineTransform(img)
saveLines(lines)
main()
However when tested using the following 
As you can see it is missing lines that are not axis aligned and if you look closely even the detected lines have been split into 2 lines with some space between them. I also had to draw these images with a preset width while the real width isn't known.
Edit: on the suggestion of @MarkSetchell I tried the pypotrace by using the following code, currently it largely ignored bezier curves and just tries to act like they are straight lines, I will focus on that problem later, however right now the results aren't optimal either:
def TraceLines(img):
bmp = potrace.Bitmap(bitmap(img))
path=bmp.trace()
lines=[]
i=0
for curve in path:
for segment in curve:
print(repr(segment))
if segment.is_corner:
c_x, c_y = segment.c
c2_x ,c2_y= segment.end_point
lines.append([[int(c_x), int(c_y),int(c2_x) ,int(c2_y)]])
else:
c_x, c_y = segment.c1
c2_x ,c2_y= segment.end_point
i=i+1
return lines
this results in this image
, which is an improvement, however while the problem with the circle can be addressed at a later point the missing parts of the square and the weird artefacts on the other straight lines are more problematic. Anyone know how to fix them? Any tips on how to get the line widths?
Anybody got any suggestions on how to better approach this problem?
edit edit: here is another test image :
, it includes multiple line widths I would like to capture.







