Skip to content

Commit 0706b08

Browse files
author
yxdragon
committed
connectivity
1 parent 3a9d8f5 commit 0706b08

File tree

3 files changed

+103
-1
lines changed

3 files changed

+103
-1
lines changed

imagepy/ipyalg/graph/connect.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import numpy as np
2+
from numba import jit
3+
from scipy.ndimage import generate_binary_structure
4+
5+
def neighbors(shape, conn=1):
6+
dim = len(shape)
7+
block = generate_binary_structure(dim, conn)
8+
block[tuple([1]*dim)] = 0
9+
idx = np.where(block>0)
10+
idx = np.array(idx, dtype=np.uint8).T
11+
idx = np.array(idx-[1]*dim)
12+
acc = np.cumprod((1,)+shape[::-1][:-1])
13+
return np.dot(idx, acc[::-1])
14+
15+
@jit(nopython=True)
16+
def search(img, nbs):
17+
s, line = 0, img.ravel()
18+
rst = np.zeros((len(line),2), img.dtype)
19+
for i in range(len(line)):
20+
if line[i]==0:continue
21+
for d in nbs:
22+
if line[i+d]==0: continue
23+
if line[i]==line[i+d]: continue
24+
rst[s,0] = line[i]
25+
rst[s,1] = line[i+d]
26+
s += 1
27+
return rst[:s]
28+
29+
def connect(img, conn=1):
30+
buf = np.pad(img, 1, 'constant')
31+
nbs = neighbors(buf.shape, conn)
32+
rst = search(buf, nbs)
33+
if len(rst)==0: return rst
34+
rst.sort()
35+
return np.unique(rst, axis=0)
36+
37+
def mapidx(idx):
38+
dic = {}
39+
for i in np.unique(idx): dic[i] = []
40+
for i,j in idx:
41+
dic[i].append(j)
42+
dic[j].append(i)
43+
return dic
44+
45+
if __name__ == '__main__':
46+
img = np.array([[1,1,1,1,1],
47+
[1,1,2,2,1],
48+
[1,3,0,0,1],
49+
[1,3,1,1,4]])
50+
rst = connect(img, 2)
51+
print(rst)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#
2-
catlog = ['regionprops_plgs', '-', 'statistic_plgs']
2+
catlog = ['regionprops_plgs', 'connect_plg', '-', 'statistic_plgs']
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from imagepy import IPy
2+
import numpy as np
3+
from imagepy.core.engine import Simple
4+
from skimage.measure import regionprops
5+
from imagepy.core.mark import GeometryMark
6+
from scipy.ndimage import label, generate_binary_structure
7+
from imagepy.ipyalg.graph.connect import connect, mapidx
8+
import pandas as pd
9+
10+
# center, area, l, extent, cov
11+
class Plugin(Simple):
12+
title = 'Connective Analysis'
13+
note = ['8-bit', '16-bit', 'int']
14+
para = {'con':'8-connect', 'labled':False, 'slice':False}
15+
view = [(list, 'con', ['4-connect', '8-connect'], str, 'conection', 'pix'),
16+
(bool, 'labled', 'it is a label image'),
17+
(bool, 'slice', 'slice')]
18+
19+
#process
20+
def run(self, ips, imgs, para = None):
21+
if not para['slice']:imgs = [ips.img]
22+
k = ips.unit[0]
23+
24+
titles = ['Slice', 'ID'][0 if para['slice'] else 1:] + ['Center-X','Center-Y', 'N', 'Neighbors']
25+
buf = imgs[0].astype(np.uint32)
26+
data, mark = [], {'type':'layers', 'body':{}}
27+
for i in range(len(imgs)):
28+
if para['labled']: buf = imgs[i]
29+
else: label(imgs[i], generate_binary_structure(2, 1), output=buf)
30+
conarr = connect(buf, 1 if para['con']=='4-connect' else 2)
31+
conmap = mapidx(conarr)
32+
33+
ls = regionprops(buf)
34+
dt = [[i]*len(ls), list(range(1,1+len(ls)))]
35+
36+
if not para['slice']:dt = dt[1:]
37+
38+
layer = {'type':'layer', 'body':[]}
39+
texts = [(i.centroid[::-1])+('id=%d'%i.label,) for i in ls]
40+
lines = [(ls[i-1].centroid[::-1], ls[j-1].centroid[::-1]) for i,j in conarr]
41+
layer['body'].append({'type':'texts', 'body':texts})
42+
layer['body'].append({'type':'lines', 'body':lines})
43+
mark['body'][i] = layer
44+
45+
dt.append([round(i.centroid[1]*k,1) for i in ls])
46+
dt.append([round(i.centroid[0]*k,1) for i in ls])
47+
neibs = [conmap[i.label] if i.label in conmap else [] for i in ls]
48+
dt.extend([[len(i) for i in neibs], neibs])
49+
data.extend(list(zip(*dt)))
50+
ips.mark = GeometryMark(mark)
51+
IPy.show_table(pd.DataFrame(data, columns=titles), ips.title+'-region')

0 commit comments

Comments
 (0)