Skip to content

Commit 5f95de1

Browse files
committed
Changes:
1. Edits in vect_edge and agg_recursion.
1 parent d1d65a8 commit 5f95de1

File tree

2 files changed

+58
-40
lines changed

2 files changed

+58
-40
lines changed

frame_2D_alg/agg_recursion.py

+40-34
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from functools import reduce
55
from frame_blobs import frame_blobs_root, intra_blob_root, imread
66
from comp_slice import comp_latuple, comp_md_
7-
from vect_edge import feedback, comp_node_, comp_link_, sum2graph, get_rim, CH, CG, ave, ave_L, vectorize_root, comp_area, extend_box, val_
7+
from vect_edge import feedback, comp_node_, comp_link_, sum_G_, sum2graph, get_rim, CH, CG, ave, ave_L, vectorize_root, comp_area, extend_box, val_
88
'''
99
Cross-compare and cluster Gs within a frame, potentially unpacking their node_s first,
1010
alternating agglomeration and centroid clustering.
@@ -16,49 +16,60 @@
1616
capitalized vars are summed small-case vars
1717
'''
1818

19-
def cross_comp(root): # breadth-first node_,link_ cross-comp, connect.clustering, recursion
19+
def cross_comp(root, falt=0): # breadth-first node_,link_ cross-comp, connect.clustering, recursion
2020

21-
N_,L_,Et = comp_node_(root.subG_) # cross-comp exemplars, extrapolate to their node_s
21+
N_,L_,Et = comp_node_(root.altG_ if falt else root.node_) # cross-comp exemplars, extrapolate to their node_s
2222
# mfork
2323
if val_(Et, fo=1) > 0:
2424
mlay = CH().add_tree([L.derH for L in L_]); H=root.derH; mlay.root=H; H.Et += mlay.Et; H.lft = [mlay]
2525
pL_ = {l for n in N_ for l,_ in get_rim(n, fd=0)}
2626
if len(pL_) > ave_L:
27-
cluster_N_(root, pL_, fd=0) # nested distance clustering, calls centroid and higher connect.clustering
27+
G_ = cluster_N_(root, pL_, fd=0, falt=falt) # nested distance clustering, calls centroid and higher connect.clustering
2828
# dfork
29-
if val_(Et, mEt=Et, fo=1) > 0: # same root for L_, root.link_ was compared in root-forming for alt clustering
29+
if val_( Et, mEt=Et, fo=1) > 0: # same root for L_, root.link_ was compared in root-forming for alt clustering
3030
for L in L_:
3131
L.extH, L.root, L.Et, L.mL_t, L.rimt, L.aRad, L.visited_ = CH(),root,copy(L.derH.Et), [[],[]], [[],[]], 0,[L]
3232
lN_,lL_,dEt = comp_link_(L_,Et)
3333
if val_(dEt, mEt=Et, fo=1) > 0:
3434
dlay = CH().add_tree([L.derH for L in lL_]); dlay.root=H; H.Et += dlay.Et; H.lft += [dlay]
3535
plL_ = {l for n in lN_ for l,_ in get_rim(n, fd=1)}
3636
if len(plL_) > ave_L:
37-
cluster_N_(root, plL_, fd=1)
38-
37+
cluster_N_(root, plL_, fd=1, falt=falt)
38+
# draft ( i think this should be here? Right after d fork, else G doesn't have altG_ too):
39+
for G in G_:
40+
if G.altG_: # non empty
41+
# cross-comp | sum altG_ -> combined altG before next agg+ cross-comp
42+
if val_(np.sum([alt.Et for alt in G.altG_],axis=0), mEt=G.Et):
43+
cross_comp(G, falt=1) # altG_ will be updated within cluster_N_
44+
else:
45+
# why we need to sum them into single altG here?
46+
G.altG_ = sum_G_([alt for alt in G.altG_])
3947
feedback(root) # add root derH to higher roots derH
4048

41-
def cluster_N_(root, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L.dists
49+
def cluster_N_(root, L_, fd, nest=0, falt=0): # top-down segment L_ by >ave ratio of L.dists
4250

4351
L_ = sorted(L_, key=lambda x: x.dist) # shorter links first
44-
for n in [n for l in L_ for n in l.nodet]: n.fin = 0
4552
_L = L_[0]
4653
N_, et = copy(_L.nodet), _L.derH.Et
4754
L_ = L_[1:]
55+
G_ = [] # this should be outside while loop?
4856
while L_: # longer links
57+
for n in [n for l in L_ for n in l.nodet]: n.fin = 0 # this should be here? Since we may get a same N in a later segment
4958
for i, L in enumerate(L_): # short first
5059
rel_dist = L.dist / _L.dist # >= 1
60+
# there's a problem here
5161
if rel_dist < 1.2 or val_(et)>0 or len(L_[i:]) < ave_L: # ~=dist Ns or either side of L is weak
5262
_L = L; N_ += L.nodet; et += L.derH.Et # last L
5363
else:
5464
i -= 1; break # terminate contiguous-distance segment
55-
G_ = []
65+
5666
max_dist = _L.dist
5767
for N in {*N_}: # cluster current distance segment
5868
_eN_, node_,link_, et, = [N], [],[], np.zeros(4)
5969
while _eN_:
6070
eN_ = []
6171
for eN in _eN_: # cluster rim-connected ext Ns, all in root Gt
72+
if eN.fin: continue # this is missed out?
6273
node_+=[eN]; eN.fin = 1 # all rim
6374
for L,_ in get_rim(eN, fd):
6475
if L not in link_: # if L.derH.Et[0]/ave * n.extH m/ave or L.derH.Et[0] + n.extH m*.1: density?
@@ -69,11 +80,19 @@ def cluster_N_(root, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L.
6980
G_ += [sum2graph(root, [list({*node_}),list({*link_}), et], fd, max_dist, nest)]
7081
# cluster node roots if nest else nodes
7182
nest += 1
72-
if fd: root.link_ = G_ # replace with current-dist clusters
73-
else: root.node_ = G_
7483
L_ = L_[i+1:] # get longer links if any, may connect current-dist clusters
7584
N_ = []
76-
cluster_C_(root)
85+
86+
# below should be outside while loop? G_ will be updated only when the loops end
87+
if falt:
88+
if not fd: root.altG_ = G_ # for d fork, no further update since we do not have alt_link_?
89+
else:
90+
if fd: root.link_ = G_ # replace with current-dist clusters
91+
else: root.node_ = G_
92+
cluster_C_(root, falt=falt)
93+
94+
return G_
95+
7796

7897
''' Hierarchical clustering should alternate between two phases: generative via connectivity and compressive via centroid.
7998
@@ -86,15 +105,15 @@ def cluster_N_(root, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L.
86105
So connectivity clustering is a generative learning phase, forming new derivatives and structured composition levels,
87106
while centroid clustering is a compressive phase, reducing multiple similar comparands to a single exemplar. '''
88107

89-
def cluster_C_(graph):
108+
def cluster_C_(graph, falt=0):
90109

91110
def centroid(dnode_, node_, C=None): # sum|subtract and average Rim nodes
92111

93112
if C is None:
94113
C = CG(); C.L = 0; C.M = 0 # setattr summed len node_ and match to nodes
95114
for n in dnode_:
96115
s = n.sign; n.sign=1 # single-use sign
97-
C.Et += n.Et * s; C.rng = n.rng * s; C.aRad += n.aRad * s
116+
C.Et += n.Et * s; C.aRad += n.aRad * s
98117
C.L += len(n.node_) * s
99118
C.latuple += n.latuple * s
100119
C.vert += n.vert * s
@@ -155,7 +174,7 @@ def centroid_cluster(N): # refine and extend cluster with extN_
155174
return N # keep seed node
156175

157176
# get representative centroids of complemented Gs: mCore + dContour, initially in unpacked edges
158-
N_ = sorted([N for N in graph.node_ if any(N.Et)], key=lambda n: n.Et[0], reverse=True)
177+
N_ = sorted([N for N in (graph.altG_ if falt else graph.node_) if any(N.Et)], key=lambda n: n.Et[0], reverse=True)
159178
G_ = []
160179
for N in N_:
161180
N.sign, N.m, N.fin = 1, 0, 0 # setattr: C update sign, inclusion val, prior C inclusion flag
@@ -166,33 +185,20 @@ def centroid_cluster(N): # refine and extend cluster with extN_
166185
else: # the rest of N_ M is lower
167186
G_ += [N for N in N_[i:] if not N.fin]
168187
break
169-
# draft:
170-
for G in G_:
171-
# cross-comp | sum altG_ -> combined altG before next agg+ cross-comp
172-
if val_(np.sum([alt.Et for alt in G.altG_]), mEt=G.Et):
173-
G.altG_ = cross_comp(G, G.altG_)
174-
else:
175-
G.altG_ = reduce(sum_G_, [alt for alt in G.altG_])
176-
177-
graph.node_ = G_ # mix of Ns and Cs: exemplars of their network?
188+
189+
if falt: graph.altG_ = G_
190+
else: graph.node_ = G_ # mix of Ns and Cs: exemplars of their network?
178191
if len(G_) > ave_L:
179-
cross_comp(graph) # selective connectivity clustering between exemplars, extrapolated to their node_
192+
cross_comp(graph, falt) # selective connectivity clustering between exemplars, extrapolated to their node_
180193

181-
def sum_G_(node_):
182-
G = CG()
183-
for n in node_:
184-
G.rng = n.rng; G.latuple += n.latuple; G.vert += n.vert; G.aRad += n.aRad; G.box = extend_box(G.box, n.box)
185-
if n.derH: G.derH.add_tree(n.derH, root=G)
186-
if n.extH: G.extH.add_tree(n.extH)
187-
return G
188194

189195
if __name__ == "__main__":
190196
image_file = './images/raccoon_eye.jpeg'
191197
image = imread(image_file)
192198
frame = frame_blobs_root(image)
193199
intra_blob_root(frame)
194200
vectorize_root(frame)
195-
if frame.subG_: # converted edges
201+
if frame.node_: # converted edges
196202
G_ = []
197203
for edge in frame.node_:
198204
cluster_C_(edge) # no cluster_C_ in vect_edge

frame_2D_alg/vect_edge.py

+18-6
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def vectorize_root(frame):
215215
if len(G_) > ave_L:
216216
cluster_edge(edge); frame.node_ += [edge]; frame.derH.add_tree(edge.derH)
217217
# add altG: summed converted adj_blobs of converted edge blob
218-
# if len(edge.subG_) > ave_L: agg_recursion(edge) # unlikely
218+
# if len(edge.node_) > ave_L: agg_recursion(edge) # unlikely
219219

220220
def val_(Et, mEt=[], fo=0):
221221
m, d, n, o = Et
@@ -230,7 +230,7 @@ def cluster_edge(edge): # edge is CG but not a connectivity cluster, just a set
230230

231231
def cluster_PP_(edge, fd):
232232
G_ = []
233-
N_ = copy(edge.link_ if fd else edge.subG_)
233+
N_ = copy(edge.link_ if fd else edge.node_)
234234
while N_: # flood fill
235235
node_,link_, et = [],[], np.zeros(4)
236236
N = N_.pop(); _eN_ = [N]
@@ -252,7 +252,7 @@ def cluster_PP_(edge, fd):
252252
if fd: edge.link_ = G_
253253
else: edge.node_ = G_ # vs init PP_
254254
# comp PP_:
255-
N_,L_,Et = comp_node_(edge.subG_)
255+
N_,L_,Et = comp_node_(edge.node_)
256256
if val_(Et, fo=1) > 0: # cancel by borrowing d?
257257
mlay = CH().add_tree([L.derH for L in L_]); H=edge.derH; mlay.root=H; H.Et += mlay.Et; H.lft = [mlay] # init with mfork
258258
if len(N_) > ave_L:
@@ -323,6 +323,7 @@ def comp_link_(iL_, iEt): # comp CLs via directional node-mediated link tracing
323323
for L in _L_:
324324
for mL_ in L.mL_t:
325325
for _L, rev in mL_: # rev is relative to L
326+
# if _L not in iL_, skip it? Or it shouldn't happen?
326327
rn = _L.Et[2] / L.Et[2]
327328
if rn > ave_rn: continue # scope disparity
328329
dy,dx = np.subtract(_L.yx,L.yx)
@@ -397,8 +398,10 @@ def comp_N(_N,N, rn, angle=None, dist=None, dir=1): # dir if fd, Link.derH=dH,
397398
lay.Et += derH.Et; lay.lft = [derH]
398399
# spec: comp_node_(node_|link_), combinatorial, node_ nested / rng-)agg+?
399400
Et = copy(lay.Et)
400-
if not fd and _N.altG and N.altG: # not for CL, eval M?
401-
alt_Link = comp_N(_N.altG, N.altG, _N.altG.Et[2]/N.altG.Et[2]) # init alternating PPds | dPs?
401+
if not fd and _N.altG_ and N.altG_: # not for CL, eval M?
402+
# not sure
403+
_altG, altG = sum_G_(_N.altG_), sum_G_(N.altG_)
404+
alt_Link = comp_N(_altG, altG, _altG.Et[2]/altG.Et[2]) # init alternating PPds | dPs?
402405
lay.altH = alt_Link.derH
403406
Et += lay.altH.Et
404407
Link = CL(nodet=[_N,N], derH=lay, yx=np.add(_N.yx,N.yx)/2, angle=angle,dist=dist,box=extend_box(N.box,_N.box))
@@ -413,6 +416,15 @@ def comp_N(_N,N, rn, angle=None, dist=None, dir=1): # dir if fd, Link.derH=dH,
413416

414417
def get_rim(N,fd): return N.rimt[0] + N.rimt[1] if fd else N.rim # add nesting in cluster_N_?
415418

419+
def sum_G_(node_):
420+
G = CG()
421+
for n in node_:
422+
G.latuple += n.latuple; G.vert += n.vert; G.aRad += n.aRad; G.box = extend_box(G.box, n.box)
423+
if n.derH: G.derH.add_tree(n.derH, root=G)
424+
if n.extH: G.extH.add_tree(n.extH)
425+
return G
426+
427+
416428
def sum2graph(root, grapht, fd, maxL=None, nest=0): # sum node and link params into graph, aggH in agg+ or player in sub+
417429

418430
node_, link_, Et = grapht
@@ -423,7 +435,7 @@ def sum2graph(root, grapht, fd, maxL=None, nest=0): # sum node and link params
423435
root_ = []
424436
for N in node_:
425437
if nest: # G is dist-nested in cluster_N_, cluster roots instead of nodes
426-
while N.root.nest < nest: N = N.root # incr/elevation, term if ==nest
438+
while N.root and N.root.nest < nest: N = N.root # incr/elevation, term if ==nest (how to skip frame or edge here? If frame.nest is init as 0, their nest is < nest too)
427439
if N in root_: continue # roots overlap
428440
root_ += [N]
429441
graph.box = extend_box(graph.box, N.box) # pre-compute graph.area += N.area?

0 commit comments

Comments
 (0)