Skip to content

Commit d4dfa32

Browse files
authored
Merge pull request #7 from diku-dk/union_find
Union-find.
2 parents 0bab036 + 1718dc0 commit d4dfa32

File tree

5 files changed

+1288
-0
lines changed

5 files changed

+1288
-0
lines changed

examples/labeling/labeling.fut

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import "../../lib/github.com/diku-dk/containers/unionfind"
2+
3+
-- Start with some utility definitions for handling directions and positions.
4+
5+
-- | A cardinal direction, with `#c` being current location ("centre").
6+
type dir = #n | #w | #e | #s
7+
8+
-- | Position in a grid.
9+
type pos = (i64, i64)
10+
11+
-- | Move along direction.
12+
def move (d: dir) ((i, j): pos) =
13+
match d
14+
case #n -> (i - 1, j)
15+
case #w -> (i, j - 1)
16+
case #e -> (i, j + 1)
17+
case #s -> (i + 1, j)
18+
19+
-- | Turn a position into a flat index, given a grid width.
20+
def flat_pos (w: i64) ((x, y): pos) : i64 = x * w + y
21+
22+
-- | Is this position in bounds in some grid?
23+
def in_bounds [h] [w] 'a (_: [h][w]a) ((i, j): pos) =
24+
i >= 0 && i < h && j >= 0 && j < w
25+
26+
-- | Get element at position in grid.
27+
def get 'a ((i, j): pos) (g: [][]a) =
28+
g[i, j]
29+
30+
-- | Could be improved. This is unlikely to produce something very legible.
31+
def colourise_regions [h] [w] (labels: [h][w]i64) : [h][w]u32 =
32+
let f l = u32.i64 l
33+
in map (map f) labels
34+
35+
def mk_nasty (w: i64) : [w][w]u32 =
36+
tabulate_2d w w \i j ->
37+
if (j % 2 == 0) || (i == 0 && (j / 2) % 2 == 0)
38+
|| (i == w - 1 && (j / 2) % 2 == 1)
39+
then 0
40+
else 0xffffff
41+
42+
def mk_equivalences [h] [w] (img: [h][w]u32) : ?[n].[n](i64, i64) =
43+
tabulate_2d h
44+
w
45+
(\i j ->
46+
let p = (i, j)
47+
let flat_p = flat_pos w p
48+
in map (\n ->
49+
let p' = move n p
50+
in if in_bounds img p' && get p img == get p' img
51+
then (flat_p, flat_pos w p')
52+
else (flat_p, -1))
53+
[#n, #w, #e, #s])
54+
|> flatten_3d
55+
|> filter ((>= 0) <-< (.1))
56+
57+
module u = unionfind
58+
59+
def region_label_unionfind [h] [w] (img: [h][w]u32) =
60+
let uf = u.create (h * w)
61+
let eqs =
62+
copy (mk_equivalences img
63+
|> map (\(i, j) ->
64+
( u.from_i64 uf i
65+
, u.from_i64 uf j
66+
)))
67+
let uf = u.union uf eqs
68+
let labels = u.find' uf (u.handles uf)
69+
in unflatten (map (u.to_i64 uf) labels :> [h * w]i64)
70+
71+
-- > :img (colourise_regions (region_label_unionfind ($loadimg "regions-hard.png")))
72+
73+
-- > :img mk_nasty 128
74+
75+
-- > :img colourise_regions (region_label_unionfind (mk_nasty 128))

examples/labeling/regions-hard.png

11.7 KB
Loading

0 commit comments

Comments
 (0)