1 # More Complex Interface Mapping MavenStyleProject - The Cascade
2 [Back to Index ../](../index.md)
3
4 # More Complex Interface Mapping MavenStyleProject - The Cascade
5
6 Previously we showed probably the minimal useful mapping with S32Array
7
8 The HaarCascade example has multiple nested interfaces representing data
9 structures involving various nested structs and unions
10
11 ```java
12 public interface Cascade extends Buffer {
13 int width();
14 void width(int width);
15 int height();
16 void height(int height);
17 interface Feature extends Buffer.StructChild {
18 int id();
19 float threshold();
20 void id(int id);
21 void threshold(float threshold);
22 interface LinkOrValue extends Buffer.StructChild {
23 interface Anon extends Buffer.UnionChild {
24 int featureId();
25 void featureId(int featureId);
26 float value();
27 void value(float value);
28 }
29 boolean hasValue();
30 void hasValue(boolean hasValue);
31 Anon anon();
32 }
33 LinkOrValue left();
34 LinkOrValue right();
35 interface Rect extends Buffer.StructChild {
36 byte x();
37 byte y();
38 byte width();
39 byte height();
40 float weight();
41 void x(byte x);
42 void y(byte y);
43 void width(byte width);
44 void height(byte height);
45 void weight(float height);
46 }
47 Rect rect(long idx);
48 }
49 int featureCount();
50 void featureCount(int featureCount);
51 Feature feature(long idx);
52 interface Stage extends Buffer.StructChild {
53 float threshold();
54 short firstTreeId();
55 short treeCount();
56 int id();
57 void id(int id);
58 void threshold(float threshold);
59 void firstTreeId(short firstTreeId);
60 void treeCount(short treeCount);
61 }
62
63 int stageCount();
64 void stageCount(int stageCount);
65 Stage stage(long idx);
66 interface Tree extends Buffer.StructChild {
67 void id(int id);
68 void firstFeatureId(short firstFeatureId);
69 void featureCount(short featureCount);
70 int id();
71 short firstFeatureId();
72 short featureCount();
73 }
74 int treeCount();
75 void treeCount(int treeCount);
76 Tree tree(long idx);
77 Schema<Cascade> schema = Schema.of(Cascade.class, cascade -> cascade
78 .fields("width", "height")
79 .arrayLen("featureCount")
80 .array("feature", feature -> feature
81 .field("id")
82 .field("threshold")
83 .fields("left", "right", linkOrValue -> linkOrValue
84 .field("hasValue")
85 .pad(3)
86 .field("anon", anon -> anon
87 .field("featureId")
88 .field("value")
89 )
90 )
91 .array("rect", 3, rect -> rect
92 .field("x")
93 .field("y")
94 .field("width")
95 .field("height").
96 .field("weight"))
97 )
98 .arrayLen("treeCount")
99 .array("tree", tree -> tree
100 .field("id")
101 .field("featureCount")
102 .field("firstFeatureId")
103 )
104 .arrayLen("stageCount")
105 .array("stage", stage -> stage
106 .field("id")
107 .field("threshold")
108 .field("treeCount")
109 .field("firstTreeId"))
110 );
111 }
112 ```
113
114 Another great advantage of using interfaces is that we can choose
115 to re implement the interface in any was we see fit.
116
117 For example we load HaarCascades from XML files.
118 We therefore can create an implementation of the Cascade interface which just
119 loads the XML DOM... stores them in arrays and the interface methods just delegate to
120 the appropriately wrapped w3c.Node tree nodes ;)
121
122 If we know we are using Java backend we can actually
123 just pass the XMLCascade implementation directly to the backend...
124
125 Actually the Cascade `create` method takes an existing
126 implementation of a Cascade and clones it.
127 So we can just pass it an XMLHaarCascade ;)
128
129 So we build an XMLCascade then pass it to the `create` method of the iface
130 mapped Cascade
131
132 ```java
133 XMLHaarCascadeModel haarCascade = XMLHaarCascadeModel.load(
134 ViolaJonesRaw.class.getResourceAsStream("haarcascade_frontalface_default.xml"));
135
136 assert haarCascade instanceof Cascade; // Here it is just an interface
137
138 Cascade cascade = Cascade.create(accelerator, haarCascade);
139
140 // Now it can be used on the GPU
141 ```
142
143 The implementation is currently hand crafted, but this could easily be automated.
144
145 ```java
146 import java.lang.invoke.MethodHandles;
147
148 static Cascade create(MethodHandles.Lookup lookup,BufferAllocator bufferAllocator, XMLHaarCascadeModel haarCascade) {
149
150 Cascade cascade = bufferAllocator.allocate(SegmentMapper.of(lookup, Cascade.class,
151 JAVA_INT.withName("width"),
152 JAVA_INT.withName("height"),
153 JAVA_INT.withName("featureCount"),
154 sequenceLayout(haarCascade.features.size(), Feature.layout.withName(Feature.class.getSimpleName())).withName("feature"),
155 JAVA_INT.withName("stageCount"),
156 sequenceLayout(haarCascade.stages.size(), Stage.layout.withName(Stage.class.getSimpleName())).withName("stage"),
157 JAVA_INT.withName("treeCount"),
158 sequenceLayout(haarCascade.trees.size(), Tree.layout.withName(Tree.class.getSimpleName())).withName("tree")
159 ));
160 cascade.width(haarCascade.width());
161 cascade.height(haarCascade.height());
162 cascade.featureCount(haarCascade.features.size());
163 cascade.stageCount(haarCascade.stages.size());
164 cascade.treeCount(haarCascade.trees.size());
165 for (int idx = 0; idx < haarCascade.features.size(); idx++) {
166 Cascade.Feature cascadeFeature = cascade.feature(idx);
167 var haarfeature = haarCascade.features.get(idx);
168 cascadeFeature.id(haarfeature.id());
169 cascadeFeature.threshold(haarfeature.threshold());
170 Cascade.Feature.LinkOrValue cascadeLeft = cascadeFeature.left();
171 cascadeLeft.hasValue(haarfeature.left.hasValue());
172 if (haarfeature.left.hasValue()) {
173 cascadeLeft.anon().value(haarfeature.left.value());
174 } else {
175 cascadeLeft.anon().value(haarfeature.left.featureId());
176 }
177 Cascade.Feature.LinkOrValue cascadeRight = cascadeFeature.right();
178 cascadeRight.hasValue(haarfeature.right.hasValue());
179 if (haarfeature.right.hasValue()) {
180 cascadeRight.anon().value(haarfeature.right.value());
181 } else {
182 cascadeRight.anon().featureId(haarfeature.right.featureId());
183 }
184 for (int r = 0; r < 3; r++) {
185 var haarrect = haarfeature.rects[r];
186 if (haarrect != null) {
187 Cascade.Feature.Rect cascadeRect = cascadeFeature.rect(r);
188 cascadeRect.x(haarrect.x());
189 cascadeRect.y(haarrect.y());
190 cascadeRect.width(haarrect.width());
191 cascadeRect.height(haarrect.height());
192 cascadeRect.weight(haarrect.weight());
193 }
194 }
195 }
196 for (XMLHaarCascadeModel.Stage haarstage : haarCascade.stages) {
197 Cascade.Stage cascadeStage = cascade.stage(haarstage.id);
198 cascadeStage.id(haarstage.id());
199 cascadeStage.threshold(haarstage.threshold());
200 cascadeStage.firstTreeId(haarstage.firstTreeId());
201 cascadeStage.treeCount(haarstage.treeCount());
202 }
203
204 for (XMLHaarCascadeModel.Tree haarTree : haarCascade.trees) {
205 Cascade.Tree cascadeTree = cascade.tree(haarTree.id());
206 cascadeTree.id(haarTree.id());
207 cascadeTree.firstFeatureId(haarTree.firstFeatureId());
208 cascadeTree.featureCount(haarTree.featureCount());
209 }
210 return cascade;
211 }
212 ```
213