Skip to content

Commit 5e49451

Browse files
author
Robert Sachunsky
committed
ocrolib.morph: add dist_labels (distance transform of semantic segmentation)
1 parent a8dc700 commit 5e49451

File tree

1 file changed

+29
-15
lines changed

1 file changed

+29
-15
lines changed

ocrd_cis/ocropy/ocrolib/morph.py

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
### various add-ons to the SciPy morphology package
33
################################################################
44

5-
6-
75
from numpy import *
86
#from scipy.ndimage import morphology,measurements,filters
97
from scipy.ndimage import measurements
@@ -68,36 +66,40 @@ def check_binary(image):
6866
assert amin(image)>=0 and amax(image)<=1,\
6967
"array should be binary, has values %g to %g"%(amin(image),amax(image))
7068

69+
@checks(uintpair)
70+
def brick(size):
71+
return ones(size, uint8)
72+
7173
@checks(ABINARY2,uintpair)
7274
def r_dilation(image,size,origin=0):
7375
"""Dilation with rectangular structuring element using fast OpenCV.dilate."""
74-
return cv2.dilate(image.astype(uint8), ones(size, uint8))
76+
return cv2.dilate(image.astype(uint8), brick(size))
7577
# return filters.maximum_filter(image,size,origin=(size[0]%2-1,size[1]%2-1))
7678

7779
@checks(ABINARY2,uintpair)
7880
def r_erosion(image,size,origin=-1):
7981
"""Erosion with rectangular structuring element using fast OpenCV.erode."""
80-
return cv2.erode(image.astype(uint8), ones(size, uint8))
82+
return cv2.erode(image.astype(uint8), brick(size))
8183
# return filters.minimum_filter(image,size,origin=0, mode='constant', cval=1)
8284

8385
@checks(ABINARY2,uintpair)
8486
def r_opening(image,size,origin=0):
8587
"""Opening with rectangular structuring element using fast OpenCV.morphologyEx."""
86-
return cv2.morphologyEx(image.astype(uint8), cv2.MORPH_OPEN, ones(size, uint8))
88+
return cv2.morphologyEx(image.astype(uint8), cv2.MORPH_OPEN, brick(size))
8789
# image = r_erosion(image,size,origin=0)
8890
# return r_dilation(image,size,origin=-1)
8991

9092
@checks(ABINARY2,uintpair)
9193
def r_closing(image,size,origin=0):
9294
"""Closing with rectangular structuring element using fast OpenCV.morphologyEx."""
93-
return cv2.morphologyEx(image.astype(uint8), cv2.MORPH_CLOSE, ones(size, uint8))
95+
return cv2.morphologyEx(image.astype(uint8), cv2.MORPH_CLOSE, brick(size))
9496
# image = r_dilation(image,size,origin=0)
9597
# return r_erosion(image,size,origin=-1)
9698

9799
@checks(ABINARY2,uintpair)
98100
def rb_dilation(image,size,origin=0):
99101
"""Binary dilation using linear filters."""
100-
return cv2.dilate(image.astype(uint8), ones(size, uint8))
102+
return cv2.dilate(image.astype(uint8), brick(size))
101103
# output = zeros(image.shape,'f')
102104
# filters.uniform_filter(image,size,output=output,origin=(size[0]%2-1,size[1]%2-1))
103105
# # 0 creates rounding artifacts
@@ -106,22 +108,22 @@ def rb_dilation(image,size,origin=0):
106108
@checks(ABINARY2,uintpair)
107109
def rb_erosion(image,size,origin=-1):
108110
"""Binary erosion using linear filters."""
109-
return cv2.erode(image.astype(uint8), ones(size, uint8))
111+
return cv2.erode(image.astype(uint8), brick(size))
110112
# output = zeros(image.shape,'f')
111113
# filters.uniform_filter(image,size,output=output,origin=0, mode='constant', cval=1)
112114
# return array(output==1,'i')
113115

114116
@checks(ABINARY2,uintpair)
115117
def rb_opening(image,size,origin=0):
116118
"""Binary opening using linear filters."""
117-
return cv2.morphologyEx(image.astype(uint8), cv2.MORPH_OPEN, ones(size, uint8))
119+
return cv2.morphologyEx(image.astype(uint8), cv2.MORPH_OPEN, brick(size))
118120
# image = rb_erosion(image,size,origin=0)
119121
# return rb_dilation(image,size,origin=-1)
120122

121123
@checks(ABINARY2,uintpair)
122124
def rb_closing(image,size,origin=0):
123125
"""Binary closing using linear filters."""
124-
return cv2.morphologyEx(image.astype(uint8), cv2.MORPH_CLOSE, ones(size, uint8))
126+
return cv2.morphologyEx(image.astype(uint8), cv2.MORPH_CLOSE, brick(size))
125127
# image = rb_dilation(image,size,origin=0)
126128
# return rb_erosion(image,size,origin=-1)
127129

@@ -142,26 +144,26 @@ def rb_reconstruction(image,mask,step=1,maxsteps=None):
142144
@checks(GRAYSCALE,uintpair)
143145
def rg_dilation(image,size,origin=0):
144146
"""Grayscale dilation using fast OpenCV.dilate."""
145-
return cv2.dilate(image, ones(size, uint8))
147+
return cv2.dilate(image, brick(size))
146148
# return filters.maximum_filter(image,size,origin=origin)
147149

148150
@checks(GRAYSCALE,uintpair)
149151
def rg_erosion(image,size,origin=0):
150152
"""Grayscale erosion using fast OpenCV.erode."""
151-
return cv2.erode(image, ones(size, uint8))
153+
return cv2.erode(image, brick(size))
152154
# return filters.minimum_filter(image,size,origin=origin, mode='constant', cval=1)
153155

154156
@checks(GRAYSCALE,uintpair)
155157
def rg_opening(image,size,origin=0):
156158
"""Grayscale opening using fast OpenCV.morphologyEx."""
157-
return cv2.morphologyEx(image, cv2.MORPH_OPEN, ones(size, uint8))
159+
return cv2.morphologyEx(image, cv2.MORPH_OPEN, brick(size))
158160
# image = r_erosion(image,size,origin=origin)
159161
# return r_dilation(image,size,origin=origin)
160162

161163
@checks(GRAYSCALE,uintpair)
162164
def rg_closing(image,size,origin=0):
163165
"""Grayscale closing using fast OpenCV.morphologyEx."""
164-
return cv2.morphologyEx(image, cv2.MORPH_CLOSE, ones(size, uint8))
166+
return cv2.morphologyEx(image, cv2.MORPH_CLOSE, brick(size))
165167
# image = r_dilation(image,size,origin=0)
166168
# return r_erosion(image,size,origin=-1)
167169

@@ -196,7 +198,7 @@ def find_label_contours(labels):
196198
contours[label] = find_contours(labels==label)
197199
return contours
198200

199-
@checks(SEGMENTATION)
201+
@checks(ALL(SEGMENTATION,ANONNEG))
200202
def spread_labels(labels,maxdist=9999999):
201203
"""Spread the given labels to the background."""
202204
#distances,features = morphology.distance_transform_edt(labels==0,return_distances=1,return_indices=1)
@@ -206,9 +208,21 @@ def spread_labels(labels,maxdist=9999999):
206208
return labels
207209
distances,indexes = cv2.distanceTransformWithLabels(array(labels==0,uint8),cv2.DIST_L2,cv2.DIST_MASK_PRECISE,labelType=cv2.DIST_LABEL_PIXEL)
208210
spread = labels[where(labels>0)][indexes-1]
211+
if maxdist is None:
212+
return spread, distances
209213
spread *= (distances<maxdist)
210214
return spread
211215

216+
@checks(SEGMENTATION)
217+
def dist_labels(labels):
218+
"""Get the distance transformation of the segments."""
219+
if not labels.any():
220+
return labels
221+
return cv2.distanceTransform(labels,
222+
distanceType=cv2.DIST_L1,
223+
maskSize=3,
224+
dstType=cv2.CV_8U)
225+
212226
@checks(ABINARY2,ABINARY2)
213227
def keep_marked(image,markers):
214228
"""Given a marker image, keep only the connected components

0 commit comments

Comments
 (0)