Advertisement
YauhenMardan

Untitled

Dec 15th, 2020
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.49 KB | None | 0 0
  1. from PIL import Image
  2. import numpy as np
  3. from skimage.morphology import binary_erosion, binary_dilation
  4. from scipy.ndimage.morphology import binary_erosion as binary_erosion_2
  5. from skimage.morphology import disk, diamond
  6.  
  7.  
  8. # SKELETONIZATION AND RESTORING
  9.  
  10. class MorphologicalSkeleton:
  11.  
  12. @staticmethod
  13. def skeletonize_n_restore(img, str_elem_name='disk', str_elem_size=3):
  14. if str_elem_name == 'disk':
  15. str_elem = disk(str_elem_size)
  16. elif str_elem_name == 'diamond':
  17. str_elem = diamond(str_elem_size)
  18.  
  19. # preprocess
  20. img = img.copy()
  21. img = img.convert('1')
  22. img = np.array(img)
  23. img = np.invert(img)
  24. # skeletonize
  25. s_list, res, total_n = MorphologicalSkeleton.get_skeleton(img, str_elem)
  26. skeletonized_img = Image.fromarray(res.astype('uint8'))
  27. # restore
  28. res = MorphologicalSkeleton.get_restored(res, s_list, str_elem, total_n)
  29. res = np.invert(res)
  30. restored_img = Image.fromarray(res.astype('uint8'))
  31.  
  32. return skeletonized_img, restored_img, total_n
  33.  
  34. @staticmethod
  35. def get_skeleton(img, str_elem):
  36. # step 1
  37. n = 0
  38. y1 = img.copy()
  39. s_list = []
  40. while True:
  41. # step 2
  42. y2 = binary_erosion(y1, str_elem)
  43. # step 3
  44. if np.all(y2 <= 0):
  45. total_n = n
  46. s_list.append(y1)
  47. break
  48. # step 4
  49. y3 = binary_dilation(y2, str_elem)
  50. # step 5
  51. s_list.append(np.bitwise_xor(y1, y3))
  52. # step 6
  53. n += 1
  54. y1 = y2
  55. res = np.zeros((len(img[:, 1]), len(img[1, :])))
  56.  
  57. for s in s_list:
  58. res += s
  59.  
  60. return s_list, res, total_n
  61.  
  62. @staticmethod
  63. def get_restored(img, s_list, str_elem, total_n):
  64. n = total_n
  65. # step 1
  66. res = np.zeros(img.shape)
  67. while True:
  68. # step 2
  69. res = np.logical_or(res, s_list[n])
  70. if n == 0:
  71. break
  72. # step 3
  73. res = binary_dilation(res, str_elem)
  74. # step 4
  75. n -= 1
  76. return res
  77.  
  78.  
  79. # SKELETONIZATION WITH THINNING
  80.  
  81. class Skeleton:
  82. t1 = np.array([[[True, True, True],
  83. [False, True, False],
  84. [False, False, False]],
  85.  
  86. [[False, False, False],
  87. [False, False, False],
  88. [True, True, True]]])
  89.  
  90. t5 = np.array([[[False, True, False],
  91. [False, True, True],
  92. [False, False, False]],
  93.  
  94. [[False, False, False],
  95. [True, False, False],
  96. [True, True, False]]])
  97.  
  98. @staticmethod
  99. def skeletonize(img):
  100. # preprocess
  101. img = img.copy()
  102. img = img.convert('1')
  103. img = np.array(img)
  104. img = np.invert(img)
  105. # skeletonize
  106. total_n = 0
  107. while True:
  108. prev_img = img.copy()
  109. img = Skeleton.iterate(img, Skeleton.t1)
  110. img = Skeleton.iterate(img, Skeleton.t5)
  111. total_n += 1
  112. if (prev_img == img).all():
  113. break
  114. skeletonized_img = Image.fromarray(img.astype('uint8'))
  115. return skeletonized_img, total_n
  116.  
  117. @staticmethod
  118. def iterate(img, t):
  119. for i in range(0, 4):
  120. img = Skeleton.thinning_operation(img, t)
  121. t[0] = np.rot90(t[0])
  122. t[1] = np.rot90(t[1])
  123. return img
  124.  
  125. @staticmethod
  126. def cross_operation(x, t):
  127. return np.logical_and(binary_erosion(x, t[0]), binary_erosion(np.logical_not(x), t[1]))
  128.  
  129. @staticmethod
  130. def thinning_operation(x, t):
  131. return np.logical_and(x, np.logical_not(Skeleton.cross_operation(x, t)))
  132.  
  133.  
  134. # GETTING CONVEX HULL
  135.  
  136. class ConvexHull:
  137. t1 = np.array([[[True, True, True],
  138. [False, False, True],
  139. [False, False, False]],
  140.  
  141. [[False, False, False],
  142. [False, True, False],
  143. [False, False, False]]])
  144.  
  145. t5 = np.array([[[True, True, True],
  146. [True, False, False],
  147. [False, False, False]],
  148.  
  149. [[False, False, False],
  150. [False, True, False],
  151. [False, False, False]]])
  152.  
  153. @staticmethod
  154. def get_convex_hull(img):
  155. # preprocess
  156. img = img.copy()
  157. img = img.convert('1')
  158. img = np.array(img)
  159. img = np.logical_not(img)
  160. # getting convex hull
  161. total_n = 0
  162. while True:
  163. prev_img = img.copy()
  164. img = ConvexHull.iterate(img, ConvexHull.t1)
  165. img = ConvexHull.iterate(img, ConvexHull.t5)
  166. total_n += 1
  167. if (prev_img == img).all():
  168. break
  169. hull_img = Image.fromarray(img.astype('uint8'))
  170. return hull_img, total_n
  171.  
  172. @staticmethod
  173. def iterate(img, t):
  174. for i in range(0, 4):
  175. img = ConvexHull.thickening_operation(img, t)
  176. t[0] = np.rot90(t[0])
  177. return img
  178.  
  179. @staticmethod
  180. def cross_operation(x, t):
  181. return np.logical_and(binary_erosion_2(x, t[0]), binary_erosion_2(np.logical_not(x), t[1]))
  182.  
  183. @staticmethod
  184. def thickening_operation(x, t):
  185. return np.logical_or(x, ConvexHull.cross_operation(x, t))
  186.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement