Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
2008__tour3.cc
1 // Copyright (C) 2001, 2007, 2008 EPITA Research and Development
2 // Laboratory
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 // File: tour2.cc.
28 
29 #include <oln/core/2d/image2d.hh>
30 #include <oln/core/2d/neighb2d.hh>
31 
32 #include <oln/core/gen/such_as.hh>
33 #include <oln/core/gen/torus_image.hh>
34 #include <oln/core/gen/pw_value.hh>
35 #include <oln/core/gen/fun_ops.hh>
36 
37 #include <oln/data/fill.hh>
38 #include <oln/debug/fill.hh>
39 #include <oln/debug/println.hh>
40 
41 
42 // Note to the reader: you should have read the files tour1.cc and
43 // tour2.cc before starting with this present file.
44 
45 
46 
47 // We have encapsulated an algorithm into a procedure which is forward
48 // declared below so that it can be used in the section 'main'.
49 template <typename I> void algo(const I& img);
50 
51 
52 // Some functions that will be useful in the following:
53 bool chessboard(oln::point2d p)
54 {
55  return (p.row() + p.col()) % 2;
56 }
57 
58 
59 
60 int main()
61 {
62  using namespace oln;
63 
64  // First our domain is 2d box:
65  box2d b(point2d(0, 0), point2d(2, 2));
66  // ^^^^ ^^^^
67  // from to
68 
69  // We define a binary image with values on that box.
70  image2d<bool> img(b);
71 
72  // With an array of Booleans (1 means true, 0 means false)...
73  bool vals[] = { 1, 0, 0,
74  0, 1, 0,
75  0, 1, 1 };
76  // ...the debug::fill routine allows for manually initializing
77  // image data:
78  debug::fill(img, vals);
79  std::cout << "img = " << std::endl;
80  debug::println(img);
81  // img =
82  // | - -
83  // - | -
84  // - | |
85 
86  image2d<int> ima(b); // An image of integers with the same
87  box2d::piter p(ima.points()); // domain as img...
88  int i = 0;
89  for_all(p)
90  ima(p) = i++; // ...and manually filled with values.
91 
92  std::cout << "ima = " << std::endl;
93  debug::println(ima);
94  // ima =
95  // 0 1 2
96  // 3 4 5
97  // 6 7 8
98 
99 
100 
101  // The algorithm defined at the end of this file is very close to
102  // the one of the tour former file. The major difference is that it
103  // does not rely on a window but on a neighborhood.
104 
105  // In image processing, we usually say that "an image has a given
106  // neighborhood" or that "we associate/embed a neighborhood to/into
107  // an image". In Olena, that is really the case: the image can
108  // "have" a neighborhood, meaning that a neighborhood can be added
109  // to an image in order to obtain an "image with a neighborhood".
110 
111  // Joining an image with a neighborhood is performed with the
112  // operator '+':
113  algo(ima + c4); // c4 is the 2D neighborhood corresponding to
114  // 4-connectivity; such as many classical
115  // neighborhoods it is provided by Olena.
116  // The result is given below.
117 
118  // ---input:
119  // 0 1 2
120  // 1 2 3
121  // 2 3 4
122  // ---output:
123  // 0: 1 1
124  // 1: 0 2 2
125  // 2: 1 3
126  // 1: 0 2 2
127  // 2: 1 1 3 3
128  // 3: 2 2 4
129  // 2: 1 3
130  // 3: 2 2 4
131  // 4: 3 3
132 
133  // That was expectable...
134 
135 
136  // And now for a little test: what is the result of this code?
137  {
138  image2d<int> test(ima.points());
139  data::fill(test, ima);
140  (test + c4).at(1, 1) = 9;
141  debug::println(test);
142  }
143  // and can you tell why?
144  // The answers are given in the file tour3-test.txt
145 
146 
147  // Now let us start experimenting the genericity of Olena!
148 
149 
150  // First, imagine that you want to restrict the domain of ima to a
151  // subset of points, a region or whatever. For instance, the
152  // chessboard function takes a point as argument and returns a
153  // Boolean so it is like a predicate. We can want to consider only
154  // the points of ima "such as" this predicate is verified. The
155  // "such as" mathematical symbol is '|' so let's rock:
156 
157  algo((ima | chessboard) + c8);
158  // gives:
159 
160  // ---input:
161  // 1
162  // 3 5
163  // 7
164  // ---output:
165  // 1: 3 5
166  // 3: 1 7
167  // 5: 1 7
168  // 7: 3 5
169 
170  // where the blanks in printing the input image denote that the
171  // corresponding points do NOT belong to the image domain.
172 
173  // Another similar example is based on the binary image created at
174  // the beginning of this tour:
175  algo((ima | img) + c8);
176  // which gives:
177 
178  // ---input:
179  // 0
180  // 4
181  // 7 8
182  // ---output:
183  // 0: 4
184  // 4: 0 7 8
185  // 7: 4 8
186  // 8: 4 7
187 
188 
189 
190  // Second, imagine that you want your initial image to get the
191  // geodesy of a torus, that is, a 2D image wrapped on a torus.
192  // Points located at the image boundary have neighbors; for
193  // instance, the point denoted by the 'x' cross below has for
194  // 4-connectivity neighbors: t, l, r, and b (respectively for top,
195  // left, right, and bottom):
196 
197  // b o o o
198  // o o o o
199  // t o o o
200  // x r o l
201 
202  // Let us try:
203  algo(torus(ima) + c8);
204  // gives:
205 
206  // ---input:
207  // 0 1 2
208  // 3 4 5
209  // 6 7 8
210  // ---output:
211  // 0: 8 6 7 2 1 5 3 4
212  // 1: 6 7 8 0 2 3 4 5
213  // 2: 7 8 6 1 0 4 5 3
214  // 3: 2 0 1 5 4 8 6 7
215  // 4: 0 1 2 3 5 6 7 8
216  // 5: 1 2 0 4 3 7 8 6
217  // 6: 5 3 4 8 7 2 0 1
218  // 7: 3 4 5 6 8 0 1 2
219  // 8: 4 5 3 7 6 1 2 0
220 
221 
222 
223  // We can have both the torus geodesy and a sub-domain:
224 
225  algo(torus(ima | chessboard) + c8);
226  algo(torus(ima | img) + c8);
227 
228  // which respectively give:
229 
230  // ---input:
231  // 1
232  // 3 5
233  // 7
234  // ---output:
235  // 1: 7 3 5
236  // 3: 1 5 7
237  // 5: 1 3 7
238  // 7: 3 5 1
239 
240  // and:
241 
242  // ---input:
243  // 0
244  // 4
245  // 7 8
246  // ---output:
247  // 0: 8 7 4
248  // 4: 0 7 8
249  // 7: 4 8 0
250  // 8: 4 7 0
251 
252 
253 
254 
255  // Last, the way a predicate is defined can also rely on some image
256  // values. For that the user can on the fly provide an expression
257  // built with the "pw_value" facility, where "pw_" means
258  // "point-wise" for short:
259 
260  algo((ima | (pw_value(ima) < 4)) + c4);
261 
262  // In this example, "pw_value(ima)" is the function that represents
263  // the point-wise value of the 'ima' image, that is, the function
264  // "p -> ima(p)". This naturally leads to:
265 
266  // ---input:
267  // 0 1 2
268  // 3
269  //
270  // ---output:
271  // 0: 1 3
272  // 1: 0 2
273  // 2: 1
274  // 3: 0
275 
276 
277 
278  // From those examples, you should realize that:
279 
280 
281  // +-----------------------------------------------------------+
282  // | |
283  // | The level of "genericity" provided by Olena is rather |
284  // | high; it means: |
285  // | |
286  // | - taking the image dimension you work on; |
287  // | |
288  // | - having the type of pixel values you need; |
289  // | |
290  // | - choosing the neighborhood you want; |
291  // | |
292  // | - changing the geodesy if you need it; |
293  // | |
294  // | - being able to restrict the image domain; |
295  // | |
296  // | - and many other features that are addressed further |
297  // | in the tour... |
298  // | |
299  // +-----------------------------------------------------------+
300 
301 }
302 
303 
304 
305 
306 
307 // The algorithm 'algo':
308 
309 template <typename I>
310 void algo(const I& img)
311 {
312  std::cout << "---input:" << std::endl;
313  oln::debug::print(img);
314  std::cout << "---output:" << std::endl;
315 
316  oln_piter(I) p(img.points()); // p iterates on img points
317  oln_niter(I) n(img, p); // n iterates in img on neighbors of p
318 
319  for_all(p)
320  {
321  std::cout << oln::debug::format(img(p))
322  << ':';
323  for_all(n)
324  std::cout << ' '
325  << oln::debug::format(img(n));
326  std::cout << std::endl;
327  }
328 
329  std::cout << std::endl;
330 }