Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
vpImageTools.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See https://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * Image tools.
33 *
34*****************************************************************************/
35
36#include <visp3/core/vpCPUFeatures.h>
37#include <visp3/core/vpImageConvert.h>
38#include <visp3/core/vpImageTools.h>
39
40#include <Simd/SimdLib.hpp>
41
97void vpImageTools::changeLUT(vpImage<unsigned char> &I, unsigned char A, unsigned char A_star, unsigned char B,
98 unsigned char B_star)
99{
100 // Test if input values are valid
101 if (B <= A) {
102 vpERROR_TRACE("Bad gray levels");
104 }
105 unsigned char v;
106
107 double factor = (double)(B_star - A_star) / (double)(B - A);
108
109 for (unsigned int i = 0; i < I.getHeight(); i++)
110 for (unsigned int j = 0; j < I.getWidth(); j++) {
111 v = I[i][j];
112
113 if (v <= A)
114 I[i][j] = A_star;
115 else if (v >= B)
116 I[i][j] = B_star;
117 else
118 I[i][j] = (unsigned char)(A_star + factor * (v - A));
119 }
120}
121
136{
137 if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
138 throw(vpException(vpException::dimensionError, "The two images have not the same size"));
139 }
140
141 if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth())) {
142 Idiff.resize(I1.getHeight(), I1.getWidth());
143 }
144
145 SimdImageDifference(I1.bitmap, I2.bitmap, I1.getSize(), Idiff.bitmap);
146}
147
162{
163 if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
165 "Cannot compute image difference. The two images "
166 "(%ux%u) and (%ux%u) have not the same size",
167 I1.getWidth(), I1.getHeight(), I2.getWidth(), I2.getHeight()));
168 }
169
170 if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth())) {
171 Idiff.resize(I1.getHeight(), I1.getWidth());
172 }
173
174 SimdImageDifference(reinterpret_cast<unsigned char *>(I1.bitmap), reinterpret_cast<unsigned char *>(I2.bitmap),
175 I1.getSize() * 4, reinterpret_cast<unsigned char *>(Idiff.bitmap));
176}
177
190{
191 if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
192 throw(vpException(vpException::dimensionError, "The two images do not have the same size"));
193 }
194
195 if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth())) {
196 Idiff.resize(I1.getHeight(), I1.getWidth());
197 }
198
199 unsigned int n = I1.getHeight() * I1.getWidth();
200 for (unsigned int b = 0; b < n; b++) {
201 int diff = I1.bitmap[b] - I2.bitmap[b];
202 Idiff.bitmap[b] = static_cast<unsigned char>(vpMath::abs(diff));
203 }
204}
205
214{
215 if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
216 throw(vpException(vpException::dimensionError, "The two images do not have the same size"));
217 }
218
219 if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth())) {
220 Idiff.resize(I1.getHeight(), I1.getWidth());
221 }
222
223 unsigned int n = I1.getHeight() * I1.getWidth();
224 for (unsigned int b = 0; b < n; b++) {
225 Idiff.bitmap[b] = vpMath::abs(I1.bitmap[b] - I2.bitmap[b]);
226 }
227}
228
243{
244 if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
245 throw(vpException(vpException::dimensionError, "The two images do not have the same size"));
246 }
247
248 if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth())) {
249 Idiff.resize(I1.getHeight(), I1.getWidth());
250 }
251
252 unsigned int n = I1.getHeight() * I1.getWidth();
253 for (unsigned int b = 0; b < n; b++) {
254 int diffR = I1.bitmap[b].R - I2.bitmap[b].R;
255 int diffG = I1.bitmap[b].G - I2.bitmap[b].G;
256 int diffB = I1.bitmap[b].B - I2.bitmap[b].B;
257 // int diffA = I1.bitmap[b].A - I2.bitmap[b].A;
258 Idiff.bitmap[b].R = static_cast<unsigned char>(vpMath::abs(diffR));
259 Idiff.bitmap[b].G = static_cast<unsigned char>(vpMath::abs(diffG));
260 Idiff.bitmap[b].B = static_cast<unsigned char>(vpMath::abs(diffB));
261 // Idiff.bitmap[b].A = diffA;
262 Idiff.bitmap[b].A = 0;
263 }
264}
265
280 vpImage<unsigned char> &Ires, bool saturate)
281{
282 if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
283 throw(vpException(vpException::dimensionError, "The two images do not have the same size"));
284 }
285
286 if ((I1.getHeight() != Ires.getHeight()) || (I1.getWidth() != Ires.getWidth())) {
287 Ires.resize(I1.getHeight(), I1.getWidth());
288 }
289
290 typedef Simd::View<Simd::Allocator> View;
291 View img1(I1.getWidth(), I1.getHeight(), I1.getWidth(), View::Gray8, I1.bitmap);
292 View img2(I2.getWidth(), I2.getHeight(), I2.getWidth(), View::Gray8, I2.bitmap);
293 View imgAdd(Ires.getWidth(), Ires.getHeight(), Ires.getWidth(), View::Gray8, Ires.bitmap);
294
295 Simd::OperationBinary8u(img1, img2, imgAdd,
296 saturate ? SimdOperationBinary8uSaturatedAddition : SimdOperationBinary8uAddition);
297}
298
313 vpImage<unsigned char> &Ires, bool saturate)
314{
315 if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
316 throw(vpException(vpException::dimensionError, "The two images do not have the same size"));
317 }
318
319 if ((I1.getHeight() != Ires.getHeight()) || (I1.getWidth() != Ires.getWidth())) {
320 Ires.resize(I1.getHeight(), I1.getWidth());
321 }
322
323 typedef Simd::View<Simd::Allocator> View;
324 View img1(I1.getWidth(), I1.getHeight(), I1.getWidth(), View::Gray8, I1.bitmap);
325 View img2(I2.getWidth(), I2.getHeight(), I2.getWidth(), View::Gray8, I2.bitmap);
326 View imgAdd(Ires.getWidth(), Ires.getHeight(), Ires.getWidth(), View::Gray8, Ires.bitmap);
327
328 Simd::OperationBinary8u(img1, img2, imgAdd,
329 saturate ? SimdOperationBinary8uSaturatedSubtraction : SimdOperationBinary8uSubtraction);
330}
331
343void vpImageTools::initUndistortMap(const vpCameraParameters &cam, unsigned int width, unsigned int height,
345 vpArray2D<float> &mapDv)
346{
347 mapU.resize(height, width, false, false);
348 mapV.resize(height, width, false, false);
349 mapDu.resize(height, width, false, false);
350 mapDv.resize(height, width, false, false);
351
353 bool is_KannalaBrandt =
354 (projModel == vpCameraParameters::ProjWithKannalaBrandtDistortion); // Check the projection model used
355
356 float u0 = static_cast<float>(cam.get_u0());
357 float v0 = static_cast<float>(cam.get_v0());
358 float px = static_cast<float>(cam.get_px());
359 float py = static_cast<float>(cam.get_py());
360 float kud = 0;
361 std::vector<double> dist_coefs;
362
363 if (!is_KannalaBrandt)
364 kud = static_cast<float>(cam.get_kud());
365
366 else
368
369 if (!is_KannalaBrandt && std::fabs(static_cast<double>(kud)) <= std::numeric_limits<double>::epsilon()) {
370 // There is no need to undistort the image (Perpective projection)
371 for (unsigned int i = 0; i < height; i++) {
372 for (unsigned int j = 0; j < width; j++) {
373 mapU[i][j] = static_cast<int>(j);
374 mapV[i][j] = static_cast<int>(i);
375 mapDu[i][j] = 0;
376 mapDv[i][j] = 0;
377 }
378 }
379
380 return;
381 }
382
383 float invpx, invpy;
384 float kud_px2 = 0., kud_py2 = 0., deltau_px, deltav_py = 0;
385 float fr1 = 0, fr2;
386 float deltav, deltau;
387 float u_float, v_float;
388 int u_round, v_round;
389 double r, scale;
390 double theta, theta_d;
391 double theta2, theta4, theta6, theta8;
392
393 invpx = 1.0f / px;
394 invpy = 1.0f / py;
395
396 if (!is_KannalaBrandt) {
397 kud_px2 = kud * invpx * invpx;
398 kud_py2 = kud * invpy * invpy;
399 }
400
401 for (unsigned int v = 0; v < height; v++) {
402 deltav = v - v0;
403
404 if (!is_KannalaBrandt)
405 fr1 = 1.0f + kud_py2 * deltav * deltav;
406 else
407 deltav_py = deltav * invpy;
408
409 for (unsigned int u = 0; u < width; u++) {
410 // computation of u,v : corresponding pixel coordinates in I.
411 deltau = u - u0;
412 if (!is_KannalaBrandt) {
413 fr2 = fr1 + kud_px2 * deltau * deltau;
414
415 u_float = deltau * fr2 + u0;
416 v_float = deltav * fr2 + v0;
417 }
418
419 else {
420 deltau_px = deltau * invpx;
421 r = sqrt(vpMath::sqr(deltau_px) + vpMath::sqr(deltav_py));
422 theta = atan(r);
423
424 theta2 = vpMath::sqr(theta);
425 theta4 = vpMath::sqr(theta2);
426 theta6 = theta2 * theta4;
427 theta8 = vpMath::sqr(theta4);
428
429 theta_d = theta * (1 + dist_coefs[0] * theta2 + dist_coefs[1] * theta4 + dist_coefs[2] * theta6 +
430 dist_coefs[3] * theta8);
431
432 // scale = (r == 0) ? 1.0 : theta_d / r;
433 scale = (std::fabs(r) < std::numeric_limits<double>::epsilon()) ? 1.0 : theta_d / r;
434 u_float = static_cast<float>(deltau * scale + u0);
435 v_float = static_cast<float>(deltav * scale + v0);
436 }
437
438 u_round = static_cast<int>(u_float);
439 v_round = static_cast<int>(v_float);
440
441 mapU[v][u] = u_round;
442 mapV[v][u] = v_round;
443
444 mapDu[v][u] = u_float - u_round;
445 mapDv[v][u] = v_float - v_round;
446 }
447 }
448}
449
462{
463 if (I.getSize() == 0) {
464 std::cerr << "Error, input image is empty." << std::endl;
465 return;
466 }
467
468 II.resize(I.getHeight() + 1, I.getWidth() + 1, 0.0);
469 IIsq.resize(I.getHeight() + 1, I.getWidth() + 1, 0.0);
470
471 for (unsigned int i = 1; i < II.getHeight(); i++) {
472 for (unsigned int j = 1; j < II.getWidth(); j++) {
473 II[i][j] = I[i - 1][j - 1] + II[i - 1][j] + II[i][j - 1] - II[i - 1][j - 1];
474 IIsq[i][j] = vpMath::sqr(I[i - 1][j - 1]) + IIsq[i - 1][j] + IIsq[i][j - 1] - IIsq[i - 1][j - 1];
475 }
476 }
477}
478
486double vpImageTools::normalizedCorrelation(const vpImage<double> &I1, const vpImage<double> &I2, bool useOptimized)
487{
488 if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
490 "Error: in vpImageTools::normalizedCorrelation(): "
491 "image dimension mismatch between I1=%ux%u and I2=%ux%u",
492 I1.getHeight(), I1.getWidth(), I2.getHeight(), I2.getWidth());
493 }
494
495 const double a = I1.getMeanValue();
496 const double b = I2.getMeanValue();
497
498 double ab = 0.0;
499 double a2 = 0.0;
500 double b2 = 0.0;
501
502 SimdNormalizedCorrelation(I1.bitmap, a, I2.bitmap, b, I1.getSize(), a2, b2, ab, useOptimized);
503
504 return ab / sqrt(a2 * b2);
505}
506
514{
515 unsigned int height = I.getHeight(), width = I.getWidth();
516 V.resize(width); // resize and nullify
517
518 for (unsigned int i = 0; i < height; ++i)
519 for (unsigned int j = 0; j < width; ++j)
520 V[j] += I[i][j];
521 for (unsigned int j = 0; j < width; ++j)
522 V[j] /= height;
523}
524
530{
531 double s = I.getSum();
532 for (unsigned int i = 0; i < I.getHeight(); ++i)
533 for (unsigned int j = 0; j < I.getWidth(); ++j)
534 I(i, j, I(i, j) / s);
535}
536
545 const vpImageInterpolationType &method)
546{
547 switch (method) {
549 return I(vpMath::round(point.get_i()), vpMath::round(point.get_j()));
551 int x1 = (int)floor(point.get_i());
552 int x2 = (int)ceil(point.get_i());
553 int y1 = (int)floor(point.get_j());
554 int y2 = (int)ceil(point.get_j());
555 double v1, v2;
556 if (x1 == x2) {
557 v1 = I(x1, y1);
558 v2 = I(x1, y2);
559 } else {
560 v1 = (x2 - point.get_i()) * I(x1, y1) + (point.get_i() - x1) * I(x2, y1);
561 v2 = (x2 - point.get_i()) * I(x1, y2) + (point.get_i() - x1) * I(x2, y2);
562 }
563 if (y1 == y2)
564 return v1;
565 return (y2 - point.get_j()) * v1 + (point.get_j() - y1) * v2;
566 }
567 case INTERPOLATION_CUBIC: {
569 "vpImageTools::interpolate(): bi-cubic interpolation is not implemented.");
570 }
571 default: {
572 throw vpException(vpException::notImplementedError, "vpImageTools::interpolate(): invalid interpolation type");
573 }
574 }
575}
576
584{
585 unsigned int x_d = vpMath::round(r.getHeight());
586 unsigned int y_d = vpMath::round(r.getWidth());
587 double x1 = r.getTopLeft().get_i();
588 double y1 = r.getTopLeft().get_j();
589 double t = r.getOrientation();
590 Dst.resize(x_d, y_d);
591 for (unsigned int x = 0; x < x_d; ++x) {
592 for (unsigned int y = 0; y < y_d; ++y) {
593 Dst(x, y,
594 (unsigned char)interpolate(Src, vpImagePoint(x1 + x * cos(t) + y * sin(t), y1 - x * sin(t) + y * cos(t)),
596 }
597 }
598}
599
607{
608 unsigned int x_d = vpMath::round(r.getHeight());
609 unsigned int y_d = vpMath::round(r.getWidth());
610 double x1 = r.getTopLeft().get_i();
611 double y1 = r.getTopLeft().get_j();
612 double t = r.getOrientation();
613 Dst.resize(x_d, y_d);
614 for (unsigned int x = 0; x < x_d; ++x) {
615 for (unsigned int y = 0; y < y_d; ++y) {
616 Dst(x, y,
617 interpolate(Src, vpImagePoint(x1 + x * cos(t) + y * sin(t), y1 - x * sin(t) + y * cos(t)),
619 }
620 }
621}
622
638 vpImage<double> &I_score, unsigned int step_u, unsigned int step_v,
639 bool useOptimized)
640{
641 if (I.getSize() == 0) {
642 std::cerr << "Error, input image is empty." << std::endl;
643 return;
644 }
645
646 if (I_tpl.getSize() == 0) {
647 std::cerr << "Error, template image is empty." << std::endl;
648 return;
649 }
650
651 if (I_tpl.getHeight() > I.getHeight() || I_tpl.getWidth() > I.getWidth()) {
652 std::cerr << "Error, template image is bigger than input image." << std::endl;
653 return;
654 }
655
656 vpImage<double> I_double, I_tpl_double;
657 vpImageConvert::convert(I, I_double);
658 vpImageConvert::convert(I_tpl, I_tpl_double);
659
660 unsigned int height_tpl = I_tpl.getHeight(), width_tpl = I_tpl.getWidth();
661 I_score.resize(I.getHeight() - height_tpl, I.getWidth() - width_tpl, 0.0);
662
663 if (useOptimized) {
664 vpImage<double> II, IIsq;
665 integralImage(I, II, IIsq);
666
667 vpImage<double> II_tpl, IIsq_tpl;
668 integralImage(I_tpl, II_tpl, IIsq_tpl);
669
670 // zero-mean template image
671 const double sum2 = (II_tpl[height_tpl][width_tpl] + II_tpl[0][0] - II_tpl[0][width_tpl] - II_tpl[height_tpl][0]);
672 const double mean2 = sum2 / I_tpl.getSize();
673 for (unsigned int cpt = 0; cpt < I_tpl_double.getSize(); cpt++) {
674 I_tpl_double.bitmap[cpt] -= mean2;
675 }
676
677#if defined _OPENMP && _OPENMP >= 200711 // OpenMP 3.1
678#pragma omp parallel for schedule(dynamic)
679 for (unsigned int i = 0; i < I.getHeight() - height_tpl; i += step_v) {
680 for (unsigned int j = 0; j < I.getWidth() - width_tpl; j += step_u) {
681 I_score[i][j] = normalizedCorrelation(I_double, I_tpl_double, II, IIsq, II_tpl, IIsq_tpl, i, j);
682 }
683 }
684#else
685 // error C3016: 'i': index variable in OpenMP 'for' statement must have signed integral type
686 int end = (int)((I.getHeight() - height_tpl) / step_v) + 1;
687 std::vector<unsigned int> vec_step_v((size_t)end);
688 for (unsigned int cpt = 0, idx = 0; cpt < I.getHeight() - height_tpl; cpt += step_v, idx++) {
689 vec_step_v[(size_t)idx] = cpt;
690 }
691#if defined _OPENMP // only to disable warning: ignoring #pragma omp parallel [-Wunknown-pragmas]
692#pragma omp parallel for schedule(dynamic)
693#endif
694 for (int cpt = 0; cpt < end; cpt++) {
695 for (unsigned int j = 0; j < I.getWidth() - width_tpl; j += step_u) {
696 I_score[vec_step_v[cpt]][j] =
697 normalizedCorrelation(I_double, I_tpl_double, II, IIsq, II_tpl, IIsq_tpl, vec_step_v[cpt], j);
698 }
699 }
700#endif
701 } else {
702 vpImage<double> I_cur;
703
704 for (unsigned int i = 0; i < I.getHeight() - height_tpl; i += step_v) {
705 for (unsigned int j = 0; j < I.getWidth() - width_tpl; j += step_u) {
706 vpRect roi(vpImagePoint(i, j), vpImagePoint(i + height_tpl - 1, j + width_tpl - 1));
707 vpImageTools::crop(I_double, roi, I_cur);
708
709 I_score[i][j] = vpImageTools::normalizedCorrelation(I_cur, I_tpl_double, useOptimized);
710 }
711 }
712 }
713}
714
715// Reference:
716// http://blog.demofox.org/2015/08/15/resizing-images-with-bicubic-interpolation/
717// t is a value that goes from 0 to 1 to interpolate in a C1 continuous way
718// across uniformly sampled data points. when t is 0, this will return B.
719// When t is 1, this will return C. In between values will return an
720// interpolation between B and C. A and B are used to calculate the slopes at
721// the edges.
722float vpImageTools::cubicHermite(const float A, const float B, const float C, const float D, const float t)
723{
724 float a = (-A + 3.0f * B - 3.0f * C + D) / 2.0f;
725 float b = A + 2.0f * C - (5.0f * B + D) / 2.0f;
726 float c = (-A + C) / 2.0f;
727 float d = B;
728
729 return a * t * t * t + b * t * t + c * t + d;
730}
731
732int vpImageTools::coordCast(double x) { return x < 0 ? -1 : static_cast<int>(x); }
733
734double vpImageTools::lerp(double A, double B, double t) { return A * (1.0 - t) + B * t; }
735
736float vpImageTools::lerp(float A, float B, float t) { return A * (1.0f - t) + B * t; }
737
738int64_t vpImageTools::lerp2(int64_t A, int64_t B, int64_t t, int64_t t_1) { return A * t_1 + B * t; }
739
741 const vpImage<double> &II, const vpImage<double> &IIsq,
742 const vpImage<double> &II_tpl, const vpImage<double> &IIsq_tpl,
743 unsigned int i0, unsigned int j0)
744{
745 double ab = 0.0;
746 SimdNormalizedCorrelation2(I1.bitmap, I1.getWidth(), I2.bitmap, I2.getWidth(), I2.getHeight(), i0, j0, ab);
747
748 unsigned int height_tpl = I2.getHeight(), width_tpl = I2.getWidth();
749 const double sum1 =
750 (II[i0 + height_tpl][j0 + width_tpl] + II[i0][j0] - II[i0][j0 + width_tpl] - II[i0 + height_tpl][j0]);
751 const double sum2 = (II_tpl[height_tpl][width_tpl] + II_tpl[0][0] - II_tpl[0][width_tpl] - II_tpl[height_tpl][0]);
752
753 double a2 = ((IIsq[i0 + I2.getHeight()][j0 + I2.getWidth()] + IIsq[i0][j0] - IIsq[i0][j0 + I2.getWidth()] -
754 IIsq[i0 + I2.getHeight()][j0]) -
755 (1.0 / I2.getSize()) * vpMath::sqr(sum1));
756
757 double b2 = ((IIsq_tpl[I2.getHeight()][I2.getWidth()] + IIsq_tpl[0][0] - IIsq_tpl[0][I2.getWidth()] -
758 IIsq_tpl[I2.getHeight()][0]) -
759 (1.0 / I2.getSize()) * vpMath::sqr(sum2));
760 return ab / sqrt(a2 * b2);
761}
762
774 const vpArray2D<float> &mapDu, const vpArray2D<float> &mapDv, vpImage<unsigned char> &Iundist)
775{
776 Iundist.resize(I.getHeight(), I.getWidth());
777
778#if defined _OPENMP // only to disable warning: ignoring #pragma omp parallel [-Wunknown-pragmas]
779#pragma omp parallel for schedule(dynamic)
780#endif
781 for (int i_ = 0; i_ < static_cast<int>(I.getHeight()); i_++) {
782 const unsigned int i = static_cast<unsigned int>(i_);
783 for (unsigned int j = 0; j < I.getWidth(); j++) {
784
785 int u_round = mapU[i][j];
786 int v_round = mapV[i][j];
787
788 float du = mapDu[i][j];
789 float dv = mapDv[i][j];
790
791 if (0 <= u_round && 0 <= v_round && u_round < static_cast<int>(I.getWidth()) - 1 &&
792 v_round < static_cast<int>(I.getHeight()) - 1) {
793 // process interpolation
794 float col0 = lerp(I[v_round][u_round], I[v_round][u_round + 1], du);
795 float col1 = lerp(I[v_round + 1][u_round], I[v_round + 1][u_round + 1], du);
796 float value = lerp(col0, col1, dv);
797
798 Iundist[i][j] = static_cast<unsigned char>(value);
799 } else {
800 Iundist[i][j] = 0;
801 }
802 }
803 }
804}
805
816void vpImageTools::remap(const vpImage<vpRGBa> &I, const vpArray2D<int> &mapU, const vpArray2D<int> &mapV,
817 const vpArray2D<float> &mapDu, const vpArray2D<float> &mapDv, vpImage<vpRGBa> &Iundist)
818{
819 Iundist.resize(I.getHeight(), I.getWidth());
820
821#if defined _OPENMP // only to disable warning: ignoring #pragma omp parallel [-Wunknown-pragmas]
822#pragma omp parallel for schedule(dynamic)
823#endif
824 for (int i = 0; i < static_cast<int>(I.getHeight()); i++) {
825 SimdRemap(reinterpret_cast<unsigned char *>(I.bitmap), 4, I.getWidth(), I.getHeight(), i * I.getWidth(), mapU.data,
826 mapV.data, mapDu.data, mapDv.data, reinterpret_cast<unsigned char *>(Iundist.bitmap));
827 }
828}
829
830void vpImageTools::resizeSimdlib(const vpImage<vpRGBa> &Isrc, unsigned int resizeWidth, unsigned int resizeHeight,
831 vpImage<vpRGBa> &Idst, int method)
832{
833 Idst.resize(resizeHeight, resizeWidth);
834
835 typedef Simd::View<Simd::Allocator> View;
836 View src(Isrc.getWidth(), Isrc.getHeight(), Isrc.getWidth() * sizeof(vpRGBa), View::Bgra32, Isrc.bitmap);
837 View dst(Idst.getWidth(), Idst.getHeight(), Idst.getWidth() * sizeof(vpRGBa), View::Bgra32, Idst.bitmap);
838
839 Simd::Resize(src, dst, method == INTERPOLATION_LINEAR ? SimdResizeMethodBilinear : SimdResizeMethodArea);
840}
841
842void vpImageTools::resizeSimdlib(const vpImage<unsigned char> &Isrc, unsigned int resizeWidth,
843 unsigned int resizeHeight, vpImage<unsigned char> &Idst, int method)
844{
845 Idst.resize(resizeHeight, resizeWidth);
846
847 typedef Simd::View<Simd::Allocator> View;
848 View src(Isrc.getWidth(), Isrc.getHeight(), Isrc.getWidth(), View::Gray8, Isrc.bitmap);
849 View dst(Idst.getWidth(), Idst.getHeight(), Idst.getWidth(), View::Gray8, Idst.bitmap);
850
851 Simd::Resize(src, dst, method == INTERPOLATION_LINEAR ? SimdResizeMethodBilinear : SimdResizeMethodArea);
852}
853
854bool vpImageTools::checkFixedPoint(unsigned int x, unsigned int y, const vpMatrix &T, bool affine)
855{
856 double a0 = T[0][0];
857 double a1 = T[0][1];
858 double a2 = T[0][2];
859 double a3 = T[1][0];
860 double a4 = T[1][1];
861 double a5 = T[1][2];
862 double a6 = affine ? 0.0 : T[2][0];
863 double a7 = affine ? 0.0 : T[2][1];
864 double a8 = affine ? 1.0 : T[2][2];
865
866 double w = a6 * x + a7 * y + a8;
867 double x2 = (a0 * x + a1 * y + a2) / w;
868 double y2 = (a3 * x + a4 * y + a5) / w;
869
870 const double limit = 1 << 15;
871 return (vpMath::abs(x2) < limit) && (vpMath::abs(y2) < limit);
872}
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition vpArray2D.h:131
Type * data
Address of the first element of the data array.
Definition vpArray2D.h:144
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition vpArray2D.h:305
Generic class defining intrinsic camera parameters.
@ ProjWithKannalaBrandtDistortion
Projection with Kannala-Brandt distortion model.
std::vector< double > getKannalaBrandtDistortionCoefficients() const
vpCameraParametersProjType get_projModel() const
error that can be emitted by ViSP classes.
Definition vpException.h:59
@ dimensionError
Bad dimension.
Definition vpException.h:83
@ notImplementedError
Not implemented.
Definition vpException.h:81
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Error that can be emitted by the vpImage class and its derivatives.
@ incorrectInitializationError
Wrong image initialization.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
double get_j() const
double get_i() const
static void imageDifference(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Idiff)
static void templateMatching(const vpImage< unsigned char > &I, const vpImage< unsigned char > &I_tpl, vpImage< double > &I_score, unsigned int step_u, unsigned int step_v, bool useOptimized=true)
static void initUndistortMap(const vpCameraParameters &cam, unsigned int width, unsigned int height, vpArray2D< int > &mapU, vpArray2D< int > &mapV, vpArray2D< float > &mapDu, vpArray2D< float > &mapDv)
static void crop(const vpImage< Type > &I, double roi_top, double roi_left, unsigned int roi_height, unsigned int roi_width, vpImage< Type > &crop, unsigned int v_scale=1, unsigned int h_scale=1)
static double interpolate(const vpImage< unsigned char > &I, const vpImagePoint &point, const vpImageInterpolationType &method=INTERPOLATION_NEAREST)
static void integralImage(const vpImage< unsigned char > &I, vpImage< double > &II, vpImage< double > &IIsq)
static void imageSubtract(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Ires, bool saturate=false)
static void imageAdd(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Ires, bool saturate=false)
static void extract(const vpImage< unsigned char > &Src, vpImage< unsigned char > &Dst, const vpRectOriented &r)
static void columnMean(const vpImage< double > &I, vpRowVector &result)
static void normalize(vpImage< double > &I)
static void remap(const vpImage< unsigned char > &I, const vpArray2D< int > &mapU, const vpArray2D< int > &mapV, const vpArray2D< float > &mapDu, const vpArray2D< float > &mapDv, vpImage< unsigned char > &Iundist)
static void changeLUT(vpImage< unsigned char > &I, unsigned char A, unsigned char newA, unsigned char B, unsigned char newB)
static double normalizedCorrelation(const vpImage< double > &I1, const vpImage< double > &I2, bool useOptimized=true)
static void imageDifferenceAbsolute(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Idiff)
Definition of the vpImage class member functions.
Definition vpImage.h:135
Type getMeanValue() const
Return the mean value of the bitmap.
Definition vpImage.h:963
unsigned int getWidth() const
Definition vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:795
double getSum() const
Definition vpImage.h:1885
unsigned int getSize() const
Definition vpImage.h:223
Type * bitmap
points toward the bitmap
Definition vpImage.h:139
unsigned int getHeight() const
Definition vpImage.h:184
static double sqr(double x)
Definition vpMath.h:124
static Type abs(const Type &x)
Definition vpMath.h:187
static int round(double x)
Definition vpMath.h:323
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:152
Defines an oriented rectangle in the plane.
double getHeight() const
Get the rectangle height.
double getOrientation() const
Get the rectangle orientation (rad).
double getWidth() const
Get the rectangle width.
vpImagePoint getTopLeft() const
Get the top-left corner.
Defines a rectangle in the plane.
Definition vpRect.h:76
Implementation of row vector and the associated operations.
void resize(unsigned int i, bool flagNullify=true)
#define vpERROR_TRACE
Definition vpDebug.h:388