title: Get the contour (outline) from a png image with the correct edges
body: <p>I have multiple png files and I'm trying to get the polygon contour coordinates.
  That is the simplified coordinates, only each outer corner (not a convex hull polygon).</p>
  <p>The program that will do this at the moment is python and opencv.
  But another program is oke I did try to fix this using npm packages, imagemagick, potrace, Lua.
  It will be uses as a shell command in a 'build polygons from images' process.</p>
  <p>This was the last test under python.</p>
  <p>The problem now is the that some edges are 'not' correct in the example below.</p>
  <p>I did the following steps</p>
  <ul>
  <li>Convert the alpha to black and white</li>
  <li>Trace the contour</li>
  <li>Get the coordinates</li>
  </ul>
  <ol>
  <li>The original png file contains black lines (keep them).</li>
  </ol>
  <p><a href="https://i.stack.imgur.com/WFVso.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/WFVso.png" alt="Original png" /></a></p>
  <ol start="2">
  <li>Converted black and white image (you can't see the top line, because this website have a white background)</li>
  </ol>
  <pre><code>ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)
  </code></pre>
  <p><a href="https://i.stack.imgur.com/snaap.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/snaap.png" alt="Converted png" /></a></p>
  <ol start="3">
  <li>Traced contour outline (not the output I want)</li>
  </ol>
  <pre><code>contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  </code></pre>
  <p><a href="https://i.stack.imgur.com/WRJkC.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/WRJkC.jpg" alt="traced image" /></a></p>
  <p>The problem are the two holes, the 1 pixel left and 1 pixel right is missing.</p>
  <p><a href="https://i.stack.imgur.com/QvJOq.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/QvJOq.png" alt="problem zoom detail" /></a></p>
  <ol start="4">
  <li>When I use that contour data inside a other program you get this:</li>
  </ol>
  <p><a href="https://i.stack.imgur.com/L4BWB.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/L4BWB.png" alt="external polygon" /></a></p>
  <ol start="5">
  <li>I want this contour outline polygon data, so the external program show this:</li>
  </ol>
  <p><a href="https://i.stack.imgur.com/aJfxG.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/aJfxG.png" alt="output I want" /></a></p>
  <pre class="lang-py prettyprint-override"><code># https://opensource.com/article/19/5/python-3-default-mac#what-to-do
  # https://solarianprogrammer.com/2019/10/21/install-opencv-python-macos/
  # https://docs.opencv.org/master/d4/d73/tutorial_py_contours_begin.html
  # https://stackoverflow.com/questions/25733694/process-image-to-find-external-contour
  # https://docs.opencv.org/3.4/dd/d49/tutorial_py_contour_features.html
  # https://stackoverflow.com/questions/39823221/imagemagick-find-coordinates-of-outline-of-transparent-png-not-border
  
  import numpy as np
  import cv2
  
  img = cv2.imread('../temp/bord.png', cv2.IMREAD_UNCHANGED)
  
  # make black and white
  ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)
  
  # find the external contour
  contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  
  # at this point I want to have the correct contours to process them inside a other program
  # print(contours)
  
  # start debugging
  #save image
  cv2.imwrite('../temp/bord_converted.png',mask) 
  
  
  #create an empty image for contours
  img_contours = np.zeros(img.shape)
  # draw the contours on the empty image
  cv2.drawContours(img_contours, contours, -1, (0,255,0), 1)
  cv2.imwrite('../temp/bord_contour.jpg',img_contours) 
  </code></pre>
  <p>EDIT</p>
  <p>The other things that I did try:</p>
  <p>Marching squares programs</p>
  <p><strong>Golang</strong></p>
  <p><a href="https://github.com/zx9597446/marchingsquare/issues/1" rel="nofollow noreferrer">https://github.com/zx9597446/marchingsquare/issues/1</a>
  That one gives me another problem, but the correct codes</p>
  <p><strong>Npm</strong>
  <a href="https://github.com/scottglz/image-outline" rel="nofollow noreferrer">https://github.com/scottglz/image-outline</a>
  That one gives me almost the same problem as above</p>
  <p><strong>imagemagick</strong></p>
  <p>Was trying some things converting the png to black/ and white and return the outline.</p>
  <pre><code>convert &quot;$IMAGE&quot; -matte -bordercolor none -border 1 -alpha extract -edge 1 -threshold 50% -depth 8 txt: | awk -F: '/white/{print $1}'
  </code></pre>
  <p><strong>potrace</strong></p>
  <p>But all the outputs have things so I can't use it.</p>
  <pre><code>potrace --progress -b svg --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --group --flat ../temp/bordout.bmp -o ../temp/bordout.svg
  potrace --progress -b eps -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.eps
  potrace --progress -b pdf -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pdf
  potrace --progress -b pdfpage --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pdfpage
  potrace --progress -b ps -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.ps
  potrace --progress -b pgm --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pgm
  potrace --progress -b dxf --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.dxf
  potrace --progress -b geojson --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.geojson
  potrace --progress -b gimppath --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.gimppath
  potrace --progress -b xfig --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.xfig
  </code></pre>
  <p>For example the SVG output looks correct as a picture but I can't convert it to a x,y point array polygon.</p>
  <pre><code>&lt;path d=&quot;M121 132 l-121 0 0 -66 0 -66 121 0 121 0 0 66 0 66 -121 0z m0 -1
  l120 0 0 -22 0 -23 -10 0 -11 0 0 -42 0 -43 -5 0 -5 0 0 43 0 42 -89 0 -89 0
  0 -42 0 -43 -5 0 -5 0 0 43 0 42 -10 0 -11 0 0 23 0 22 120 0z M121 130 l-119
  0 0 -21 0 -22 11 0 10 0 0 -42 0 -43 4 0 4 0 0 43 0 42 90 0 90 0 0 -42 0 -43
  4 0 4 0 0 43 0 42 11 0 10 0 0 22 0 21 -119 0z&quot;/&gt;
  &lt;/g&gt;
  </code></pre>
  <p>Using <a href="https://github.com/Phrogz/svg-path-to-polygons" rel="nofollow noreferrer">https://github.com/Phrogz/svg-path-to-polygons</a> for example gives me</p>
  <pre><code>[
    [
      [ 121, 132 ], [ 0, 132 ],
      [ 0, 66 ],    [ 0, 0 ],
      [ 121, 0 ],   [ 242, 0 ],
      [ 242, 66 ],  [ 242, 132 ],
      [ 121, 132 ], [ 121, 132 ],
      closed: true
    ],
    [
      [ 121, 131 ], [ 241, 131 ], [ 241, 109 ],
      [ 241, 86 ],  [ 231, 86 ],  [ 220, 86 ],
      [ 220, 44 ],  [ 220, 1 ],   [ 215, 1 ],
      [ 210, 1 ],   [ 210, 44 ],  [ 210, 86 ],
      [ 121, 86 ],  [ 32, 86 ],   [ 32, 44 ],
      [ 32, 1 ],    [ 27, 1 ],    [ 22, 1 ],
      [ 22, 44 ],   [ 22, 86 ],   [ 12, 86 ],
      [ 1, 86 ],    [ 1, 109 ],   [ 1, 131 ],
      [ 121, 131 ], [ 121, 131 ], closed: true
    ],
    [
      [ 121, 130 ], [ 2, 130 ],   [ 2, 109 ],
      [ 2, 87 ],    [ 13, 87 ],   [ 23, 87 ],
      [ 23, 45 ],   [ 23, 2 ],    [ 27, 2 ],
      [ 31, 2 ],    [ 31, 45 ],   [ 31, 87 ],
      [ 121, 87 ],  [ 211, 87 ],  [ 211, 45 ],
      [ 211, 2 ],   [ 215, 2 ],   [ 219, 2 ],
      [ 219, 45 ],  [ 219, 87 ],  [ 230, 87 ],
      [ 240, 87 ],  [ 240, 109 ], [ 240, 130 ],
      [ 121, 130 ], [ 121, 130 ], closed: true
    ]
  ]
  </code></pre>
  <p>EDIT 2</p>
  <p>When I use the SVG solution the output give me now a readable point list</p>
  <pre><code>&lt;polygon fill=&quot;none&quot; points=&quot;0,0 0,44 20,44 21,45 21,129 30,129 30,45 31,44 208,44 209,45 209,129 218,129 218,45 219,44 239,44 239,0&quot; stroke=&quot;black&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;miter&quot; /&gt;
  </code></pre>
  <p>But when I use that coordinate list it is not 100% correct.
  The corners are still not correct.</p>
  <p>The output (zoomed in) with firefox will show this:</p>
  <p><a href="https://i.stack.imgur.com/f1cK6.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/f1cK6.png" alt="firefox output" /></a></p>
  <p>And the program where I will use the coordinate list (not the SVG)</p>
  <pre><code>love.graphics.polygon(&quot;line&quot;,0,0,0,44,20,44,21,45,21,129,30,129,30,45,31,44,208,44,209,45,209,129,218,129,218,45,219,44,239,44,239,0)
  </code></pre>
  <p>Will output:</p>
  <p><a href="https://i.stack.imgur.com/qKNAA.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/qKNAA.png" alt="love2d output" /></a></p>
  <p>Edit 3</p>
  <p>Using the last python script don't make the polygon.</p>
  <p><a href="https://i.stack.imgur.com/tGVH3.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/tGVH3.png" alt="program output" /></a></p>