39 #ifndef vpImageTools_H
40 #define vpImageTools_H
49 #include <visp3/core/vpImage.h>
51 #ifdef VISP_HAVE_PTHREAD
55 #include <visp3/core/vpCameraParameters.h>
56 #include <visp3/core/vpImageException.h>
57 #include <visp3/core/vpMath.h>
58 #include <visp3/core/vpRect.h>
59 #include <visp3/core/vpRectOriented.h>
89 static inline void binarise(
vpImage<Type> &I, Type threshold1, Type threshold2, Type value1, Type value2, Type value3,
95 static void crop(
const vpImage<Type> &I,
double roi_top,
double roi_left,
unsigned int roi_height,
96 unsigned int roi_width,
vpImage<Type> &crop,
unsigned int v_scale = 1,
unsigned int h_scale = 1);
100 template <
class Type>
102 vpImage<Type> &crop,
unsigned int v_scale = 1,
unsigned int h_scale = 1);
103 template <
class Type>
105 unsigned int h_scale = 1);
106 template <
class Type>
107 static void crop(
const unsigned char *bitmap,
unsigned int width,
unsigned int height,
const vpRect &roi,
108 vpImage<Type> &crop,
unsigned int v_scale = 1,
unsigned int h_scale = 1);
127 bool saturate =
false);
132 static void initUndistortMap(
const vpCameraParameters &cam,
unsigned int width,
unsigned int height,
137 const vpImageInterpolationType &method = INTERPOLATION_NEAREST);
142 bool useOptimized =
true);
151 template <
class Type>
153 const vpImageInterpolationType &method = INTERPOLATION_NEAREST,
unsigned int nThreads=0);
155 template <
class Type>
157 const vpImageInterpolationType &method = INTERPOLATION_NEAREST,
unsigned int nThreads=0);
161 bool useOptimized =
true);
163 template <
class Type>
165 unsigned int nThreads=2);
167 template <
class Type>
171 template <
class Type>
173 const vpImageInterpolationType &interpolation=INTERPOLATION_NEAREST,
174 bool fixedPointArithmetic=
true,
bool pixelCenter=
false);
176 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
181 template <
class Type>
183 unsigned int nrow_sub,
unsigned int ncol_sub,
vpImage<Type> &S);
185 template <
class Type>
192 static float cubicHermite(
const float A,
const float B,
const float C,
const float D,
const float t);
194 template <
class Type>
static Type getPixelClamped(
const vpImage<Type> &I,
float u,
float v);
196 static int coordCast(
double x);
199 static double lerp(
double A,
double B,
double t);
200 static float lerp(
float A,
float B,
float t);
201 static int64_t lerp2(int64_t A, int64_t B, int64_t t, int64_t t_1);
207 template <
class Type>
209 float u,
float v,
float xFrac,
float yFrac);
211 template <
class Type>
213 float u,
float v,
float xFrac,
float yFrac);
215 template <
class Type>
219 static void resizeSimdlib(
const vpImage<vpRGBa>& Isrc,
unsigned int resizeWidth,
unsigned int resizeHeight,
221 static void resizeSimdlib(
const vpImage<unsigned char>& Isrc,
unsigned int resizeWidth,
unsigned int resizeHeight,
224 template <
class Type>
227 template <
class Type>
230 static bool checkFixedPoint(
unsigned int x,
unsigned int y,
const vpMatrix &T,
bool affine);
233 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
253 template <
class Type>
255 unsigned int roi_height,
unsigned int roi_width,
vpImage<Type> &crop)
304 template <
class Type>
306 unsigned int roi_width,
vpImage<Type> &crop,
unsigned int v_scale,
unsigned int h_scale)
308 int i_min = (std::max)((
int)(ceil(roi_top / v_scale)), 0);
309 int j_min = (std::max)((
int)(ceil(roi_left / h_scale)), 0);
310 int i_max = (std::min)((
int)(ceil((roi_top + roi_height)) / v_scale), (
int)(I.
getHeight() / v_scale));
311 int j_max = (std::min)((
int)(ceil((roi_left + roi_width) / h_scale)), (
int)(I.
getWidth() / h_scale));
313 unsigned int i_min_u = (
unsigned int)i_min;
314 unsigned int j_min_u = (
unsigned int)j_min;
316 unsigned int r_width = (
unsigned int)(j_max - j_min);
317 unsigned int r_height = (
unsigned int)(i_max - i_min);
319 crop.resize(r_height, r_width);
321 if (v_scale == 1 && h_scale == 1) {
322 for (
unsigned int i = 0; i < r_height; i++) {
323 void *src = (
void *)(I[i + i_min_u] + j_min_u);
324 void *dst = (
void *)
crop[i];
325 memcpy(dst, src, r_width *
sizeof(Type));
327 }
else if (h_scale == 1) {
328 for (
unsigned int i = 0; i < r_height; i++) {
329 void *src = (
void *)(I[(i + i_min_u) * v_scale] + j_min_u);
330 void *dst = (
void *)
crop[i];
331 memcpy(dst, src, r_width *
sizeof(Type));
334 for (
unsigned int i = 0; i < r_height; i++) {
335 for (
unsigned int j = 0; j < r_width; j++) {
336 crop[i][j] = I[(i + i_min_u) * v_scale][(j + j_min_u) * h_scale];
359 template <
class Type>
361 unsigned int roi_width,
vpImage<Type> &crop,
unsigned int v_scale,
unsigned int h_scale)
382 template <
class Type>
384 unsigned int h_scale)
407 template <
class Type>
409 vpImage<Type> &crop,
unsigned int v_scale,
unsigned int h_scale)
411 int i_min = (std::max)((
int)(ceil(roi.
getTop() / v_scale)), 0);
412 int j_min = (std::max)((
int)(ceil(roi.
getLeft() / h_scale)), 0);
413 int i_max = (std::min)((
int)(ceil((roi.
getTop() + roi.
getHeight()) / v_scale)), (
int)(height / v_scale));
414 int j_max = (std::min)((
int)(ceil((roi.
getLeft() + roi.
getWidth()) / h_scale)), (
int)(width / h_scale));
416 unsigned int i_min_u = (
unsigned int)i_min;
417 unsigned int j_min_u = (
unsigned int)j_min;
419 unsigned int r_width = (
unsigned int)(j_max - j_min);
420 unsigned int r_height = (
unsigned int)(i_max - i_min);
422 crop.resize(r_height, r_width);
424 if (v_scale == 1 && h_scale == 1) {
425 for (
unsigned int i = 0; i < r_height; i++) {
426 void *src = (
void *)(bitmap + ((i + i_min_u) * width + j_min_u) *
sizeof(Type));
427 void *dst = (
void *)
crop[i];
428 memcpy(dst, src, r_width *
sizeof(Type));
430 }
else if (h_scale == 1) {
431 for (
unsigned int i = 0; i < r_height; i++) {
432 void *src = (
void *)(bitmap + ((i + i_min_u) * width * v_scale + j_min_u) *
sizeof(Type));
433 void *dst = (
void *)
crop[i];
434 memcpy(dst, src, r_width *
sizeof(Type));
437 for (
unsigned int i = 0; i < r_height; i++) {
438 unsigned int i_src = (i + i_min_u) * width * v_scale + j_min_u * h_scale;
439 for (
unsigned int j = 0; j < r_width; j++) {
440 void *src = (
void *)(bitmap + (i_src + j * h_scale) *
sizeof(Type));
441 void *dst = (
void *)&
crop[i][j];
442 memcpy(dst, src,
sizeof(Type));
458 template <
class Type>
460 Type value3,
bool useLUT)
463 std::cerr <<
"LUT not available for this type ! Will use the iteration method." << std::endl;
469 for (; p < pend; p++) {
473 else if (v > threshold2)
492 unsigned char value1,
unsigned char value2,
unsigned char value3,
bool useLUT)
496 unsigned char lut[256];
497 for (
unsigned int i = 0; i < 256; i++) {
498 lut[i] = i < threshold1 ? value1 : (i > threshold2 ? value3 : value2);
503 unsigned char *p = I.
bitmap;
505 for (; p < pend; p++) {
506 unsigned char v = *p;
509 else if (v > threshold2)
517 #ifdef VISP_HAVE_PTHREAD
519 #ifndef DOXYGEN_SHOULD_SKIP_THIS
520 template <
class Type>
class vpUndistortInternalType
528 unsigned int nthreads;
529 unsigned int threadid;
532 vpUndistortInternalType() : src(NULL), dst(NULL), width(0), height(0), cam(), nthreads(0), threadid(0) {}
534 vpUndistortInternalType(
const vpUndistortInternalType<Type> &u) { *
this = u; }
535 vpUndistortInternalType &operator=(
const vpUndistortInternalType<Type> &u)
542 nthreads = u.nthreads;
543 threadid = u.threadid;
548 static void *vpUndistort_threaded(
void *arg);
551 template <
class Type>
void *vpUndistortInternalType<Type>::vpUndistort_threaded(
void *arg)
553 vpUndistortInternalType<Type> *undistortSharedData =
static_cast<vpUndistortInternalType<Type> *
>(arg);
554 int offset = (int)undistortSharedData->threadid;
555 int width = (
int)undistortSharedData->width;
556 int height = (int)undistortSharedData->height;
557 int nthreads = (
int)undistortSharedData->nthreads;
559 double u0 = undistortSharedData->cam.get_u0();
560 double v0 = undistortSharedData->cam.get_v0();
561 double px = undistortSharedData->cam.get_px();
562 double py = undistortSharedData->cam.get_py();
563 double kud = undistortSharedData->cam.get_kud();
565 double invpx = 1.0 / px;
566 double invpy = 1.0 / py;
568 double kud_px2 = kud * invpx * invpx;
569 double kud_py2 = kud * invpy * invpy;
571 Type *dst = undistortSharedData->dst + (height / nthreads * offset) * width;
572 Type *src = undistortSharedData->src;
574 for (
double v = height / nthreads * offset; v < height / nthreads * (offset + 1); v++) {
575 double deltav = v - v0;
577 double fr1 = 1.0 + kud_py2 * deltav * deltav;
579 for (
double u = 0; u < width; u++) {
581 double deltau = u - u0;
583 double fr2 = fr1 + kud_px2 * deltau * deltau;
585 double u_double = deltau * fr2 + u0;
586 double v_double = deltav * fr2 + v0;
591 int u_round = (int)(u_double);
592 int v_round = (int)(v_double);
597 double du_double = (u_double) - (
double)u_round;
598 double dv_double = (v_double) - (
double)v_round;
601 if ((0 <= u_round) && (0 <= v_round) && (u_round < ((width)-1)) && (v_round < ((height)-1))) {
603 const Type *_mp = &src[v_round * width + u_round];
604 v01 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
606 v23 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
607 *dst = (Type)(v01 + ((v23 - v01) * dv_double));
615 pthread_exit((
void *)0);
644 template <
class Type>
646 unsigned int nThreads)
648 #ifdef VISP_HAVE_PTHREAD
655 undistI.
resize(height, width);
660 if (std::fabs(kud) <= std::numeric_limits<double>::epsilon()) {
666 unsigned int nthreads = nThreads;
668 pthread_t *callThd =
new pthread_t[nthreads];
669 pthread_attr_init(&attr);
670 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
672 vpUndistortInternalType<Type> *undistortSharedData;
673 undistortSharedData =
new vpUndistortInternalType<Type>[nthreads];
675 for (
unsigned int i = 0; i < nthreads; i++) {
678 undistortSharedData[i].src = I.
bitmap;
679 undistortSharedData[i].dst = undistI.
bitmap;
680 undistortSharedData[i].width = I.
getWidth();
681 undistortSharedData[i].height = I.
getHeight();
682 undistortSharedData[i].cam = cam;
683 undistortSharedData[i].nthreads = nthreads;
684 undistortSharedData[i].threadid = i;
685 pthread_create(&callThd[i], &attr, &vpUndistortInternalType<Type>::vpUndistort_threaded, &undistortSharedData[i]);
687 pthread_attr_destroy(&attr);
690 for (
unsigned int i = 0; i < nthreads; i++) {
692 pthread_join(callThd[i], NULL);
696 delete[] undistortSharedData;
705 undistI.
resize(height, width);
714 if (std::fabs(kud) <= std::numeric_limits<double>::epsilon()) {
720 double invpx = 1.0 / px;
721 double invpy = 1.0 / py;
723 double kud_px2 = kud * invpx * invpx;
724 double kud_py2 = kud * invpy * invpy;
726 Type *dst = undistI.
bitmap;
727 for (
double v = 0; v < height; v++) {
728 double deltav = v - v0;
730 double fr1 = 1.0 + kud_py2 * deltav * deltav;
732 for (
double u = 0; u < width; u++) {
734 double deltau = u - u0;
736 double fr2 = fr1 + kud_px2 * deltau * deltau;
738 double u_double = deltau * fr2 + u0;
739 double v_double = deltav * fr2 + v0;
746 int u_round = (int)(u_double);
747 int v_round = (int)(v_double);
752 double du_double = (u_double) - (
double)u_round;
753 double dv_double = (v_double) - (
double)v_round;
756 if ((0 <= u_round) && (0 <= v_round) && (u_round < (((
int)width) - 1)) && (v_round < (((
int)height) - 1))) {
758 const Type *_mp = &I[(
unsigned int)v_round][(
unsigned int)u_round];
759 v01 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
761 v23 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
762 *dst = (Type)(v01 + ((v23 - v01) * dv_double));
777 undistI.
resize(height,width);
791 for(
int v = 0 ; v < height; v++){
792 for(
int u = 0; u < height; u++){
795 double u_double = ((double)u - u0)*(1.0+kd*r2) + u0;
796 double v_double = ((double)v - v0)*(1.0+kd*r2) + v0;
797 undistI[v][u] = I.getPixelBI((
float)u_double,(float)v_double);
817 template <
class Type>
821 remap(I, mapU, mapV, mapDu, mapDv, newI);
832 unsigned int height = 0, width = 0;
836 newI.
resize(height, width);
838 for (
unsigned int i = 0; i < height; i++) {
839 memcpy(newI.
bitmap + i * width, I.
bitmap + (height - 1 - i) * width, width *
sizeof(Type));
876 unsigned int height = 0, width = 0;
884 for (i = 0; i < height / 2; i++) {
885 memcpy(Ibuf.
bitmap, I.
bitmap + i * width, width *
sizeof(Type));
887 memcpy(I.
bitmap + i * width, I.
bitmap + (height - 1 - i) * width, width *
sizeof(Type));
888 memcpy(I.
bitmap + (height - 1 - i) * width, Ibuf.
bitmap, width *
sizeof(Type));
892 template <
class Type> Type vpImageTools::getPixelClamped(
const vpImage<Type> &I,
float u,
float v)
896 x = (std::max)(0, (std::min)(x,
static_cast<int>(I.
getWidth())-1));
897 y = (std::max)(0, (std::min)(y,
static_cast<int>(I.
getHeight())-1));
904 template <
class Type>
906 unsigned int j,
float u,
float v,
float xFrac,
float yFrac)
909 Type p00 = getPixelClamped(I, u - 1, v - 1);
910 Type p01 = getPixelClamped(I, u + 0, v - 1);
911 Type p02 = getPixelClamped(I, u + 1, v - 1);
912 Type p03 = getPixelClamped(I, u + 2, v - 1);
915 Type p10 = getPixelClamped(I, u - 1, v + 0);
916 Type p11 = getPixelClamped(I, u + 0, v + 0);
917 Type p12 = getPixelClamped(I, u + 1, v + 0);
918 Type p13 = getPixelClamped(I, u + 2, v + 0);
921 Type p20 = getPixelClamped(I, u - 1, v + 1);
922 Type p21 = getPixelClamped(I, u + 0, v + 1);
923 Type p22 = getPixelClamped(I, u + 1, v + 1);
924 Type p23 = getPixelClamped(I, u + 2, v + 1);
927 Type p30 = getPixelClamped(I, u - 1, v + 2);
928 Type p31 = getPixelClamped(I, u + 0, v + 2);
929 Type p32 = getPixelClamped(I, u + 1, v + 2);
930 Type p33 = getPixelClamped(I, u + 2, v + 2);
932 float col0 = cubicHermite(p00, p01, p02, p03, xFrac);
933 float col1 = cubicHermite(p10, p11, p12, p13, xFrac);
934 float col2 = cubicHermite(p20, p21, p22, p23, xFrac);
935 float col3 = cubicHermite(p30, p31, p32, p33, xFrac);
936 float value = cubicHermite(col0, col1, col2, col3, yFrac);
937 Ires[i][j] = vpMath::saturate<Type>(value);
942 unsigned int j,
float u,
float v,
float xFrac,
float yFrac)
945 vpRGBa p00 = getPixelClamped(I, u - 1, v - 1);
946 vpRGBa p01 = getPixelClamped(I, u + 0, v - 1);
947 vpRGBa p02 = getPixelClamped(I, u + 1, v - 1);
948 vpRGBa p03 = getPixelClamped(I, u + 2, v - 1);
951 vpRGBa p10 = getPixelClamped(I, u - 1, v + 0);
952 vpRGBa p11 = getPixelClamped(I, u + 0, v + 0);
953 vpRGBa p12 = getPixelClamped(I, u + 1, v + 0);
954 vpRGBa p13 = getPixelClamped(I, u + 2, v + 0);
957 vpRGBa p20 = getPixelClamped(I, u - 1, v + 1);
958 vpRGBa p21 = getPixelClamped(I, u + 0, v + 1);
959 vpRGBa p22 = getPixelClamped(I, u + 1, v + 1);
960 vpRGBa p23 = getPixelClamped(I, u + 2, v + 1);
963 vpRGBa p30 = getPixelClamped(I, u - 1, v + 2);
964 vpRGBa p31 = getPixelClamped(I, u + 0, v + 2);
965 vpRGBa p32 = getPixelClamped(I, u + 1, v + 2);
966 vpRGBa p33 = getPixelClamped(I, u + 2, v + 2);
968 for (
int c = 0; c < 3; c++) {
969 float col0 = cubicHermite(
static_cast<float>(
reinterpret_cast<unsigned char *
>(&p00)[c]),
970 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p01)[c]),
971 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p02)[c]),
972 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p03)[c]), xFrac);
973 float col1 = cubicHermite(
static_cast<float>(
reinterpret_cast<unsigned char *
>(&p10)[c]),
974 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p11)[c]),
975 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p12)[c]),
976 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p13)[c]), xFrac);
977 float col2 = cubicHermite(
static_cast<float>(
reinterpret_cast<unsigned char *
>(&p20)[c]),
978 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p21)[c]),
979 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p22)[c]),
980 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p23)[c]), xFrac);
981 float col3 = cubicHermite(
static_cast<float>(
reinterpret_cast<unsigned char *
>(&p30)[c]),
982 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p31)[c]),
983 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p32)[c]),
984 static_cast<float>(
reinterpret_cast<unsigned char *
>(&p33)[c]), xFrac);
985 float value = cubicHermite(col0, col1, col2, col3, yFrac);
987 reinterpret_cast<unsigned char *
>(&Ires[i][j])[c] = vpMath::saturate<unsigned char>(value);
991 template <
class Type>
993 unsigned int j,
float u,
float v,
float xFrac,
float yFrac)
995 int u0 =
static_cast<int>(u);
996 int v0 =
static_cast<int>(v);
998 int u1 = (std::min)(
static_cast<int>(I.
getWidth()) - 1, u0 + 1);
1002 int v2 = (std::min)(
static_cast<int>(I.
getHeight()) - 1, v0 + 1);
1007 float col0 = lerp(I[v0][u0], I[v1][u1], xFrac);
1008 float col1 = lerp(I[v2][u2], I[v3][u3], xFrac);
1009 float value = lerp(col0, col1, yFrac);
1011 Ires[i][j] = vpMath::saturate<Type>(value);
1016 unsigned int j,
float u,
float v,
float xFrac,
float yFrac)
1018 int u0 =
static_cast<int>(u);
1019 int v0 =
static_cast<int>(v);
1021 int u1 = (std::min)(
static_cast<int>(I.
getWidth()) - 1, u0 + 1);
1025 int v2 = (std::min)(
static_cast<int>(I.
getHeight()) - 1, v0 + 1);
1030 for (
int c = 0; c < 3; c++) {
1031 float col0 = lerp(
static_cast<float>(
reinterpret_cast<const unsigned char *
>(&I[v0][u0])[c]),
1032 static_cast<float>(
reinterpret_cast<const unsigned char *
>(&I[v1][u1])[c]), xFrac);
1033 float col1 = lerp(
static_cast<float>(
reinterpret_cast<const unsigned char *
>(&I[v2][u2])[c]),
1034 static_cast<float>(
reinterpret_cast<const unsigned char *
>(&I[v3][u3])[c]), xFrac);
1035 float value = lerp(col0, col1, yFrac);
1037 reinterpret_cast<unsigned char *
>(&Ires[i][j])[c] = vpMath::saturate<unsigned char>(value);
1041 template <
class Type>
1043 unsigned int j,
float u,
float v)
1045 Ires[i][j] = getPixelClamped(I, u, v);
1066 template <
class Type>
1069 unsigned int nThreads)
1071 Ires.
resize(height, width);
1093 template <
class Type>
1102 std::cerr <<
"Input or output image is too small!" << std::endl;
1107 std::cerr <<
"INTERPOLATION_AREA is not implemented for this type." << std::endl;
1113 const float half = 0.5f;
1117 omp_set_num_threads(
static_cast<int>(nThreads));
1119 #pragma omp parallel for schedule(dynamic)
1121 for (
int i = 0; i < static_cast<int>(Ires.
getHeight()); i++) {
1122 const float v = (i + half) * scaleY - half;
1123 const int v0 =
static_cast<int>(v);
1124 const float yFrac = v - v0;
1126 for (
unsigned int j = 0; j < Ires.
getWidth(); j++) {
1127 const float u = (j + half) * scaleX - half;
1128 const int u0 =
static_cast<int>(u);
1129 const float xFrac = u - u0;
1132 resizeNearest(I, Ires,
static_cast<unsigned int>(i), j, u, v);
1134 resizeBilinear(I, Ires,
static_cast<unsigned int>(i), j, u0, v0, xFrac, yFrac);
1136 resizeBicubic(I, Ires,
static_cast<unsigned int>(i), j, u, v, xFrac, yFrac);
1151 std::cerr <<
"Input or output image is too small!" << std::endl;
1162 const float half = 0.5f;
1166 omp_set_num_threads(
static_cast<int>(nThreads));
1168 #pragma omp parallel for schedule(dynamic)
1170 for (
int i = 0; i < static_cast<int>(Ires.
getHeight()); i++) {
1171 float v = (i + half) * scaleY - half;
1172 float yFrac = v -
static_cast<int>(v);
1174 for (
unsigned int j = 0; j < Ires.
getWidth(); j++) {
1175 float u = (j + half) * scaleX - half;
1176 float xFrac = u -
static_cast<int>(u);
1179 resizeNearest(I, Ires,
static_cast<unsigned int>(i), j, u, v);
1181 resizeBicubic(I, Ires,
static_cast<unsigned int>(i), j, u, v, xFrac, yFrac);
1197 std::cerr <<
"Input or output image is too small!" << std::endl;
1208 const float half = 0.5f;
1212 omp_set_num_threads(
static_cast<int>(nThreads));
1214 #pragma omp parallel for schedule(dynamic)
1216 for (
int i = 0; i < static_cast<int>(Ires.
getHeight()); i++) {
1217 float v = (i + half) * scaleY - half;
1218 float yFrac = v -
static_cast<int>(v);
1220 for (
unsigned int j = 0; j < Ires.
getWidth(); j++) {
1221 float u = (j + half) * scaleX - half;
1222 float xFrac = u -
static_cast<int>(u);
1225 resizeNearest(I, Ires,
static_cast<unsigned int>(i), j, u, v);
1227 resizeBicubic(I, Ires,
static_cast<unsigned int>(i), j, u, v, xFrac, yFrac);
1248 template <
class Type>
1251 bool fixedPointArithmetic,
bool pixelCenter)
1254 std::cerr <<
"Input transformation must be a (2x3) or (3x3) matrix." << std::endl;
1262 const bool affine = (T.
getRows() == 2);
1271 double D = M[0][0] * M[1][1] - M[0][1] * M[1][0];
1272 D = !
vpMath::nul(D, std::numeric_limits<double>::epsilon()) ? 1.0 / D : 0;
1273 double A11 = M[1][1] * D, A22 = M[0][0] * D;
1274 M[0][0] = A11; M[0][1] *= -D;
1275 M[1][0] *= -D; M[1][1] = A22;
1276 double b1 = -M[0][0] * M[0][2] - M[0][1] * M[1][2];
1277 double b2 = -M[1][0] * M[0][2] - M[1][1] * M[1][2];
1278 M[0][2] = b1; M[1][2] = b2;
1283 if (fixedPointArithmetic && !pixelCenter) {
1284 fixedPointArithmetic = checkFixedPoint(0, 0, M, affine) &&
1285 checkFixedPoint(dst.
getWidth()-1, 0, M, affine) &&
1286 checkFixedPoint(0, dst.
getHeight()-1, M, affine) &&
1292 warpNN(src, M, dst, affine, pixelCenter, fixedPointArithmetic);
1295 warpLinear(src, M, dst, affine, pixelCenter, fixedPointArithmetic);
1299 template <
class Type>
1301 bool centerCorner,
bool fixedPoint)
1303 if (fixedPoint && !centerCorner) {
1304 const int nbits = 16;
1305 const int32_t precision = 1 << nbits;
1306 const float precision_1 = 1 /
static_cast<float>(precision);
1308 int32_t a0_i32 =
static_cast<int32_t
>(T[0][0] * precision);
1309 int32_t a1_i32 =
static_cast<int32_t
>(T[0][1] * precision);
1310 int32_t a2_i32 =
static_cast<int32_t
>(T[0][2] * precision);
1311 int32_t a3_i32 =
static_cast<int32_t
>(T[1][0] * precision);
1312 int32_t a4_i32 =
static_cast<int32_t
>(T[1][1] * precision);
1313 int32_t a5_i32 =
static_cast<int32_t
>(T[1][2] * precision);
1314 int32_t a6_i32 = T.
getRows() == 3 ?
static_cast<int32_t
>(T[2][0] * precision) : 0;
1315 int32_t a7_i32 = T.
getRows() == 3 ?
static_cast<int32_t
>(T[2][1] * precision) : 0;
1316 int32_t a8_i32 = T.
getRows() == 3 ?
static_cast<int32_t
>(T[2][2] * precision) : 1;
1318 int32_t height_1_i32 =
static_cast<int32_t
>((src.
getHeight() - 1) * precision) + 0x8000;
1319 int32_t width_1_i32 =
static_cast<int32_t
>((src.
getWidth() - 1) * precision) + 0x8000;
1322 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1323 int32_t xi = a2_i32;
1324 int32_t yi = a5_i32;
1326 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1327 if (yi >= 0 && yi < height_1_i32 && xi >= 0 && xi < width_1_i32) {
1328 float x_ = (xi >> nbits) + (xi & 0xFFFF) * precision_1;
1329 float y_ = (yi >> nbits) + (yi & 0xFFFF) * precision_1;
1333 dst[i][j] = src[y][x];
1344 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1345 int64_t xi = a2_i32;
1346 int64_t yi = a5_i32;
1347 int64_t wi = a8_i32;
1349 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1350 if (wi != 0 && yi >= 0 && yi <= (
static_cast<int>(src.
getHeight()) - 1)*wi &&
1351 xi >= 0 && xi <= (
static_cast<int>(src.
getWidth()) - 1)*wi) {
1352 float w_ = (wi >> nbits) + (wi & 0xFFFF) * precision_1;
1353 float x_ = ((xi >> nbits) + (xi & 0xFFFF) * precision_1) / w_;
1354 float y_ = ((yi >> nbits) + (yi & 0xFFFF) * precision_1) / w_;
1359 dst[i][j] = src[y][x];
1373 double a0 = T[0][0];
double a1 = T[0][1];
double a2 = T[0][2];
1374 double a3 = T[1][0];
double a4 = T[1][1];
double a5 = T[1][2];
1375 double a6 = affine ? 0.0 : T[2][0];
1376 double a7 = affine ? 0.0 : T[2][1];
1377 double a8 = affine ? 1.0 : T[2][2];
1379 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1380 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1381 double x = a0 * (centerCorner ? j + 0.5 : j) + a1 * (centerCorner ? i + 0.5 : i) + a2;
1382 double y = a3 * (centerCorner ? j + 0.5 : j) + a4 * (centerCorner ? i + 0.5 : i) + a5;
1383 double w = a6 * (centerCorner ? j + 0.5 : j) + a7 * (centerCorner ? i + 0.5 : i) + a8;
1385 if (
vpMath::nul(w, std::numeric_limits<double>::epsilon())) {
1389 int x_ = centerCorner ? coordCast(x / w) :
vpMath::round(x / w);
1390 int y_ = centerCorner ? coordCast(y / w) :
vpMath::round(y / w);
1392 if (x_ >= 0 && x_ <
static_cast<int>(src.
getWidth()) &&
1393 y_ >= 0 && y_ <
static_cast<int>(src.
getHeight())) {
1394 dst[i][j] = src[y_][x_];
1401 template <
class Type>
1403 bool centerCorner,
bool fixedPoint)
1405 if (fixedPoint && !centerCorner) {
1406 const int nbits = 16;
1407 const int64_t precision = 1 << nbits;
1408 const float precision_1 = 1 /
static_cast<float>(precision);
1409 const int64_t precision2 = 1ULL << (2 * nbits);
1410 const float precision_2 = 1 /
static_cast<float>(precision2);
1412 int64_t a0_i64 =
static_cast<int64_t
>(T[0][0] * precision);
1413 int64_t a1_i64 =
static_cast<int64_t
>(T[0][1] * precision);
1414 int64_t a2_i64 =
static_cast<int64_t
>(T[0][2] * precision);
1415 int64_t a3_i64 =
static_cast<int64_t
>(T[1][0] * precision);
1416 int64_t a4_i64 =
static_cast<int64_t
>(T[1][1] * precision);
1417 int64_t a5_i64 =
static_cast<int64_t
>(T[1][2] * precision);
1418 int64_t a6_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[2][0] * precision) : 0;
1419 int64_t a7_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[2][1] * precision) : 0;
1420 int64_t a8_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[2][2] * precision) : 1;
1422 int64_t height_i64 =
static_cast<int64_t
>(src.
getHeight() * precision);
1423 int64_t width_i64 =
static_cast<int64_t
>(src.
getWidth() * precision);
1426 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1427 int64_t xi_ = a2_i64;
1428 int64_t yi_ = a5_i64;
1430 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1431 if (yi_ >= 0 && yi_ < height_i64 && xi_ >= 0 && xi_ < width_i64) {
1432 const int64_t xi_lower = xi_ & (~0xFFFF);
1433 const int64_t yi_lower = yi_ & (~0xFFFF);
1435 const int64_t t = yi_ - yi_lower;
1436 const int64_t t_1 = precision - t;
1437 const int64_t s = xi_ - xi_lower;
1438 const int64_t s_1 = precision - s;
1440 const int x_ =
static_cast<int>(xi_ >> nbits);
1441 const int y_ =
static_cast<int>(yi_ >> nbits);
1443 if (y_ <
static_cast<int>(src.
getHeight())-1 && x_ <
static_cast<int>(src.
getWidth())-1) {
1444 const Type val00 = src[y_][x_];
1445 const Type val01 = src[y_][x_+1];
1446 const Type val10 = src[y_+1][x_];
1447 const Type val11 = src[y_+1][x_+1];
1448 const int64_t interp_i64 =
static_cast<int64_t
>(s_1*t_1*val00 + s*t_1*val01 + s_1*t*val10 + s*t*val11);
1449 const float interp = (interp_i64 >> (nbits*2)) + (interp_i64 & 0xFFFFFFFF) * precision_2;
1450 dst[i][j] = vpMath::saturate<Type>(interp);
1451 }
else if (y_ <
static_cast<int>(src.
getHeight())-1) {
1452 const Type val00 = src[y_][x_];
1453 const Type val10 = src[y_+1][x_];
1454 const int64_t interp_i64 =
static_cast<int64_t
>(t_1*val00 + t*val10);
1455 const float interp = (interp_i64 >> nbits) + (interp_i64 & 0xFFFF) * precision_1;
1456 dst[i][j] = vpMath::saturate<Type>(interp);
1457 }
else if (x_ <
static_cast<int>(src.
getWidth())-1) {
1458 const Type val00 = src[y_][x_];
1459 const Type val01 = src[y_][x_+1];
1460 const int64_t interp_i64 =
static_cast<int64_t
>(s_1*val00 + s*val01);
1461 const float interp = (interp_i64 >> nbits) + (interp_i64 & 0xFFFF) * precision_1;
1462 dst[i][j] = vpMath::saturate<Type>(interp);
1464 dst[i][j] = src[y_][x_];
1476 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1477 int64_t xi = a2_i64;
1478 int64_t yi = a5_i64;
1479 int64_t wi = a8_i64;
1481 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1482 if (wi != 0 && yi >= 0 && yi <= (
static_cast<int>(src.
getHeight()) - 1)*wi &&
1483 xi >= 0 && xi <= (
static_cast<int>(src.
getWidth()) - 1)*wi) {
1484 const float wi_ = (wi >> nbits) + (wi & 0xFFFF) * precision_1;
1485 const float xi_ = ((xi >> nbits) + (xi & 0xFFFF) * precision_1) / wi_;
1486 const float yi_ = ((yi >> nbits) + (yi & 0xFFFF) * precision_1) / wi_;
1488 const int x_ =
static_cast<int>(xi_);
1489 const int y_ =
static_cast<int>(yi_);
1491 const float t = yi_ - y_;
1492 const float s = xi_ - x_;
1494 if (y_ <
static_cast<int>(src.
getHeight()) - 1 && x_ <
static_cast<int>(src.
getWidth()) - 1) {
1495 const Type val00 = src[y_][x_];
1496 const Type val01 = src[y_][x_ + 1];
1497 const Type val10 = src[y_ + 1][x_];
1498 const Type val11 = src[y_ + 1][x_ + 1];
1499 const float col0 = lerp(val00, val01, s);
1500 const float col1 = lerp(val10, val11, s);
1501 const float interp = lerp(col0, col1, t);
1502 dst[i][j] = vpMath::saturate<Type>(interp);
1503 }
else if (y_ <
static_cast<int>(src.
getHeight()) - 1) {
1504 const Type val00 = src[y_][x_];
1505 const Type val10 = src[y_ + 1][x_];
1506 const float interp = lerp(val00, val10, t);
1507 dst[i][j] = vpMath::saturate<Type>(interp);
1508 }
else if (x_ <
static_cast<int>(src.
getWidth()) - 1) {
1509 const Type val00 = src[y_][x_];
1510 const Type val01 = src[y_][x_ + 1];
1511 const float interp = lerp(val00, val01, s);
1512 dst[i][j] = vpMath::saturate<Type>(interp);
1514 dst[i][j] = src[y_][x_];
1529 double a0 = T[0][0];
double a1 = T[0][1];
double a2 = T[0][2];
1530 double a3 = T[1][0];
double a4 = T[1][1];
double a5 = T[1][2];
1531 double a6 = affine ? 0.0 : T[2][0];
1532 double a7 = affine ? 0.0 : T[2][1];
1533 double a8 = affine ? 1.0 : T[2][2];
1535 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1536 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1537 double x = a0 * (centerCorner ? j + 0.5 : j) + a1 * (centerCorner ? i + 0.5 : i) + a2;
1538 double y = a3 * (centerCorner ? j + 0.5 : j) + a4 * (centerCorner ? i + 0.5 : i) + a5;
1539 double w = a6 * (centerCorner ? j + 0.5 : j) + a7 * (centerCorner ? i + 0.5 : i) + a8;
1540 if (
vpMath::nul(w, std::numeric_limits<double>::epsilon())) {
1544 x = x / w - (centerCorner ? 0.5 : 0);
1545 y = y / w - (centerCorner ? 0.5 : 0);
1547 int x_lower =
static_cast<int>(x);
1548 int y_lower =
static_cast<int>(y);
1550 if (y_lower >=
static_cast<int>(src.
getHeight()) || x_lower >=
static_cast<int>(src.
getWidth()) ||
1555 double s = x - x_lower;
1556 double t = y - y_lower;
1558 if (y_lower <
static_cast<int>(src.
getHeight())-1 && x_lower <
static_cast<int>(src.
getWidth())-1) {
1559 const Type val00 = src[y_lower][x_lower];
1560 const Type val01 = src[y_lower][x_lower + 1];
1561 const Type val10 = src[y_lower + 1][x_lower];
1562 const Type val11 = src[y_lower + 1][x_lower + 1];
1563 const double col0 = lerp(val00, val01, s);
1564 const double col1 = lerp(val10, val11, s);
1565 const double interp = lerp(col0, col1, t);
1566 dst[i][j] = vpMath::saturate<Type>(interp);
1567 }
else if (y_lower <
static_cast<int>(src.
getHeight())-1) {
1568 const Type val00 = src[y_lower][x_lower];
1569 const Type val10 = src[y_lower + 1][x_lower];
1570 const double interp = lerp(val00, val10, t);
1571 dst[i][j] = vpMath::saturate<Type>(interp);
1572 }
else if (x_lower <
static_cast<int>(src.
getWidth())-1) {
1573 const Type val00 = src[y_lower][x_lower];
1574 const Type val01 = src[y_lower][x_lower + 1];
1575 const double interp = lerp(val00, val01, s);
1576 dst[i][j] = vpMath::saturate<Type>(interp);
1578 dst[i][j] = src[y_lower][x_lower];
1587 bool centerCorner,
bool fixedPoint)
1589 if (fixedPoint && !centerCorner) {
1590 const int nbits = 16;
1591 const int64_t precision = 1 << nbits;
1592 const float precision_1 = 1 /
static_cast<float>(precision);
1593 const int64_t precision2 = 1ULL << (2 * nbits);
1594 const float precision_2 = 1 /
static_cast<float>(precision2);
1596 int64_t a0_i64 =
static_cast<int64_t
>(T[0][0] * precision);
1597 int64_t a1_i64 =
static_cast<int64_t
>(T[0][1] * precision);
1598 int64_t a2_i64 =
static_cast<int64_t
>(T[0][2] * precision);
1599 int64_t a3_i64 =
static_cast<int64_t
>(T[1][0] * precision);
1600 int64_t a4_i64 =
static_cast<int64_t
>(T[1][1] * precision);
1601 int64_t a5_i64 =
static_cast<int64_t
>(T[1][2] * precision);
1602 int64_t a6_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[2][0] * precision) : 0;
1603 int64_t a7_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[2][1] * precision) : 0;
1604 int64_t a8_i64 = precision;
1606 int64_t height_i64 =
static_cast<int64_t
>(src.
getHeight() * precision);
1607 int64_t width_i64 =
static_cast<int64_t
>(src.
getWidth() * precision);
1610 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1611 int64_t xi = a2_i64;
1612 int64_t yi = a5_i64;
1614 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1615 if (yi >= 0 && yi < height_i64 && xi >= 0 && xi < width_i64) {
1616 const int64_t xi_lower = xi & (~0xFFFF);
1617 const int64_t yi_lower = yi & (~0xFFFF);
1619 const int64_t t = yi - yi_lower;
1620 const int64_t t_1 = precision - t;
1621 const int64_t s = xi - xi_lower;
1622 const int64_t s_1 = precision - s;
1624 const int x_ =
static_cast<int>(xi >> nbits);
1625 const int y_ =
static_cast<int>(yi >> nbits);
1627 if (y_ <
static_cast<int>(src.
getHeight())-1 && x_ <
static_cast<int>(src.
getWidth())-1) {
1628 const vpRGBa val00 = src[y_][x_];
1629 const vpRGBa val01 = src[y_][x_+1];
1630 const vpRGBa val10 = src[y_+1][x_];
1631 const vpRGBa val11 = src[y_+1][x_+1];
1632 const int64_t interpR_i64 =
static_cast<int64_t
>(s_1*t_1*val00.
R + s * t_1*val01.
R + s_1 * t*val10.
R + s * t*val11.
R);
1633 const float interpR = (interpR_i64 >> (nbits*2)) + (interpR_i64 & 0xFFFFFFFF) * precision_2;
1635 const int64_t interpG_i64 =
static_cast<int64_t
>(s_1*t_1*val00.
G + s * t_1*val01.
G + s_1 * t*val10.
G + s * t*val11.
G);
1636 const float interpG = (interpG_i64 >> (nbits * 2)) + (interpG_i64 & 0xFFFFFFFF) * precision_2;
1638 const int64_t interpB_i64 =
static_cast<int64_t
>(s_1*t_1*val00.
B + s * t_1*val01.
B + s_1 * t*val10.
B + s * t*val11.
B);
1639 const float interpB = (interpB_i64 >> (nbits * 2)) + (interpB_i64 & 0xFFFFFFFF) * precision_2;
1641 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1642 vpMath::saturate<unsigned char>(interpG),
1643 vpMath::saturate<unsigned char>(interpB),
1645 }
else if (y_ <
static_cast<int>(src.
getHeight())-1) {
1646 const vpRGBa val00 = src[y_][x_];
1647 const vpRGBa val10 = src[y_+1][x_];
1648 const int64_t interpR_i64 =
static_cast<int64_t
>(t_1*val00.
R + t*val10.
R);
1649 const float interpR = (interpR_i64 >> nbits) + (interpR_i64 & 0xFFFF) * precision_1;
1651 const int64_t interpG_i64 =
static_cast<int64_t
>(t_1*val00.
G + t * val10.
G);
1652 const float interpG = (interpG_i64 >> nbits) + (interpG_i64 & 0xFFFF) * precision_1;
1654 const int64_t interpB_i64 =
static_cast<int64_t
>(t_1*val00.
B + t * val10.
B);
1655 const float interpB = (interpB_i64 >> nbits) + (interpB_i64 & 0xFFFF) * precision_1;
1657 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1658 vpMath::saturate<unsigned char>(interpG),
1659 vpMath::saturate<unsigned char>(interpB),
1661 }
else if (x_ <
static_cast<int>(src.
getWidth())-1) {
1662 const vpRGBa val00 = src[y_][x_];
1663 const vpRGBa val01 = src[y_][x_+1];
1664 const int64_t interpR_i64 =
static_cast<int64_t
>(s_1*val00.
R + s*val01.
R);
1665 const float interpR = (interpR_i64 >> nbits) + (interpR_i64 & 0xFFFF) * precision_1;
1667 const int64_t interpG_i64 =
static_cast<int64_t
>(s_1*val00.
G + s * val01.
G);
1668 const float interpG = (interpG_i64 >> nbits) + (interpG_i64 & 0xFFFF) * precision_1;
1670 const int64_t interpB_i64 =
static_cast<int64_t
>(s_1*val00.
B + s * val01.
B);
1671 const float interpB = (interpB_i64 >> nbits) + (interpB_i64 & 0xFFFF) * precision_1;
1673 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1674 vpMath::saturate<unsigned char>(interpG),
1675 vpMath::saturate<unsigned char>(interpB),
1678 dst[i][j] = src[y_][x_];
1690 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1691 int64_t xi = a2_i64;
1692 int64_t yi = a5_i64;
1693 int64_t wi = a8_i64;
1695 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1696 if (yi >= 0 && yi <= (
static_cast<int>(src.
getHeight()) - 1)*wi &&
1697 xi >= 0 && xi <= (
static_cast<int>(src.
getWidth()) - 1)*wi) {
1698 const float wi_ = (wi >> nbits) + (wi & 0xFFFF) * precision_1;
1699 const float xi_ = ((xi >> nbits) + (xi & 0xFFFF) * precision_1) / wi_;
1700 const float yi_ = ((yi >> nbits) + (yi & 0xFFFF) * precision_1) / wi_;
1702 const int x_ =
static_cast<int>(xi_);
1703 const int y_ =
static_cast<int>(yi_);
1705 const float t = yi_ - y_;
1706 const float s = xi_ - x_;
1708 if (y_ <
static_cast<int>(src.
getHeight()) - 1 && x_ <
static_cast<int>(src.
getWidth()) - 1) {
1709 const vpRGBa val00 = src[y_][x_];
1710 const vpRGBa val01 = src[y_][x_ + 1];
1711 const vpRGBa val10 = src[y_ + 1][x_];
1712 const vpRGBa val11 = src[y_ + 1][x_ + 1];
1713 const float colR0 = lerp(val00.
R, val01.
R, s);
1714 const float colR1 = lerp(val10.
R, val11.
R, s);
1715 const float interpR = lerp(colR0, colR1, t);
1717 const float colG0 = lerp(val00.
G, val01.
G, s);
1718 const float colG1 = lerp(val10.
G, val11.
G, s);
1719 const float interpG = lerp(colG0, colG1, t);
1721 const float colB0 = lerp(val00.
B, val01.
B, s);
1722 const float colB1 = lerp(val10.
B, val11.
B, s);
1723 const float interpB = lerp(colB0, colB1, t);
1725 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1726 vpMath::saturate<unsigned char>(interpG),
1727 vpMath::saturate<unsigned char>(interpB),
1729 }
else if (y_ <
static_cast<int>(src.
getHeight()) - 1) {
1730 const vpRGBa val00 = src[y_][x_];
1731 const vpRGBa val10 = src[y_ + 1][x_];
1732 const float interpR = lerp(val00.
R, val10.
R, t);
1733 const float interpG = lerp(val00.
G, val10.
G, t);
1734 const float interpB = lerp(val00.
B, val10.
B, t);
1736 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1737 vpMath::saturate<unsigned char>(interpG),
1738 vpMath::saturate<unsigned char>(interpB),
1740 }
else if (x_ <
static_cast<int>(src.
getWidth()) - 1) {
1741 const vpRGBa val00 = src[y_][x_];
1742 const vpRGBa val01 = src[y_][x_ + 1];
1743 const float interpR = lerp(val00.
R, val01.
R, s);
1744 const float interpG = lerp(val00.
G, val01.
G, s);
1745 const float interpB = lerp(val00.
B, val01.
B, s);
1747 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1748 vpMath::saturate<unsigned char>(interpG),
1749 vpMath::saturate<unsigned char>(interpB),
1752 dst[i][j] = src[y_][x_];
1767 double a0 = T[0][0];
double a1 = T[0][1];
double a2 = T[0][2];
1768 double a3 = T[1][0];
double a4 = T[1][1];
double a5 = T[1][2];
1769 double a6 = affine ? 0.0 : T[2][0];
1770 double a7 = affine ? 0.0 : T[2][1];
1771 double a8 = affine ? 1.0 : T[2][2];
1773 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1774 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1775 double x = a0 * (centerCorner ? j + 0.5 : j) + a1 * (centerCorner ? i + 0.5 : i) + a2;
1776 double y = a3 * (centerCorner ? j + 0.5 : j) + a4 * (centerCorner ? i + 0.5 : i) + a5;
1777 double w = a6 * (centerCorner ? j + 0.5 : j) + a7 * (centerCorner ? i + 0.5 : i) + a8;
1779 x = x / w - (centerCorner ? 0.5 : 0);
1780 y = y / w - (centerCorner ? 0.5 : 0);
1782 int x_lower =
static_cast<int>(x);
1783 int y_lower =
static_cast<int>(y);
1785 if (y_lower >=
static_cast<int>(src.
getHeight()) || x_lower >=
static_cast<int>(src.
getWidth()) ||
1790 double s = x - x_lower;
1791 double t = y - y_lower;
1793 if (y_lower <
static_cast<int>(src.
getHeight())-1 && x_lower <
static_cast<int>(src.
getWidth())-1) {
1794 const vpRGBa val00 = src[y_lower][x_lower];
1795 const vpRGBa val01 = src[y_lower][x_lower +1];
1796 const vpRGBa val10 = src[y_lower +1][x_lower];
1797 const vpRGBa val11 = src[y_lower +1][x_lower +1];
1798 const double colR0 = lerp(val00.
R, val01.
R, s);
1799 const double colR1 = lerp(val10.
R, val11.
R, s);
1800 const double interpR = lerp(colR0, colR1, t);
1802 const double colG0 = lerp(val00.
G, val01.
G, s);
1803 const double colG1 = lerp(val10.
G, val11.
G, s);
1804 const double interpG = lerp(colG0, colG1, t);
1806 const double colB0 = lerp(val00.
B, val01.
B, s);
1807 const double colB1 = lerp(val10.
B, val11.
B, s);
1808 const double interpB = lerp(colB0, colB1, t);
1810 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1811 vpMath::saturate<unsigned char>(interpG),
1812 vpMath::saturate<unsigned char>(interpB),
1814 }
else if (y_lower <
static_cast<int>(src.
getHeight())-1) {
1815 const vpRGBa val00 = src[y_lower][x_lower];
1816 const vpRGBa val10 = src[y_lower +1][x_lower];
1817 const double interpR = lerp(val00.
R, val10.
R, t);
1818 const double interpG = lerp(val00.
G, val10.
G, t);
1819 const double interpB = lerp(val00.
B, val10.
B, t);
1821 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1822 vpMath::saturate<unsigned char>(interpG),
1823 vpMath::saturate<unsigned char>(interpB),
1825 }
else if (x_lower <
static_cast<int>(src.
getWidth())-1) {
1826 const vpRGBa val00 = src[y_lower][x_lower];
1827 const vpRGBa val01 = src[y_lower][x_lower +1];
1828 const double interpR = lerp(val00.
R, val01.
R, s);
1829 const double interpG = lerp(val00.
G, val01.
G, s);
1830 const double interpB = lerp(val00.
B, val01.
B, s);
1832 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1833 vpMath::saturate<unsigned char>(interpG),
1834 vpMath::saturate<unsigned char>(interpB),
1837 dst[i][j] = src[y_lower][x_lower];
Implementation of a generic 2D array used as base class for matrices and vectors.
unsigned int getCols() const
unsigned int getRows() const
Generic class defining intrinsic camera parameters.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
unsigned int getSize() const
Type * bitmap
points toward the bitmap
unsigned int getHeight() const
Provides simple mathematics computation tools that are not available in the C mathematics library (ma...
static double sqr(double x)
static bool nul(double x, double s=0.001)
static int round(double x)
Implementation of a matrix and operations on matrices.
vpMatrix inverseByLU() const
unsigned char B
Blue component.
unsigned char R
Red component.
unsigned char G
Green component.
Defines an oriented rectangle in the plane.
Defines a rectangle in the plane.
Implementation of row vector and the associated operations.