Skip to content

Commit f22ef8a

Browse files
author
yxdragon
committed
blog detect
1 parent 0e3be4c commit f22ef8a

File tree

8 files changed

+230
-21
lines changed

8 files changed

+230
-21
lines changed

imagepy/menus/Analysis/label_plg.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"""
66
import numpy as np
77
from scipy.ndimage import label, generate_binary_structure
8+
from skimage.segmentation import find_boundaries
89
from imagepy import IPy
910
from imagepy.core import ImagePlus
1011
from imagepy.core.engine import Filter, Simple
@@ -27,7 +28,27 @@ def run(self, ips, imgs, para = None):
2728
lab, n = label(imgs[i], strc, output = np.int32)
2829
labels.append(lab)
2930
IPy.show_img(labels, ips.title+'-label')
31+
32+
class Boundaries(Simple):
33+
title = 'Mark Boundaries'
34+
note = ['8-bit', '16-bit','int']
35+
para = {'slice':False, 'mode':'outer', 'con':'4-Connect'}
36+
view = [(list, 'con', ['4-Connect','8-Connect'], str, 'Structure', 'connect'),
37+
(list, 'mode', ['thick', 'inner', 'outer', 'subpixel'], str, 'mode', ''),
38+
(bool, 'slice', 'slice')]
3039

40+
def run(self, ips, imgs, para = None):
41+
if not para['slice']: imgs = [ips.img]
42+
labels = []
43+
for i in range(len(imgs)):
44+
self.progress(i, len(imgs))
45+
con = 1 if para['con']=='4-Connect' else 2
46+
bound = find_boundaries(imgs[i], con, para['mode'])
47+
bound.dtype = np.uint8
48+
bound *= 255
49+
labels.append(bound)
50+
IPy.show_img(labels, ips.title+'-boundary')
51+
3152
class Render(Simple):
3253
title = 'Label Render'
3354
note = ['8-bit', '16-bit', 'int']
@@ -36,7 +57,7 @@ class Render(Simple):
3657
(int, 'colors', (4, 255), 0, 'colors', 'n'),
3758
(bool, 'back', 'background'),
3859
(bool, 'slice', 'slice')]
39-
60+
4061
def run(self, ips, imgs, para = None):
4162
if not para['slice']: imgs = [ips.img]
4263
print(para)
@@ -57,4 +78,4 @@ def run(self, ips, imgs, para = None):
5778
ips.range = (0, para['colors'])
5879
IPy.show_ips(ips)
5980

60-
plgs = [Label, Render]
81+
plgs = [Label, Boundaries, Render]

imagepy/menus/File/Samples Local/samples_plgs.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,20 @@ def __init__(self, title):
1313

1414
def run(self, para = None):
1515
img = self.data()
16-
if img.dtype != np.uint8:
17-
img = img.astype(np.uint8)
16+
if isinstance(img, tuple):
17+
return IPy.show_img(list(img), self.title)
18+
if img.dtype == np.bool:
19+
img.dtype = np.uint8
20+
img *= 255
1821
IPy.show_img([img], self.title)
1922

2023
def __call__(self):
2124
return self
2225

23-
datas = ['face', 'ascent', '-', 'page', 'astronaut', 'horse', 'camera',
24-
'coffee', 'hubble_deep_field', 'coins', 'immunohistochemistry', 'moon']
26+
datas = ['face', 'ascent', '-', 'binary_blobs', 'brick', 'astronaut',
27+
'camera', 'cell', 'checkerboard', 'chelsea', 'clock', 'coffee', 'coins',
28+
'colorwheel', 'grass', 'gravel', 'horse', 'hubble_deep_field',
29+
'immunohistochemistry', 'microaneurysms', 'moon', 'page',
30+
'text', 'retina', 'rocket', 'rough_wall', 'shepp_logan_phantom', 'stereo_motorcycle']
2531

2632
plgs = [i if i=='-' else Data(i) for i in datas]

imagepy/menus/Process/Binary/binary_plgs.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import numpy as np
1111
from imagepy.core.engine import Filter
1212
from skimage.morphology import convex_hull_object
13+
from skimage.segmentation import clear_border
1314

1415
class Closing(Filter):
1516
"""Closing: derived from imagepy.core.engine.Filter """
@@ -82,13 +83,20 @@ def run(self, ips, snap, img, para = None):
8283
ndimg.binary_fill_holes(snap, output=img)
8384
img *= 255
8485

86+
class ClearBorder(Filter):
87+
title = 'Clear Border'
88+
note = ['8-bit', 'auto_msk', 'auto_snap']
89+
90+
def run(self, ips, snap, img, para = None):
91+
clear_border(img, in_place=True)
92+
93+
8594
class Convex(Filter):
8695
title = 'Binary ConvexHull'
8796
note = ['8-bit', 'auto_msk', 'auto_snap']
8897

89-
#process
9098
def run(self, ips, snap, img, para = None):
9199
img[convex_hull_object(snap)] = 255
92100

93101

94-
plgs = [Dilation, Erosion, '-', Closing, Opening, '-', Outline, FillHoles, Convex]
102+
plgs = [Dilation, Erosion, '-', Closing, Opening, '-', Outline, FillHoles, ClearBorder, Convex]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
catlog = ['corner_plgs', '-', 'edge_plgs']
1+
catlog = ['edge_plgs', '-', 'corner_plgs', '-', 'ridge_plgs', '-', 'blob_plgs']
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
from imagepy import IPy
2+
import numpy as np
3+
from imagepy.core.engine import Simple
4+
from skimage.feature import blob_dog, blob_doh, blob_log
5+
from imagepy.core.mark import GeometryMark
6+
import pandas as pd
7+
8+
class Dog(Simple):
9+
title = 'Blob Dog'
10+
note = ['all', 'preview']
11+
para = {'min_sigma':1, 'max_sigma':50, 'sigma_ratio':1.6, 'threshold':0.1,
12+
'overlap':0.5, 'exclude_border':False, 'showid':True, 'slice':False}
13+
14+
view = [(int, 'min_sigma', (1, 50), 0, 'min', 'sigma'),
15+
(int, 'max_sigma', (1, 50), 0, 'max', 'sigma'),
16+
(float, 'sigma_ratio', (1.3, 5), 1, 'ratio', '1.3~5'),
17+
(float, 'threshold', (0.1, 10), 1, 'threshold', '0.1~10'),
18+
(float, 'overlap', (0, 10), 1, 'overlap', ''),
19+
(bool, 'exclude_border', 'exclude border'),
20+
(bool, 'showid', 'show id on image'),
21+
(bool, 'slice', 'slice')]
22+
23+
def preview(self, ips, para):
24+
grayimg = ips.img if ips.img.ndim==2 else ips.img.mean(axis=-1)
25+
grayimg /= grayimg.max()
26+
pts = blob_dog(grayimg, min_sigma=para['min_sigma'], max_sigma=para['max_sigma'],
27+
sigma_ratio=para['sigma_ratio'], threshold=para['threshold'],
28+
overlap=para['overlap'], exclude_border=para['exclude_border'])
29+
pts[:,2] *= np.sqrt(2)
30+
ips.mark = GeometryMark({'type':'circles', 'body':pts[:,[1,0,2]]})
31+
32+
def cancel(self, ips): ips.mark = None
33+
34+
def run(self, ips, imgs, para = None):
35+
if not para['slice']:imgs = [ips.img]
36+
37+
data, sid, fid, mark = [], [], [], {'type':'layers', 'body':{}}
38+
39+
for i in range(len(imgs)):
40+
grayimg = imgs[i] if imgs[i].ndim==2 else imgs[i].mean(axis=-1)
41+
grayimg /= grayimg.max()
42+
pts = blob_dog(grayimg, min_sigma=para['min_sigma'], max_sigma=para['max_sigma'],
43+
sigma_ratio=para['sigma_ratio'], threshold=para['threshold'],
44+
overlap=para['overlap'], exclude_border=para['exclude_border'])
45+
pts[:,2] *= np.sqrt(2)
46+
sid.extend([i]*len(pts))
47+
fid.extend(range(1, len(pts)+1))
48+
data.append(pts)
49+
50+
layer = {'type':'layer', 'body':[{'type':'circles', 'body':pts[:,[1,0,2]]}]}
51+
if para['showid']:
52+
layer['body'].append({'type':'texts', 'body':[
53+
(x,y,'id=%d'%i) for (x,y),i in zip(pts[:,1::-1], fid)]})
54+
mark['body'][i] = layer
55+
56+
ips.mark = GeometryMark(mark)
57+
df = pd.DataFrame(np.vstack(data)*ips.unit[0], columns = ['X', 'Y', 'R'])
58+
df.insert(0, 'FID', fid)
59+
if para['slice']: df.insert(o, 'SliceID', sid)
60+
IPy.show_table(df, ips.title+'-dogblob')
61+
62+
class Doh(Simple):
63+
title = 'Blob Doh'
64+
note = ['all', 'preview']
65+
para = {'min_sigma':1, 'max_sigma':30, 'num_sigma':10, 'threshold':0.01,
66+
'overlap':0.5, 'log_scale':False, 'showid':True, 'slice':False}
67+
68+
view = [(int, 'min_sigma', (1, 50), 0, 'min', 'sigma'),
69+
(int, 'max_sigma', (1, 50), 0, 'max', 'sigma'),
70+
(int, 'num_sigma', (5, 30), 0, 'num', 'sigma'),
71+
(float, 'threshold', (0.01, 1), 2, 'threshold', '0.1~10'),
72+
(float, 'overlap', (0, 10), 1, 'overlap', ''),
73+
(bool, 'log_scale', 'log scale'),
74+
(bool, 'showid', 'show id on image'),
75+
(bool, 'slice', 'slice')]
76+
77+
def preview(self, ips, para):
78+
grayimg = ips.img if ips.img.ndim==2 else ips.img.mean(axis=-1)
79+
grayimg /= grayimg.max()
80+
pts = blob_doh(grayimg, min_sigma=para['min_sigma'], max_sigma=para['max_sigma'],
81+
num_sigma=para['num_sigma'], threshold=para['threshold'],
82+
overlap=para['overlap'], log_scale=para['log_scale'])
83+
ips.mark = GeometryMark({'type':'circles', 'body':pts[:,[1,0,2]]})
84+
85+
def cancel(self, ips): ips.mark = None
86+
87+
def run(self, ips, imgs, para = None):
88+
if not para['slice']:imgs = [ips.img]
89+
90+
data, sid, fid, mark = [], [], [], {'type':'layers', 'body':{}}
91+
92+
for i in range(len(imgs)):
93+
grayimg = imgs[i] if imgs[i].ndim==2 else imgs[i].mean(axis=-1)
94+
grayimg /= grayimg.max()
95+
pts = blob_doh(grayimg, min_sigma=para['min_sigma'], max_sigma=para['max_sigma'],
96+
num_sigma=para['num_sigma'], threshold=para['threshold'],
97+
overlap=para['overlap'], log_scale=para['log_scale'])
98+
99+
sid.extend([i]*len(pts))
100+
fid.extend(range(1, len(pts)+1))
101+
data.append(pts)
102+
103+
layer = {'type':'layer', 'body':[{'type':'circles', 'body':pts[:,[1,0,2]]}]}
104+
if para['showid']:
105+
layer['body'].append({'type':'texts', 'body':[
106+
(x,y,'id=%d'%i) for (x,y),i in zip(pts[:,1::-1], fid)]})
107+
mark['body'][i] = layer
108+
109+
ips.mark = GeometryMark(mark)
110+
df = pd.DataFrame(np.vstack(data)*ips.unit[0], columns = ['X', 'Y', 'R'])
111+
df.insert(0, 'FID', fid)
112+
if para['slice']: df.insert(o, 'SliceID', sid)
113+
IPy.show_table(df, ips.title+'-dohblob')
114+
115+
class Log(Simple):
116+
title = 'Blob Log'
117+
note = ['all', 'preview']
118+
para = {'min_sigma':1, 'max_sigma':30, 'num_sigma':10, 'threshold':0.1, 'overlap':0.5,
119+
'log_scale':False, 'showid':True, 'exclude_border':False, 'slice':False}
120+
121+
view = [(int, 'min_sigma', (1, 50), 0, 'min', 'sigma'),
122+
(int, 'max_sigma', (1, 50), 0, 'max', 'sigma'),
123+
(int, 'num_sigma', (5, 30), 0, 'num', 'sigma'),
124+
(float, 'threshold', (0.01, 1), 2, 'threshold', '0.02~1'),
125+
(float, 'overlap', (0, 10), 1, 'overlap', ''),
126+
(bool, 'log_scale', 'log scale'),
127+
(bool, 'exclude_border', 'exclude border'),
128+
(bool, 'showid', 'show id on image'),
129+
(bool, 'slice', 'slice')]
130+
131+
def preview(self, ips, para):
132+
grayimg = ips.img if ips.img.ndim==2 else ips.img.mean(axis=-1)
133+
grayimg /= grayimg.max()
134+
pts = blob_log(grayimg, min_sigma=para['min_sigma'], max_sigma=para['max_sigma'],
135+
num_sigma=para['num_sigma'], threshold=para['threshold'],
136+
overlap=para['overlap'], log_scale=para['log_scale'], exclude_border=para['exclude_border'])
137+
pts[:,2] *= np.sqrt(2)
138+
ips.mark = GeometryMark({'type':'circles', 'body':pts[:,[1,0,2]]})
139+
140+
def cancel(self, ips): ips.mark = None
141+
142+
def run(self, ips, imgs, para = None):
143+
if not para['slice']:imgs = [ips.img]
144+
145+
data, sid, fid, mark = [], [], [], {'type':'layers', 'body':{}}
146+
147+
for i in range(len(imgs)):
148+
grayimg = imgs[i] if imgs[i].ndim==2 else imgs[i].mean(axis=-1)
149+
grayimg /= grayimg.max()
150+
pts = blob_log(grayimg, min_sigma=para['min_sigma'], max_sigma=para['max_sigma'],
151+
num_sigma=para['num_sigma'], threshold=para['threshold'],
152+
overlap=para['overlap'], log_scale=para['log_scale'], exclude_border=para['exclude_border'])
153+
pts[:,2] *= np.sqrt(2)
154+
sid.extend([i]*len(pts))
155+
fid.extend(range(1, len(pts)+1))
156+
data.append(pts)
157+
158+
layer = {'type':'layer', 'body':[{'type':'circles', 'body':pts[:,[1,0,2]]}]}
159+
if para['showid']:
160+
layer['body'].append({'type':'texts', 'body':[
161+
(x,y,'id=%d'%i) for (x,y),i in zip(pts[:,1::-1], fid)]})
162+
mark['body'][i] = layer
163+
164+
ips.mark = GeometryMark(mark)
165+
df = pd.DataFrame(np.vstack(data)*ips.unit[0], columns = ['X', 'Y', 'R'])
166+
df.insert(0, 'FID', fid)
167+
if para['slice']: df.insert(o, 'SliceID', sid)
168+
IPy.show_table(df, ips.title+'-dohblob')
169+
170+
plgs = [Dog, Doh, Log]

imagepy/tools/Draw/aibrush_tol.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ def fill_normal(img, r, c, color, con, tor):
1515
msk &= flood(img[:,:,i], (r, c), connectivity=con, tolerance=tor)
1616
img[msk] = color
1717

18-
def local_brush(img, r, c, color, sigma, msize):
19-
lab = felzenszwalb(img, 1, sigma, msize)
18+
def local_brush(img, back, r, c, color, sigma, msize):
19+
lab = felzenszwalb(back, 1, sigma, msize)
2020
msk = flood(lab, (r, c), connectivity=2)
2121
img[msk] = color
2222

@@ -127,10 +127,11 @@ def global_out_fill(img, r, c, color):
127127
128128
scale and move: | wheel
129129
'''
130+
130131
class Plugin(Tool):
131-
title = 'AI Painter'
132+
title = 'AI Brush'
132133

133-
para = {'win':48, 'tor':10, 'con':'8-connect', 'ms':20, 'r':2, 'color':(255,0,128)}
134+
para = {'win':48, 'tor':10, 'con':'8-connect', 'ms':30, 'r':2, 'color':(255,0,128)}
134135
view = [(int, 'win', (28, 64), 0, 'window', 'size'),
135136
('color', 'color', 'color', 'mark'),
136137
('lab', None, '======= Brush ======='),
@@ -244,19 +245,21 @@ def mouse_move(self, ips, x, y, btn, **key):
244245
sr = (max(0,r-w), min(img.shape[0], r+w))
245246
sc = (max(0,c-w), min(img.shape[1], c+w))
246247
r, c = min(r, w), min(c, w)
247-
clip = img[slice(*sr), slice(*sc)]
248+
backclip = imgclip = img[slice(*sr), slice(*sc)]
249+
if not ips.back is None:
250+
backclip = ips.back.img[slice(*sr), slice(*sc)]
248251

249252
if self.status == 'local_pen':
250-
local_pen(clip, r, c, self.para['r'], color)
253+
local_pen(imgclip, r, c, self.para['r'], color)
251254
if self.status == 'local_brush':
252-
if (clip[r,c] - color).sum()==0: continue
253-
local_brush(clip, r, c, color, 0, self.para['ms'])
255+
if (imgclip[r,c] - color).sum()==0: continue
256+
local_brush(imgclip, backclip, r, c, color, 0, self.para['ms'])
254257
if self.status == 'local_in':
255-
local_in_fill(clip, r, c, self.para['r'], self.pickcolor, color)
258+
local_in_fill(imgclip, r, c, self.para['r'], self.pickcolor, color)
256259
if self.status == 'local_sketch':
257-
local_sketch(clip, r, c, self.para['r'], self.pickcolor, color)
260+
local_sketch(imgclip, r, c, self.para['r'], self.pickcolor, color)
258261
if self.status=='local_out':
259-
local_out_fill(clip, r, c, self.para['r'], self.pickcolor, color)
262+
local_out_fill(imgclip, r, c, self.para['r'], self.pickcolor, color)
260263

261264

262265
ips.mark = self.make_mark(x, y)

imagepy/ui/canvasframe.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ def on_idle(self, event):
132132
self.canvas.set_rg(self.ips.chan_range)
133133

134134
if self.ips.back != None:
135-
self.canvas.set_back(self.ips.back.imgs[self.ips.cur])
135+
self.ips.back.cur = self.ips.cur
136+
self.canvas.set_back(self.ips.back.img)
136137
self.canvas.set_cn(self.ips.back.chan, True)
137138
self.canvas.set_rg(self.ips.back.chan_range, True)
138139
self.canvas.set_lut(self.ips.back.lut, True)

0 commit comments

Comments
 (0)