def analyze(tgt, idx):
print "%d :==========================" % idx
tgt = binarize(tgt)
if should_invert(tgt):
tgt = invert(tgt)
regions = regionprops(label(tgt))
for region in regions:
print "-----"
print "area:%s" % region.area # ???????????
print "centroid:" + str(region.centroid) # ????
print "perimeter:%s" % region.perimeter # ??
print "euler:%s" % region.euler_number
print "circularity:%s" % (region.area / region.perimeter**2)
print "complexity:%s" % (region.perimeter**2 / region.area)
python类label()的实例源码
def analyze(tgt, idx):
print "%d :==========================" % idx
tgt = binarize(tgt)
if should_invert(tgt):
tgt = invert(tgt)
regions = regionprops(label(tgt))
for region in regions:
print "-----"
print "area:%s" % region.area # ???????????
print "centroid:" + str(region.centroid) # ????
print "perimeter:%s" % region.perimeter # ??
print "euler:%s" % region.euler_number
print "circularity:%s" % (region.area / region.perimeter**2)
print "complexity:%s" % (region.perimeter**2 / region.area)
def layout_seg(image, page_text):
if page_text.endswith(u'\r\n'):
separator = u'\r\n'
else:
separator = u'\n'
texts = page_text.rstrip(separator).split(separator)
bw = binarisation(image)
image_height, image_width = bw.shape
bw = (1 - bw).astype('ubyte')
label_image = label(bw, connectivity=2)
line_region_lst = get_line_region_lst(label_image)
region_lst = []
line_idx = 0
text_len = len(texts)
page_bar_no = texts[0].strip()
for i in range(1, text_len):
text = texts[i].rstrip()
if text:
region_seg(image, bw, image_height, page_bar_no, i, line_region_lst[line_idx], text, region_lst)
line_idx = line_idx + 1
else:
left = line_region_lst[line_idx].right
right = line_region_lst[line_idx-1].left
region = {
u'text': text,
u'left': left,
u'right': right,
u'top': 0,
u'bottom': image_height,
u'line_no': i,
u'region_no': 1,
u'page_bar_no': page_bar_no,
}
region_lst.append(region)
return region_lst
def connected_components2bboxes(labels):
"""Returns a dictionary of bounding boxes (upper left c., lower right c.)
for each label.
>>> labels = [[0, 0, 1, 1], [2, 0, 0, 1], [2, 0, 0, 0], [0, 0, 3, 3]]
>>> bboxes = connected_components2bboxes(labels)
>>> bboxes[0]
[0, 0, 4, 4]
>>> bboxes[1]
[0, 2, 2, 4]
>>> bboxes[2]
[1, 0, 3, 1]
>>> bboxes[3]
[3, 2, 4, 4]
:param labels: The output of cv2.connectedComponents().
:returns: A dict indexed by labels. The values are quadruplets
(xmin, ymin, xmax, ymax) so that the component with the given label
lies exactly within labels[xmin:xmax, ymin:ymax].
"""
bboxes = {}
for x, row in enumerate(labels):
for y, l in enumerate(row):
if l not in bboxes:
bboxes[l] = [x, y, x+1, y+1]
else:
box = bboxes[l]
if x < box[0]:
box[0] = x
elif x + 1 > box[2]:
box[2] = x + 1
if y < box[1]:
box[1] = y
elif y + 1 > box[3]:
box[3] = y + 1
return bboxes
def compute_connected_components(image):
labels = label(image, background=0)
cc = int(labels.max())
bboxes = connected_components2bboxes(labels)
return cc, labels, bboxes
def _get_lineSeg_Disp_all(self):
# draw mask on img_arr with foreground painted in its "color_fill" (only display cur_line_type2 lineSeg)
## always draw on original_sized arr
img_arr = self.ori_img.copy()
# self.final_BI = np.zeros(img_arr.shape, np.uint8) if self.final_BI is None else self.final_BI
bi_t = np.zeros(self.final_BI.shape, np.uint8)
# print "img_arr.shape = {}".format(img_arr.shape)
# display all types in one img
for lineType in self.line_types.keys():
if "label" not in self.line_types[lineType].keys():
continue
# print ">>>>>>>>>>>>> ", lineType
label = self.line_types[lineType]["label"]
color_fill = self.line_types[lineType]["color_fill"][0]
bi_t[:] = 0
bi_t[self.final_BI == label] = 255
### 1) visualize line type
if np.count_nonzero(bi_t) > 0:
# Image.fromarray(bi_t).show()
bi_t_img = Image.fromarray(bi_t)
img = Image.fromarray(img_arr)
draw = ImageDraw.Draw(img, mode='RGB')
draw.bitmap((0, 0), bi_t_img, fill=tuple(color_fill))
img_arr = np.array(img)
lineSeg_Disp = img_arr
# Image.fromarray(lineSeg_Disp).show()
return lineSeg_Disp
def set_seg_config(self, ref_pic, label_type, seg_method):
"""
This function is used for initializing the segmentation part
according to the label_type and seg_method
"""
self.set_reference_pic(ref_pic)
self.label_type = label_type
self.load_label_info(label_type)
# self.load_line_info()
self.seg_method = seg_method
self.init_seg() # dont use label_type; init seg_arr with ignored label
self.update_disp() # dont use label_type
self.update() # dont use label_type
# def update(self):
# super(SegPic, self).update()
def selectBlob(self, mouseXY):
# Detect blobs on binary tmp_BI (0, 255)
tmp_BI = np.zeros(self.final_BI.shape, np.uint8)
tmp_BI[self.final_BI == self.cur_line_label] = 255
all_labels = measure.label(tmp_BI, background=0)
props = measure.regionprops(all_labels, tmp_BI)
coord_RC = []
coord_XY = []
rect = [] # [min_r, max_r, min_c, max_c]
for prop in props:
## bbox: tuple (min_r, min_c, max_r, max_c)
min_r, min_c, max_r, max_c = prop.bbox
if mouseXY[0] >= min_c and mouseXY[0] <= max_c and mouseXY[1] >= min_r and mouseXY[1] <= max_r:
print "got one blob !!!!"
coord_RC = prop.coords.tolist()
rect = [min_r, max_r, min_c, max_c]
break
## [row, col] to [x, y]
for RC in coord_RC:
coord_XY.append([RC[1], RC[0]])
# print coord_XY
return coord_XY, rect
def update_segvalue(self, selected_index, label):
"""
1) mark selected_index with current label
1) update img_arr according to seg_disp and label
2) mark_boundaries on img_arr
3) reset collect_points
"""
self.seg_arr.ravel()[
selected_index] = label # 1) mark selected_index with current label
tmp = self.seg_disp.reshape((-1, 3)) # 3 cols: R, G, B
# different color represents diff labels
tmp[selected_index, :] = self.color_map[label]
self.seg_disp = tmp.reshape(self.seg_disp.shape)
self.img_arr = np.array(self.ref_pic.img_arr *
(1 -
self.alpha) +
self.alpha *
self.seg_disp, dtype=np.uint8)
self.img_arr = np.array(
mark_boundaries(
self.img_arr,
self.seg_index) * 255,
dtype=np.uint8)
self.collect_points = [] # reset collect_points[]
self.update()
def _ID2label_dict_add(self, ID, label):
"""
add pair ID - label
"""
print "@@@@@@@@@@@ [_ID2label_dict_add]>> ID: {}; label: {}".format(ID, label)
print "1 self.line_ID2label: ", self.line_ID2label
unique, counts = np.unique(self.final_ID, return_counts=True)
unique_label, counts_label = np.unique(self.final_BI, return_counts=True)
final_ID_cnt = dict(zip(unique, counts))
final_BI_cnt = dict(zip(unique_label, counts_label))
print "final_ID_cnt>>>>>>>: ", final_ID_cnt
print "final_BI_cnt>>>>>>>: ", final_BI_cnt
if ID not in final_ID_cnt.keys():
print ">>> try to add pair, but ID: {} not in final_ID".format(ID)
return
if label not in final_BI_cnt.keys():
print ">>> try to add pair, but label: {} not in final_BI".format(label)
return
if ID not in self.line_ID2label.keys():
if ID not in final_ID_cnt.keys():
print ">>> try to add pair, but ID: {} not in final_ID".format(ID)
else:
self.line_ID2label[ID] = [label]
elif label not in self.line_ID2label[ID]:
if label not in final_BI_cnt.keys():
print ">>> try to add pair, but label: {} not in final_BI".format(label)
else:
self.line_ID2label[ID].append(label)
print "2 >>>>>>>>>>>>>>>>>>>: ", self.line_ID2label
def do_segmentation(self):
# Apply segmentation and update the display
"""
1) Do pre-segmentation (2 methods available)
2) seg_index -- init with pre-segmentation result
3) seg_disp -- each pixel is colored according to its class label
4.1) img_arr -- on ori_img, color each pixel according to seg_disp
4.2) img_arr -- mark boundaries of segmentations according to seg_index
"""
ori_img = self.ref_pic.img_arr
sp = self.seg_params
if self.seg_method == 'slic':
n_segments, compactness, sigma = np.int(
sp[0]), np.int(sp[1]), sp[2]
self.seg_index = slic(
ori_img,
n_segments=n_segments,
compactness=compactness,
sigma=sigma)
elif self.seg_method == 'felzenszwalb':
scale, min_size, sigma = np.int(sp[0]), np.int(sp[1]), sp[2]
self.seg_index = felzenszwalb(
ori_img, scale=scale, min_size=min_size, sigma=sigma)
r, c = self.seg_arr.shape
# color_map -- one row; color_map[2] -- color of class label_2
# seg_disp -- 3D (r*c*3); seg_disp[r, c] -- color of pixel (r, c) on
# img according to its label
self.seg_disp = self.color_map[self.seg_arr.ravel()].reshape((r, c, 3))
# img_arr -- color the ori_img with the result of pixelwise labeling
self.img_arr = np.array(
ori_img * (1 - self.alpha) + self.alpha * self.seg_disp, dtype=np.uint8)
self.img_arr = np.array(
mark_boundaries(
self.img_arr,
self.seg_index) * 255,
dtype=np.uint8)
self.update()
def get_segmented_lungs(im, plot=False):
# Step 1: Convert into a binary image.
binary = im < -400
# Step 2: Remove the blobs connected to the border of the image.
cleared = clear_border(binary)
# Step 3: Label the image.
label_image = label(cleared)
# Step 4: Keep the labels with 2 largest areas.
areas = [r.area for r in regionprops(label_image)]
areas.sort()
if len(areas) > 2:
for region in regionprops(label_image):
if region.area < areas[-2]:
for coordinates in region.coords:
label_image[coordinates[0], coordinates[1]] = 0
binary = label_image > 0
# Step 5: Erosion operation with a disk of radius 2. This operation is seperate the lung nodules attached to the blood vessels.
selem = disk(2)
binary = binary_erosion(binary, selem)
# Step 6: Closure operation with a disk of radius 10. This operation is to keep nodules attached to the lung wall.
selem = disk(10) # CHANGE BACK TO 10
binary = binary_closing(binary, selem)
# Step 7: Fill in the small holes inside the binary mask of lungs.
edges = roberts(binary)
binary = ndi.binary_fill_holes(edges)
# Step 8: Superimpose the binary mask on the input image.
get_high_vals = binary == 0
im[get_high_vals] = -2000
return im, binary
def connected_component_image(otsu_image):
"""
apply Connected Component Analysis to otsu_image
it is because of detect tissue
choose the label that has largest spces in the image
otsu_image = input image that applied otsu thresholding
max_label = maximum label of components
cnt_label = the number of pix which in certin lebel
result_label = the label which indicate tissue
return tissue image
"""
image_labels = measure.label(otsu_image)
max_label = np.max(image_labels)
cnt_label = 0
result_label = 1
for i in range(1,max_label):
temp = (image_labels == i)
temp = temp.astype(float)
cnt_nonzero = np.count_nonzero(temp)
if cnt_nonzero > cnt_label:
cnt_label = cnt_nonzero
result_label = i
tissue_image = (image_labels == result_label)
tissue_image = tissue_image.astype(float)
return tissue_image
def measure_voxels(labs, ims):
#print("Befpre measure.regionprops, labs & intensity shapes: ", labs.shape, ims.shape)
regprop = measure.regionprops(labs, intensity_image=ims) # probkem here on 20170327
voxel_volume = np.product(RESIZE_SPACING)
areas = [rp.area for rp in regprop] # this is in cubic mm now (i.e. should really be called volume)
volumes = [rp.area * voxel_volume for rp in regprop]
diameters = [2 * (3* volume / (4 * np.pi ))**0.3333 for volume in volumes]
labs_ids = [rp.label for rp in regprop]
#ls = [rp.label for rp in regprop]
max_val = np.max(areas)
max_index = areas.index(max_val)
max_label = regprop[max_index].label
bboxes = [r.bbox for r in regprop]
#max_ls = ls[max_index]
idl = labs == regprop[max_index].label # 400
nodules_pixels = ims[idl]
nodules_hu = pix_to_hu(nodules_pixels)
run_UNNEEDED_code = False
if run_UNNEEDED_code:
nodules_hu_reg = []
for rp in regprop:
idl = labs == rp.label
nodules_pixels = ims[idl]
nodules_hu = pix_to_hu(nodules_pixels)
nodules_hu_reg.append(nodules_hu) # NOTE some are out of interest, i.e. are equal all (or near all) to MAX_BOUND (400)
dfn = pd.DataFrame(
{
#"zcenter": zcenters,
#"ycenter": ycenters,
#"xcenter": xcenters,
"area": areas,
"diameter": diameters,
#"irreg_vol": irreg_vol,
#"irreg_shape": irreg_shape,
#"nodules_hu": nodules_hu_reg,
"bbox": bboxes
},
index=labs_ids)
return dfn
def gen_sample(img, img_mark, rate=0.5, boxsize=10, px_over=5):
"""
Generate samples by splitting the pixel classified image with
provided boxsize
Input
-----
img: np.ndarray
The 2D raw image
img_mark: np.ndarray
The 2D marked image
rate: float
The rate of cavity pixels in the box, belongs to (0,1), default as 0.5
boxsize: integer
Size of the box, default as 10
px_over: integer
Overlapped pixels, default as 5
Output
------
data: np.ndarray
The matrix holding samples, each column represents one sample
label: np.ndarray
Labels with respect to samples, could be 0, 1, and 2.
"""
# Init
rows, cols = img.shape
px_diff = boxsize - px_over
# Number of boxes
box_rows = int(np.round((rows - boxsize - 1) / px_diff)) + 1
box_cols = int(np.round((cols - boxsize - 1) / px_diff)) + 1
# init data and label
data = np.zeros((box_rows * box_cols, boxsize**2))
label = np.zeros((box_rows * box_cols, 1))
# Split
for i in range(box_rows):
for j in range(box_cols):
sample = img[i * px_diff:i * px_diff + boxsize,
j * px_diff:j * px_diff + boxsize]
label_mat = img_mark[i * px_diff:i * px_diff + boxsize,
j * px_diff:j * px_diff + boxsize]
data[i * box_rows + j, :] = sample.reshape((boxsize**2, ))
rate_box = len(np.where(label_mat.reshape((boxsize**2,)) == 1)[0])
# label[i*box_rows+j,0] = np.where(hist==hist.max())[0][0]
rate_box = rate_box / boxsize**2
if rate_box >= rate:
label[i * box_rows + j, 0] = 1
else:
label[i * box_rows + j, 0] = 0
return data, label
def gen_sample_multi(img, img_mark, rate=0.2, boxsize=10, px_over=5):
"""
Generate samples by splitting the pixel classified image with
provided boxsize
Input
-----
img: np.ndarray
The 2D raw image
img_mark: np.ndarray
The 2D marked image
rate: float
The rate of cavity pixels in the box, belongs to (0,1), default as 0.5
boxsize: integer
Size of the box, default as 10
px_over: integer
Overlapped pixels, default as 5
Output
------
data: np.ndarray
The matrix holding samples, each column represents one sample
label: np.ndarray
Labels with respect to samples, could be 0, 1, and 2.
"""
# Init
rows, cols = img.shape
px_diff = boxsize - px_over
# Number of boxes
box_rows = int(np.round((rows - boxsize - 1) / px_diff)) + 1
box_cols = int(np.round((cols - boxsize - 1) / px_diff)) + 1
# init data and label
data = np.zeros((box_rows * box_cols, boxsize**2))
label = np.zeros((box_rows * box_cols, 1))
# Split
for i in range(box_rows):
for j in range(box_cols):
sample = img[i * px_diff:i * px_diff + boxsize,
j * px_diff:j * px_diff + boxsize]
label_mat = img_mark[i * px_diff:i * px_diff + boxsize,
j * px_diff:j * px_diff + boxsize]
data[i * box_rows + j, :] = sample.reshape((boxsize**2, ))
# get label (modified: 2017/02/22)
mask = label_mat.reshape((boxsize**2,))
mask0 = len(np.where(mask == 0)[0])
mask1 = len(np.where(mask == 127)[0])
mask2 = len(np.where(mask == 255)[0])
try:
r = mask1 / (len(mask))
except ZeroDivisionError:
r = 1
if r >= rate:
label[i * box_rows + j, 0] = 1
else:
mask_mat = np.array([mask0, mask1, mask2])
l = np.where(mask_mat == mask_mat.max())[0][0]
# label[i*box_rows+j,0] = np.where(hist==hist.max())[0][0]
label[i * box_rows + j, 0] = l
return data, label
def segment_lung_mask(image, speedup=4):
def largest_label_volume(im, bg=-1):
vals, counts = np.unique(im, return_counts=True)
counts = counts[vals != bg]
vals = vals[vals != bg]
if len(counts) > 0:
return vals[np.argmax(counts)]
else:
return None
if speedup>1:
smallImage = transform.downscale_local_mean(image,(1,speedup,speedup));
else:
smallImage = image;
# not actually binary, but 1 and 2.
# 0 is treated as background, which we do not want
binary_image = np.array((smallImage < -320) & (smallImage>-1400), dtype=np.int8)
#return binary_image;
for i, axial_slice in enumerate(binary_image):
axial_slice = 1-axial_slice
labeling = measure.label(axial_slice)
l_max = largest_label_volume(labeling, bg=0)
if l_max is not None: #This slice contains some lung
binary_image[i][(labeling!=l_max)] = 1
# Remove other air pockets insided body
labels = measure.label(binary_image, background=0)
m = labels.shape[0]//2;
check_layers = labels[m-12:m+20:4,:,:];
l_max = largest_label_volume(check_layers, bg=0)
while l_max is not None: # There are air pockets
idx = np.where(check_layers==l_max);
ii = np.vstack(idx[1:]).flatten();
if np.max(ii)>labels.shape[1]-24/speedup or np.min(ii)<24/speedup:
binary_image[labels==l_max] = 0;
labels = measure.label(binary_image, background=0)
m = labels.shape[0]//2;
check_layers = labels[m-12:m+20:4,:,:];
l_max = largest_label_volume(check_layers, bg=0)
else:
binary_image[labels != l_max] = 0
break
if speedup<=1:
return binary_image
else:
res = np.zeros(image.shape,dtype=np.uint8);
for i,x in enumerate(binary_image):
orig = np.copy(x);
x = binary_dilation(x,disk(5))
x = binary_erosion(x,disk(5))
x = np.logical_or(x,orig)
y = transform.resize(x*1.0,image.shape[1:3]);
res[i][y>0.5]=1
return res;
def iter_blob_extremes(image, n=5):
original_shape = image.shape[::-1]
if max(original_shape) < 2000:
size = (500, 500)
y_scale = original_shape[0] / 500
x_scale = original_shape[1] / 500
else:
size = (1000, 1000)
y_scale = original_shape[0] / 1000
x_scale = original_shape[1] / 1000
img = resize(image, size)
bimg = gaussian_filter(img, sigma=1.0)
bimg = threshold_adaptive(bimg, 20, offset=2/255)
bimg = -bimg
bimg = ndi.binary_fill_holes(bimg)
label_image = label(bimg, background=False)
label_image += 1
regions = regionprops(label_image)
regions.sort(key=attrgetter('area'), reverse=True)
iter_n = 0
for region in regions:
try:
iter_n += 1
if iter_n > n:
break
# Skip small images
if region.area < int(np.prod(size) * 0.05):
continue
coords = get_contours(add_border(label_image == region.label,
size=label_image.shape,
border_size=1,
background_value=False))[0]
coords = np.fliplr(coords)
top_left = sorted(coords, key=lambda x: np.linalg.norm(np.array(x)))[0]
top_right = sorted(coords, key=lambda x: np.linalg.norm(np.array(x) - [img.shape[1], 0]))[0]
bottom_left = sorted(coords, key=lambda x: np.linalg.norm(np.array(x) - [0, img.shape[0]]))[0]
bottom_right = sorted(coords, key=lambda x: np.linalg.norm(np.array(x) - [img.shape[1], img.shape[0]]))[0]
scaled_extremes = [(int(x[0] * y_scale), int(x[1]*x_scale)) for x in (top_left, top_right, bottom_left, bottom_right)]
yield scaled_extremes
except Exception:
pass
raise SudokuExtractError("No suitable blob could be found.")
def prob_heatmap_features(phm, cutoff, k=1, nb_cls=3):
fea_list = []
if phm is None: # deal with missing view.
for _ in xrange(nb_cls - 1): # phms depending on the # of cls.
fea = {'nb_regions': np.nan, 'total_area': np.nan,
'global_max_intensity': np.nan}
for j in xrange(k):
reg_fea = {
'area': np.nan, 'area_ratio': np.nan, 'area_ratio2': np.nan,
'eccentricity': np.nan, 'eig1': np.nan, 'eig2': np.nan,
'equivalent_diameter': np.nan, 'euler_number': np.nan,
'extent': np.nan,
'major_axis_length': np.nan, 'max_intensity': np.nan,
'mean_intensity': np.nan, 'minor_axis_length': np.nan,
'orientation': np.nan, 'perimeter': np.nan,
'solidity': np.nan,
}
for key in reg_fea.keys():
new_key = 'top' + str(j+1) + '_' + key
reg_fea[new_key] = reg_fea.pop(key)
fea.update(reg_fea)
fea_list.append(fea)
return fea_list
for i in xrange(1, nb_cls):
phm_ = phm[:,:,i]
hm_bin = np.zeros_like(phm_, dtype='uint8')
hm_bin[phm_ >= cutoff] = 255
hm_label = label(hm_bin)
props = regionprops(hm_label, phm_)
fea = {
'nb_regions':len(props),
'total_area':total_area(props),
'global_max_intensity':global_max_intensity(props),
}
nb_reg = min(k, len(props))
idx = topK_region_idx(props, k)
for j,x in enumerate(idx):
reg_fea = region_features(props[x])
for key in reg_fea.keys():
new_key = 'top' + str(j+1) + '_' + key
reg_fea[new_key] = reg_fea.pop(key)
fea.update(reg_fea)
for j in xrange(nb_reg, k):
reg_fea = region_features()
for key in reg_fea.keys():
new_key = 'top' + str(j+1) + '_' + key
reg_fea[new_key] = reg_fea.pop(key)
fea.update(reg_fea)
fea_list.append(fea)
return fea_list
def get_masks(im):
'''
Step 1: Convert into a binary image.
'''
print('step1')
binary = im < 604
# plt.imshow(binary,cmap=plt.cm.gray)
# plt.show()
'''
Step 2: Remove the blobs connected to the border of the image.
'''
print('step2')
cleared = clear_border(binary)
# plt.imshow(cleared,cmap=plt.cm.gray)
# plt.show()
'''
Step 3: Label the image.
'''
print('step3')
label_image = label(cleared)
# plt.imshow(label_image,cmap=plt.cm.gray)
# plt.show()
'''
Step 4: Keep the labels with 2 largest areas.
'''
print('step4')
areas = [r.area for r in regionprops(label_image)]
areas.sort()
if len(areas) > 2:
for region in regionprops(label_image):
if region.area < 10 and region.area > 3:
print(region.centroid,region.area)
# print(region.area)
centroid = region.centroid
plot_im(im,centroid)
# label_image[int(centroid[0]),int(centroid[1])] = 1000
# for coordinates in region.coords:
# label_image[coordinates[0], coordinates[1]] = 0
# binary = label_image > 999
# plt.imshow(binary,cmap=plt.cm.gray)
# plt.show()
'''
Step 5: Erosion operation with a disk of radius 2. This operation is
seperate the lung nodules attached to the blood vessels.
'''
# print('step5')
# selem = disk(2)
# binary = binary_erosion(binary, selem)
# plt.imshow(binary,cmap=plt.cm.gray)
# plt.show()