lvminthin.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. # High Quality Edge Thinning using Pure Python
  2. # Written by Lvmin Zhang
  3. # 2023 April
  4. # Stanford University
  5. # If you use this, please Cite "High Quality Edge Thinning using Pure Python", Lvmin Zhang, In Mikubill/sd-webui-controlnet.
  6. import cv2
  7. import numpy as np
  8. lvmin_kernels_raw = [
  9. np.array([
  10. [-1, -1, -1],
  11. [0, 1, 0],
  12. [1, 1, 1]
  13. ], dtype=np.int32),
  14. np.array([
  15. [0, -1, -1],
  16. [1, 1, -1],
  17. [0, 1, 0]
  18. ], dtype=np.int32)
  19. ]
  20. lvmin_kernels = []
  21. lvmin_kernels += [np.rot90(x, k=0, axes=(0, 1)) for x in lvmin_kernels_raw]
  22. lvmin_kernels += [np.rot90(x, k=1, axes=(0, 1)) for x in lvmin_kernels_raw]
  23. lvmin_kernels += [np.rot90(x, k=2, axes=(0, 1)) for x in lvmin_kernels_raw]
  24. lvmin_kernels += [np.rot90(x, k=3, axes=(0, 1)) for x in lvmin_kernels_raw]
  25. lvmin_prunings_raw = [
  26. np.array([
  27. [-1, -1, -1],
  28. [-1, 1, -1],
  29. [0, 0, -1]
  30. ], dtype=np.int32),
  31. np.array([
  32. [-1, -1, -1],
  33. [-1, 1, -1],
  34. [-1, 0, 0]
  35. ], dtype=np.int32)
  36. ]
  37. lvmin_prunings = []
  38. lvmin_prunings += [np.rot90(x, k=0, axes=(0, 1)) for x in lvmin_prunings_raw]
  39. lvmin_prunings += [np.rot90(x, k=1, axes=(0, 1)) for x in lvmin_prunings_raw]
  40. lvmin_prunings += [np.rot90(x, k=2, axes=(0, 1)) for x in lvmin_prunings_raw]
  41. lvmin_prunings += [np.rot90(x, k=3, axes=(0, 1)) for x in lvmin_prunings_raw]
  42. def remove_pattern(x, kernel):
  43. objects = cv2.morphologyEx(x, cv2.MORPH_HITMISS, kernel)
  44. objects = np.where(objects > 127)
  45. x[objects] = 0
  46. return x, objects[0].shape[0] > 0
  47. def thin_one_time(x, kernels):
  48. y = x
  49. is_done = True
  50. for k in kernels:
  51. y, has_update = remove_pattern(y, k)
  52. if has_update:
  53. is_done = False
  54. return y, is_done
  55. def lvmin_thin(x, prunings=True):
  56. y = x
  57. for i in range(32):
  58. y, is_done = thin_one_time(y, lvmin_kernels)
  59. if is_done:
  60. break
  61. if prunings:
  62. y, _ = thin_one_time(y, lvmin_prunings)
  63. return y
  64. def nake_nms(x):
  65. f1 = np.array([[0, 0, 0], [1, 1, 1], [0, 0, 0]], dtype=np.uint8)
  66. f2 = np.array([[0, 1, 0], [0, 1, 0], [0, 1, 0]], dtype=np.uint8)
  67. f3 = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=np.uint8)
  68. f4 = np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]], dtype=np.uint8)
  69. y = np.zeros_like(x)
  70. for f in [f1, f2, f3, f4]:
  71. np.putmask(y, cv2.dilate(x, kernel=f) == x, x)
  72. return y