_utils.py 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. import imgviz
  2. import numpy as np
  3. import skimage
  4. from labelme.logger import logger
  5. def _get_contour_length(contour):
  6. contour_start = contour
  7. contour_end = np.r_[contour[1:], contour[0:1]]
  8. return np.linalg.norm(contour_end - contour_start, axis=1).sum()
  9. def compute_polygon_from_mask(mask):
  10. contours = skimage.measure.find_contours(np.pad(mask, pad_width=1))
  11. if len(contours) == 0:
  12. logger.warning("No contour found, so returning empty polygon.")
  13. return np.empty((0, 2), dtype=np.float32)
  14. contour = max(contours, key=_get_contour_length)
  15. POLYGON_APPROX_TOLERANCE = 0.004
  16. polygon = skimage.measure.approximate_polygon(
  17. coords=contour,
  18. tolerance=np.ptp(contour, axis=0).max() * POLYGON_APPROX_TOLERANCE,
  19. )
  20. polygon = np.clip(polygon, (0, 0), (mask.shape[0] - 1, mask.shape[1] - 1))
  21. polygon = polygon[:-1] # drop last point that is duplicate of first point
  22. if 0:
  23. import PIL.Image
  24. image_pil = PIL.Image.fromarray(imgviz.gray2rgb(imgviz.bool2ubyte(mask)))
  25. imgviz.draw.line_(image_pil, yx=polygon, fill=(0, 255, 0))
  26. for point in polygon:
  27. imgviz.draw.circle_(image_pil, center=point, diameter=10, fill=(0, 255, 0))
  28. imgviz.io.imsave("contour.jpg", np.asarray(image_pil))
  29. return polygon[:, ::-1] # yx -> xy