Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpDot2_freeman.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Freeman chain dedicated functions.
32 */
33
34#include <visp3/core/vpConfig.h>
35#include <visp3/blob/vpDot2.h>
36
38
39#ifndef DOXYGEN_SHOULD_SKIP_THIS
40namespace
41{
54void computeTopRightWithMoment(const int &u_p, const int &v_p, float &dMuv, float &dMu2, float &dMv2)
55{
56 float half_u_p = static_cast<float>(0.5 * u_p);
57 dMuv = static_cast<float>((v_p * v_p * (0.25 + half_u_p)) + (v_p * ((1. / 3.) + half_u_p)) + ((1. / 6.) * u_p) + 0.125);
58 dMu2 = static_cast<float>(((-1. / 3.) * u_p * ((u_p * u_p) + (1.5 * u_p) + 1.)) - (1. / 12.0));
59 dMv2 = static_cast<float>(((1. / 3.) * v_p * ((v_p * v_p) + (1.5 * v_p) + 1.)) + (1. / 12.0));
60}
61
74void computeTopLeftWithMoment(const int &u_p, const int &v_p, float &dMuv, float &dMu2, float &dMv2)
75{
76 float half_u_p = static_cast<float>(0.5 * u_p);
77 dMuv = static_cast<float>((((v_p * v_p * (0.25 - half_u_p)) + (v_p * ((1. / 3.) - half_u_p))) - ((1. / 6.) * u_p)) + 0.125);
78 dMu2 = static_cast<float>(((-1. / 3.) * u_p * (((u_p * u_p) - (1.5 * u_p)) + 1.)) - (1. / 12.0));
79 dMv2 = static_cast<float>(((-1. / 3.) * v_p * ((v_p * v_p) + (1.5 * v_p) + 1.)) - (1. / 12.0));
80}
81
94void computeDownRightWithMoment(const int &u_p, const int &v_p, float &dMuv, float &dMu2, float &dMv2)
95{
96 float half_u_p = static_cast<float>(0.5 * u_p);
97 dMuv = static_cast<float>(((v_p * v_p * (0.25 + half_u_p)) - (v_p * ((1. / 3.) + half_u_p))) + ((1. / 6.) * u_p) + 0.125);
98 dMu2 = static_cast<float>(((1. / 3.) * u_p * ((u_p * u_p) + (1.5 * u_p) + 1.)) + (1. / 12.0));
99 dMv2 = static_cast<float>(((1. / 3.) * v_p * (((v_p * v_p) - (1.5 * v_p)) + 1.)) - (1. / 12.0));
100}
101
114void computeDownLeftWithMoment(const int &u_p, const int &v_p, float &dMuv, float &dMu2, float &dMv2)
115{
116 float half_u_p = static_cast<float>(0.5 * u_p);
117 dMuv = static_cast<float>((((v_p * v_p * (0.25 - half_u_p)) - (v_p * ((1. / 3.) - half_u_p))) - ((1. / 6.) * u_p)) + 0.125);
118 dMu2 = static_cast<float>(((1. / 3.) * u_p * (((u_p * u_p) - (1.5 * u_p)) + 1.)) - (1. / 12.0));
119 dMv2 = static_cast<float>(((-1. / 3.) * v_p * (((v_p * v_p) - (1.5 * v_p)) + 1.)) - (1. / 12.0));
120}
121}
122
123#endif // DOXYGEN_SHOULD_SKIP_THIS
139void vpDot2::getFreemanChain(std::list<unsigned int> &freeman_chain) const { freeman_chain = m_direction_list; }
140
159bool vpDot2::computeFreemanChainElement(const vpImage<unsigned char> &I, const unsigned int &u, const unsigned int &v,
160 unsigned int &element)
161{
162 if (hasGoodLevel(I, u, v)) {
163 unsigned int v_u = u;
164 unsigned int v_v = v;
165 const unsigned int val_1 = 1;
166 const unsigned int val_2 = 2;
167 const unsigned int val_3 = 3;
168 const unsigned int val_4 = 4;
169 const unsigned int val_5 = 5;
170 const unsigned int val_6 = 6;
171 const unsigned int val_7 = 7;
172 const unsigned int val_8 = 8;
173 // get the point on the right of the point passed in
174 updateFreemanPosition(v_u, v_v, (element + val_2) % val_8);
175 if (hasGoodLevel(I, v_u, v_v)) {
176 element = (element + val_2) % val_8; // turn right
177 }
178 else {
179 unsigned int v_u1 = u;
180 unsigned int v_v1 = v;
181 updateFreemanPosition(v_u1, v_v1, (element + val_1) % val_8);
182
183 if (hasGoodLevel(I, v_u1, v_v1)) {
184 element = (element + val_1) % val_8; // turn diag right
185 }
186 else {
187 unsigned int v_u2 = u;
188 unsigned int v_v2 = v;
189 updateFreemanPosition(v_u2, v_v2, element); // same direction
190
191 if (hasGoodLevel(I, v_u2, v_v2)) {
192 // element = element; // keep same dir
193 }
194 else {
195 unsigned int v_u3 = u;
196 unsigned int v_v3 = v;
197 updateFreemanPosition(v_u3, v_v3, (element + val_7) % val_8); // diag left
198
199 if (hasGoodLevel(I, v_u3, v_v3)) {
200 element = (element + val_7) % val_8; // turn diag left
201 }
202 else {
203 unsigned int v_u4 = u;
204 unsigned int v_v4 = v;
205 updateFreemanPosition(v_u4, v_v4, (element + val_6) % val_8); // left
206
207 if (hasGoodLevel(I, v_u4, v_v4)) {
208 element = (element + val_6) % val_8; // turn left
209 }
210 else {
211 unsigned int v_u5 = u;
212 unsigned int v_v5 = v;
213 updateFreemanPosition(v_u5, v_v5, (element + val_5) % val_8); // left
214
215 if (hasGoodLevel(I, v_u5, v_v5)) {
216 element = (element + val_5) % val_8; // turn diag down
217 }
218 else {
219 unsigned int v_u6 = u;
220 unsigned int v_v6 = v;
221 updateFreemanPosition(v_u6, v_v6, (element + val_4) % val_8); // left
222
223 if (hasGoodLevel(I, v_u6, v_v6)) {
224 element = (element + val_4) % val_8; // turn down
225 }
226 else {
227 unsigned int v_u7 = u;
228 unsigned int v_v7 = v;
229 updateFreemanPosition(v_u7, v_v7, (element + val_3) % val_8); // diag
230
231 if (hasGoodLevel(I, v_u7, v_v7)) {
232 element = (element + val_3) % val_8; // turn diag right down
233 }
234 else {
235 // No neighbor with a good level
236 //
237 return false;
238 }
239 }
240 }
241 }
242 }
243 }
244 }
245 }
246 }
247
248 else {
249 return false;
250 }
251
252 return true;
253}
254
284void vpDot2::computeFreemanParameters(const int &u_p, const int &v_p, unsigned int &element, int &du, int &dv,
285 float &dS, float &dMu, float &dMv, float &dMuv, float &dMu2, float &dMv2)
286{
287 /*
288 3 2 1
289 \ | /
290 \|/
291 4 ------- 0
292 /|\
293 / | \
294 5 6 7
295 */
296 const unsigned int go_right = 0;
297 const unsigned int go_right_top = 1;
298 const unsigned int go_top = 2;
299 const unsigned int go_top_left = 3;
300 const unsigned int go_left = 4;
301 const unsigned int go_left_down = 5;
302 const unsigned int go_down = 6;
303 const unsigned int go_down_right = 7;
304 du = 0;
305 dv = 0;
306 dMuv = 0;
307 dMu2 = 0;
308 dMv2 = 0;
309 const unsigned int val_2 = 2;
310 switch (element) {
311 case go_right: // go right
312 du = 1;
313 dS = static_cast<float>(v_p);
314 dMu = 0.0;
315 dMv = static_cast<float>(0.5 * v_p * v_p);
316 if (m_compute_moment) {
317 dMuv = static_cast<float>(0.25 * v_p * v_p * ((val_2 * u_p) + 1));
318 dMu2 = 0;
319 dMv2 = static_cast<float>((1.0 / 3.) * v_p * v_p * v_p);
320 }
321 break;
322
323 case go_right_top: // go right top
324 du = 1;
325 dv = 1;
326 dS = static_cast<float>(v_p + 0.5);
327 dMu = -static_cast<float>((0.5 * u_p * (u_p + 1)) + (1.0 / 6.0));
328 dMv = static_cast<float>((0.5 * v_p * (v_p + 1)) + (1.0 / 6.0));
329 if (m_compute_moment) {
330 computeTopRightWithMoment(u_p, v_p, dMuv, dMu2, dMv2);
331 }
332 break;
333
334 case go_top: // go top
335 dv = 1;
336 dS = 0.0;
337 dMu = static_cast<float>(-0.5 * u_p * u_p);
338 dMv = 0.0;
339 if (m_compute_moment) {
340 dMuv = 0;
341 dMu2 = static_cast<float>((-1.0 / 3.) * u_p * u_p * u_p);
342 dMv2 = 0;
343 }
344 break;
345
346 case go_top_left:
347 du = -1;
348 dv = 1;
349 dS = static_cast<float>(-v_p - 0.5);
350 dMu = -static_cast<float>((0.5 * u_p * (u_p - 1)) + (1.0 / 6.0));
351 dMv = -static_cast<float>((0.5 * v_p * (v_p + 1)) + (1.0 / 6.0));
352 if (m_compute_moment) {
353 computeTopLeftWithMoment(u_p, v_p, dMuv, dMu2, dMv2);
354 }
355 break;
356
357 case go_left:
358 du = -1;
359 dS = static_cast<float>(-v_p);
360 dMv = static_cast<float>(-0.5 * v_p * v_p);
361 dMu = 0.0;
362 if (m_compute_moment) {
363 dMuv = static_cast<float>(-0.25 * v_p * v_p * ((val_2 * u_p) - 1));
364 dMu2 = 0;
365 dMv2 = static_cast<float>((-1.0 / 3.) * v_p * v_p * v_p);
366 }
367 break;
368
369 case go_left_down:
370 du = -1;
371 dv = -1;
372 dS = static_cast<float>(-v_p + 0.5);
373 dMu = static_cast<float>((0.5 * u_p * (u_p - 1)) + (1.0 / 6.0));
374 dMv = static_cast<float>(-((0.5 * v_p * (v_p - 1)) + (1.0 / 6.0)));
375 if (m_compute_moment) {
376 computeDownLeftWithMoment(u_p, v_p, dMuv, dMu2, dMv2);
377 }
378 break;
379
380 case go_down:
381 dv = -1;
382 dS = 0.0;
383 dMu = static_cast<float>(0.5 * u_p * u_p);
384 dMv = 0.0;
385 if (m_compute_moment) {
386 dMuv = 0;
387 dMu2 = static_cast<float>((1.0 / 3.) * u_p * u_p * u_p);
388 dMv2 = 0;
389 }
390 break;
391
392 case go_down_right:
393 du = 1;
394 dv = -1;
395 dS = static_cast<float>(v_p - 0.5);
396 dMu = static_cast<float>((0.5 * u_p * (u_p + 1)) + (1.0 / 6.0));
397 dMv = static_cast<float>((0.5 * v_p * (v_p - 1)) + (1.0 / 6.0));
398 if (m_compute_moment) {
399 computeDownRightWithMoment(u_p, v_p, dMuv, dMu2, dMv2);
400 }
401 break;
402
403 default:
404 std::cout << "to complete the default" << std::endl;
405 }
406}
407
421void vpDot2::updateFreemanPosition(unsigned int &u, unsigned int &v, const unsigned int &dir)
422{
423 /*
424 3 2 1
425 \ | /
426 \|/
427 4 ------- 0
428 /|\
429 / | \
430 5 6 7
431 */
432 const unsigned int go_right = 0;
433 const unsigned int go_right_top = 1;
434 const unsigned int go_top = 2;
435 const unsigned int go_top_left = 3;
436 const unsigned int go_left = 4;
437 const unsigned int go_left_down = 5;
438 const unsigned int go_down = 6;
439 const unsigned int go_down_right = 7;
440 switch (dir) {
441 case go_right:
442 u += 1;
443 break;
444 case go_right_top:
445 u += 1;
446 v += 1;
447 break;
448 case go_top:
449 v += 1;
450 break;
451 case go_top_left:
452 u -= 1;
453 v += 1;
454 break;
455 case go_left:
456 u -= 1;
457 break;
458 case go_left_down:
459 u -= 1;
460 v -= 1;
461 break;
462 case go_down:
463 v -= 1;
464 break;
465 case go_down_right:
466 u += 1;
467 v -= 1;
468 break;
469 default:
470 std::cout << "In vpDot2::updateFreemanPosition dir not identified" << std::endl;
471 }
472}
473
474END_VISP_NAMESPACE
void getFreemanChain(std::list< unsigned int > &freeman_chain) const
Definition of the vpImage class member functions.
Definition vpImage.h:131