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,
142 bool useOptimized =
true);
151 template <
class Type>
155 template <
class Type>
161 bool useOptimized =
true);
163 template <
class Type>
165 unsigned int nThreads=2);
167 template <
class Type>
171 template <
class Type>
174 bool fixedPointArithmetic=
true,
bool pixelCenter=
false);
176 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS) 181 template <
class Type>
182 vp_deprecated
static void createSubImage(
const vpImage<Type> &I,
unsigned int i_sub,
unsigned int j_sub,
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)
280 #endif // #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS) 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);
618 #endif // DOXYGEN_SHOULD_SKIP_THIS 619 #endif // VISP_HAVE_PTHREAD 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;
697 #else // VISP_HAVE_PTHREAD 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));
770 #endif // VISP_HAVE_PTHREAD 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);
833 newI.
resize(height, width);
835 for (
unsigned int i = 0; i < height; i++) {
836 memcpy(newI.
bitmap + i * width, I.
bitmap + (height - 1 - i) * width, width *
sizeof(Type));
877 for (
unsigned int i = 0; i < height / 2; i++) {
878 memcpy(Ibuf.
bitmap, I.
bitmap + i * width, width *
sizeof(Type));
880 memcpy(I.
bitmap + i * width, I.
bitmap + (height - 1 - i) * width, width *
sizeof(Type));
881 memcpy(I.
bitmap + (height - 1 - i) * width, Ibuf.
bitmap, width *
sizeof(Type));
885 template <
class Type> Type vpImageTools::getPixelClamped(
const vpImage<Type> &I,
float u,
float v)
889 x = (std::max)(0, (std::min)(x,
static_cast<int>(I.
getWidth())-1));
890 y = (std::max)(0, (std::min)(y,
static_cast<int>(I.
getHeight())-1));
897 template <
class Type>
899 unsigned int j,
float u,
float v,
float xFrac,
float yFrac)
902 Type p00 = getPixelClamped(I, u - 1, v - 1);
903 Type p01 = getPixelClamped(I, u + 0, v - 1);
904 Type p02 = getPixelClamped(I, u + 1, v - 1);
905 Type p03 = getPixelClamped(I, u + 2, v - 1);
908 Type p10 = getPixelClamped(I, u - 1, v + 0);
909 Type p11 = getPixelClamped(I, u + 0, v + 0);
910 Type p12 = getPixelClamped(I, u + 1, v + 0);
911 Type p13 = getPixelClamped(I, u + 2, v + 0);
914 Type p20 = getPixelClamped(I, u - 1, v + 1);
915 Type p21 = getPixelClamped(I, u + 0, v + 1);
916 Type p22 = getPixelClamped(I, u + 1, v + 1);
917 Type p23 = getPixelClamped(I, u + 2, v + 1);
920 Type p30 = getPixelClamped(I, u - 1, v + 2);
921 Type p31 = getPixelClamped(I, u + 0, v + 2);
922 Type p32 = getPixelClamped(I, u + 1, v + 2);
923 Type p33 = getPixelClamped(I, u + 2, v + 2);
925 float col0 = cubicHermite(p00, p01, p02, p03, xFrac);
926 float col1 = cubicHermite(p10, p11, p12, p13, xFrac);
927 float col2 = cubicHermite(p20, p21, p22, p23, xFrac);
928 float col3 = cubicHermite(p30, p31, p32, p33, xFrac);
929 float value = cubicHermite(col0, col1, col2, col3, yFrac);
930 Ires[i][j] = vpMath::saturate<Type>(value);
935 unsigned int j,
float u,
float v,
float xFrac,
float yFrac)
938 vpRGBa p00 = getPixelClamped(I, u - 1, v - 1);
939 vpRGBa p01 = getPixelClamped(I, u + 0, v - 1);
940 vpRGBa p02 = getPixelClamped(I, u + 1, v - 1);
941 vpRGBa p03 = getPixelClamped(I, u + 2, v - 1);
944 vpRGBa p10 = getPixelClamped(I, u - 1, v + 0);
945 vpRGBa p11 = getPixelClamped(I, u + 0, v + 0);
946 vpRGBa p12 = getPixelClamped(I, u + 1, v + 0);
947 vpRGBa p13 = getPixelClamped(I, u + 2, v + 0);
950 vpRGBa p20 = getPixelClamped(I, u - 1, v + 1);
951 vpRGBa p21 = getPixelClamped(I, u + 0, v + 1);
952 vpRGBa p22 = getPixelClamped(I, u + 1, v + 1);
953 vpRGBa p23 = getPixelClamped(I, u + 2, v + 1);
956 vpRGBa p30 = getPixelClamped(I, u - 1, v + 2);
957 vpRGBa p31 = getPixelClamped(I, u + 0, v + 2);
958 vpRGBa p32 = getPixelClamped(I, u + 1, v + 2);
959 vpRGBa p33 = getPixelClamped(I, u + 2, v + 2);
961 for (
int c = 0; c < 3; c++) {
962 float col0 = cubicHermite(static_cast<float>(reinterpret_cast<unsigned char *>(&p00)[c]),
963 static_cast<float>(reinterpret_cast<unsigned char *>(&p01)[c]),
964 static_cast<float>(reinterpret_cast<unsigned char *>(&p02)[c]),
965 static_cast<float>(reinterpret_cast<unsigned char *>(&p03)[c]), xFrac);
966 float col1 = cubicHermite(static_cast<float>(reinterpret_cast<unsigned char *>(&p10)[c]),
967 static_cast<float>(reinterpret_cast<unsigned char *>(&p11)[c]),
968 static_cast<float>(reinterpret_cast<unsigned char *>(&p12)[c]),
969 static_cast<float>(reinterpret_cast<unsigned char *>(&p13)[c]), xFrac);
970 float col2 = cubicHermite(static_cast<float>(reinterpret_cast<unsigned char *>(&p20)[c]),
971 static_cast<float>(reinterpret_cast<unsigned char *>(&p21)[c]),
972 static_cast<float>(reinterpret_cast<unsigned char *>(&p22)[c]),
973 static_cast<float>(reinterpret_cast<unsigned char *>(&p23)[c]), xFrac);
974 float col3 = cubicHermite(static_cast<float>(reinterpret_cast<unsigned char *>(&p30)[c]),
975 static_cast<float>(reinterpret_cast<unsigned char *>(&p31)[c]),
976 static_cast<float>(reinterpret_cast<unsigned char *>(&p32)[c]),
977 static_cast<float>(reinterpret_cast<unsigned char *>(&p33)[c]), xFrac);
978 float value = cubicHermite(col0, col1, col2, col3, yFrac);
980 reinterpret_cast<unsigned char *
>(&Ires[i][j])[c] = vpMath::saturate<unsigned char>(value);
984 template <
class Type>
986 unsigned int j,
float u,
float v,
float xFrac,
float yFrac)
988 int u0 =
static_cast<int>(u);
989 int v0 =
static_cast<int>(v);
991 int u1 = (std::min)(static_cast<int>(I.
getWidth()) - 1, u0 + 1);
995 int v2 = (std::min)(static_cast<int>(I.
getHeight()) - 1, v0 + 1);
1000 float col0 = lerp(I[v0][u0], I[v1][u1], xFrac);
1001 float col1 = lerp(I[v2][u2], I[v3][u3], xFrac);
1002 float value = lerp(col0, col1, yFrac);
1004 Ires[i][j] = vpMath::saturate<Type>(value);
1009 unsigned int j,
float u,
float v,
float xFrac,
float yFrac)
1011 int u0 =
static_cast<int>(u);
1012 int v0 =
static_cast<int>(v);
1014 int u1 = (std::min)(static_cast<int>(I.
getWidth()) - 1, u0 + 1);
1018 int v2 = (std::min)(static_cast<int>(I.
getHeight()) - 1, v0 + 1);
1023 for (
int c = 0; c < 3; c++) {
1024 float col0 = lerp(static_cast<float>(reinterpret_cast<const unsigned char *>(&I[v0][u0])[c]),
1025 static_cast<float>(reinterpret_cast<const unsigned char *>(&I[v1][u1])[c]), xFrac);
1026 float col1 = lerp(static_cast<float>(reinterpret_cast<const unsigned char *>(&I[v2][u2])[c]),
1027 static_cast<float>(reinterpret_cast<const unsigned char *>(&I[v3][u3])[c]), xFrac);
1028 float value = lerp(col0, col1, yFrac);
1030 reinterpret_cast<unsigned char *
>(&Ires[i][j])[c] = vpMath::saturate<unsigned char>(value);
1034 template <
class Type>
1036 unsigned int j,
float u,
float v)
1038 Ires[i][j] = getPixelClamped(I, u, v);
1059 template <
class Type>
1062 unsigned int nThreads)
1064 Ires.
resize(height, width);
1086 template <
class Type>
1095 std::cerr <<
"Input or output image is too small!" << std::endl;
1099 if (method == INTERPOLATION_AREA) {
1100 std::cerr <<
"INTERPOLATION_AREA is not implemented for this type." << std::endl;
1106 const float half = 0.5f;
1110 omp_set_num_threads(static_cast<int>(nThreads));
1112 #pragma omp parallel for schedule(dynamic) 1114 for (
int i = 0; i < static_cast<int>(Ires.
getHeight()); i++) {
1115 const float v = (i + half) * scaleY - half;
1116 const int v0 =
static_cast<int>(v);
1117 const float yFrac = v - v0;
1119 for (
unsigned int j = 0; j < Ires.
getWidth(); j++) {
1120 const float u = (j + half) * scaleX - half;
1121 const int u0 =
static_cast<int>(u);
1122 const float xFrac = u - u0;
1124 if (method == INTERPOLATION_NEAREST) {
1125 resizeNearest(I, Ires, static_cast<unsigned int>(i), j, u, v);
1126 }
else if (method == INTERPOLATION_LINEAR) {
1127 resizeBilinear(I, Ires, static_cast<unsigned int>(i), j, u0, v0, xFrac, yFrac);
1128 }
else if (method == INTERPOLATION_CUBIC) {
1129 resizeBicubic(I, Ires, static_cast<unsigned int>(i), j, u, v, xFrac, yFrac);
1144 std::cerr <<
"Input or output image is too small!" << std::endl;
1148 if (method == INTERPOLATION_AREA) {
1150 }
else if (method == INTERPOLATION_LINEAR) {
1151 resizeSimdlib(I, Ires.
getWidth(), Ires.
getHeight(), Ires, INTERPOLATION_LINEAR);
1155 const float half = 0.5f;
1159 omp_set_num_threads(static_cast<int>(nThreads));
1161 #pragma omp parallel for schedule(dynamic) 1163 for (
int i = 0; i < static_cast<int>(Ires.
getHeight()); i++) {
1164 float v = (i + half) * scaleY - half;
1165 float yFrac = v -
static_cast<int>(v);
1167 for (
unsigned int j = 0; j < Ires.
getWidth(); j++) {
1168 float u = (j + half) * scaleX - half;
1169 float xFrac = u -
static_cast<int>(u);
1171 if (method == INTERPOLATION_NEAREST) {
1172 resizeNearest(I, Ires, static_cast<unsigned int>(i), j, u, v);
1173 }
else if (method == INTERPOLATION_CUBIC) {
1174 resizeBicubic(I, Ires, static_cast<unsigned int>(i), j, u, v, xFrac, yFrac);
1190 std::cerr <<
"Input or output image is too small!" << std::endl;
1194 if (method == INTERPOLATION_AREA) {
1196 }
else if (method == INTERPOLATION_LINEAR) {
1197 resizeSimdlib(I, Ires.
getWidth(), Ires.
getHeight(), Ires, INTERPOLATION_LINEAR);
1201 const float half = 0.5f;
1205 omp_set_num_threads(static_cast<int>(nThreads));
1207 #pragma omp parallel for schedule(dynamic) 1209 for (
int i = 0; i < static_cast<int>(Ires.
getHeight()); i++) {
1210 float v = (i + half) * scaleY - half;
1211 float yFrac = v -
static_cast<int>(v);
1213 for (
unsigned int j = 0; j < Ires.
getWidth(); j++) {
1214 float u = (j + half) * scaleX - half;
1215 float xFrac = u -
static_cast<int>(u);
1217 if (method == INTERPOLATION_NEAREST) {
1218 resizeNearest(I, Ires, static_cast<unsigned int>(i), j, u, v);
1219 }
else if (method == INTERPOLATION_CUBIC) {
1220 resizeBicubic(I, Ires, static_cast<unsigned int>(i), j, u, v, xFrac, yFrac);
1241 template <
class Type>
1244 bool fixedPointArithmetic,
bool pixelCenter)
1247 std::cerr <<
"Input transformation must be a (2x3) or (3x3) matrix." << std::endl;
1255 const bool affine = (T.
getRows() == 2);
1256 const bool interp_NN = (interpolation == INTERPOLATION_NEAREST) || (interpolation == INTERPOLATION_CUBIC);
1264 double D = M[0][0] * M[1][1] - M[0][1] * M[1][0];
1265 D = !
vpMath::nul(D, std::numeric_limits<double>::epsilon()) ? 1.0 / D : 0;
1266 double A11 = M[1][1] * D, A22 = M[0][0] * D;
1267 M[0][0] = A11; M[0][1] *= -D;
1268 M[1][0] *= -D; M[1][1] = A22;
1269 double b1 = -M[0][0] * M[0][2] - M[0][1] * M[1][2];
1270 double b2 = -M[1][0] * M[0][2] - M[1][1] * M[1][2];
1271 M[0][2] = b1; M[1][2] = b2;
1276 if (fixedPointArithmetic && !pixelCenter) {
1277 fixedPointArithmetic = checkFixedPoint(0, 0, M, affine) &&
1278 checkFixedPoint(dst.
getWidth()-1, 0, M, affine) &&
1279 checkFixedPoint(0, dst.
getHeight()-1, M, affine) &&
1285 warpNN(src, M, dst, affine, pixelCenter, fixedPointArithmetic);
1288 warpLinear(src, M, dst, affine, pixelCenter, fixedPointArithmetic);
1292 template <
class Type>
1294 bool centerCorner,
bool fixedPoint)
1296 if (fixedPoint && !centerCorner) {
1297 const int nbits = 16;
1298 const int32_t precision = 1 << nbits;
1299 const float precision_1 = 1 /
static_cast<float>(precision);
1301 int32_t a0_i32 =
static_cast<int32_t
>(T[0][0] * precision);
1302 int32_t a1_i32 =
static_cast<int32_t
>(T[0][1] * precision);
1303 int32_t a2_i32 =
static_cast<int32_t
>(T[0][2] * precision);
1304 int32_t a3_i32 =
static_cast<int32_t
>(T[1][0] * precision);
1305 int32_t a4_i32 =
static_cast<int32_t
>(T[1][1] * precision);
1306 int32_t a5_i32 =
static_cast<int32_t
>(T[1][2] * precision);
1307 int32_t a6_i32 = T.
getRows() == 3 ?
static_cast<int32_t
>(T[2][0] * precision) : 0;
1308 int32_t a7_i32 = T.
getRows() == 3 ?
static_cast<int32_t
>(T[2][1] * precision) : 0;
1309 int32_t a8_i32 = T.
getRows() == 3 ?
static_cast<int32_t
>(T[2][2] * precision) : 1;
1311 int32_t height_1_i32 =
static_cast<int32_t
>((src.
getHeight() - 1) * precision) + 0x8000;
1312 int32_t width_1_i32 =
static_cast<int32_t
>((src.
getWidth() - 1) * precision) + 0x8000;
1315 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1316 int32_t xi = a2_i32;
1317 int32_t yi = a5_i32;
1319 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1320 if (yi >= 0 && yi < height_1_i32 && xi >= 0 && xi < width_1_i32) {
1321 float x_ = (xi >> nbits) + (xi & 0xFFFF) * precision_1;
1322 float y_ = (yi >> nbits) + (yi & 0xFFFF) * precision_1;
1326 dst[i][j] = src[y][x];
1337 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1338 int64_t xi = a2_i32;
1339 int64_t yi = a5_i32;
1340 int64_t wi = a8_i32;
1342 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1343 if (wi != 0 && yi >= 0 && yi <= (static_cast<int>(src.
getHeight()) - 1)*wi &&
1344 xi >= 0 && xi <= (static_cast<int>(src.
getWidth()) - 1)*wi) {
1345 float w_ = (wi >> nbits) + (wi & 0xFFFF) * precision_1;
1346 float x_ = ((xi >> nbits) + (xi & 0xFFFF) * precision_1) / w_;
1347 float y_ = ((yi >> nbits) + (yi & 0xFFFF) * precision_1) / w_;
1352 dst[i][j] = src[y][x];
1366 double a0 = T[0][0];
double a1 = T[0][1];
double a2 = T[0][2];
1367 double a3 = T[1][0];
double a4 = T[1][1];
double a5 = T[1][2];
1368 double a6 = affine ? 0.0 : T[2][0];
1369 double a7 = affine ? 0.0 : T[2][1];
1370 double a8 = affine ? 1.0 : T[2][2];
1372 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1373 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1374 double x = a0 * (centerCorner ? j + 0.5 : j) + a1 * (centerCorner ? i + 0.5 : i) + a2;
1375 double y = a3 * (centerCorner ? j + 0.5 : j) + a4 * (centerCorner ? i + 0.5 : i) + a5;
1376 double w = a6 * (centerCorner ? j + 0.5 : j) + a7 * (centerCorner ? i + 0.5 : i) + a8;
1378 if (
vpMath::nul(w, std::numeric_limits<double>::epsilon())) {
1382 int x_ = centerCorner ? coordCast(x / w) :
vpMath::round(x / w);
1383 int y_ = centerCorner ? coordCast(y / w) :
vpMath::round(y / w);
1385 if (x_ >= 0 && x_ < static_cast<int>(src.
getWidth()) &&
1386 y_ >= 0 && y_ < static_cast<int>(src.
getHeight())) {
1387 dst[i][j] = src[y_][x_];
1394 template <
class Type>
1396 bool centerCorner,
bool fixedPoint)
1398 if (fixedPoint && !centerCorner) {
1399 const int nbits = 16;
1400 const int64_t precision = 1 << nbits;
1401 const float precision_1 = 1 /
static_cast<float>(precision);
1402 const int64_t precision2 = 1ULL << (2 * nbits);
1403 const float precision_2 = 1 /
static_cast<float>(precision2);
1405 int64_t a0_i64 =
static_cast<int64_t
>(T[0][0] * precision);
1406 int64_t a1_i64 =
static_cast<int64_t
>(T[0][1] * precision);
1407 int64_t a2_i64 =
static_cast<int64_t
>(T[0][2] * precision);
1408 int64_t a3_i64 =
static_cast<int64_t
>(T[1][0] * precision);
1409 int64_t a4_i64 =
static_cast<int64_t
>(T[1][1] * precision);
1410 int64_t a5_i64 =
static_cast<int64_t
>(T[1][2] * precision);
1411 int64_t a6_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[2][0] * precision) : 0;
1412 int64_t a7_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[2][1] * precision) : 0;
1413 int64_t a8_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[2][2] * precision) : 1;
1415 int64_t height_i64 =
static_cast<int64_t
>(src.
getHeight() * precision);
1416 int64_t width_i64 =
static_cast<int64_t
>(src.
getWidth() * precision);
1419 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1420 int64_t xi_ = a2_i64;
1421 int64_t yi_ = a5_i64;
1423 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1424 if (yi_ >= 0 && yi_ < height_i64 && xi_ >= 0 && xi_ < width_i64) {
1425 const int64_t xi_lower = xi_ & (~0xFFFF);
1426 const int64_t yi_lower = yi_ & (~0xFFFF);
1428 const int64_t t = yi_ - yi_lower;
1429 const int64_t t_1 = precision - t;
1430 const int64_t s = xi_ - xi_lower;
1431 const int64_t s_1 = precision - s;
1433 const int x_ =
static_cast<int>(xi_ >> nbits);
1434 const int y_ =
static_cast<int>(yi_ >> nbits);
1436 if (y_ < static_cast<int>(src.
getHeight())-1 && x_ < static_cast<int>(src.
getWidth())-1) {
1437 const Type val00 = src[y_][x_];
1438 const Type val01 = src[y_][x_+1];
1439 const Type val10 = src[y_+1][x_];
1440 const Type val11 = src[y_+1][x_+1];
1441 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);
1442 const float interp = (interp_i64 >> (nbits*2)) + (interp_i64 & 0xFFFFFFFF) * precision_2;
1443 dst[i][j] = vpMath::saturate<Type>(interp);
1444 }
else if (y_ < static_cast<int>(src.
getHeight())-1) {
1445 const Type val00 = src[y_][x_];
1446 const Type val10 = src[y_+1][x_];
1447 const int64_t interp_i64 =
static_cast<int64_t
>(t_1*val00 + t*val10);
1448 const float interp = (interp_i64 >> nbits) + (interp_i64 & 0xFFFF) * precision_1;
1449 dst[i][j] = vpMath::saturate<Type>(interp);
1450 }
else if (x_ < static_cast<int>(src.
getWidth())-1) {
1451 const Type val00 = src[y_][x_];
1452 const Type val01 = src[y_][x_+1];
1453 const int64_t interp_i64 =
static_cast<int64_t
>(s_1*val00 + s*val01);
1454 const float interp = (interp_i64 >> nbits) + (interp_i64 & 0xFFFF) * precision_1;
1455 dst[i][j] = vpMath::saturate<Type>(interp);
1457 dst[i][j] = src[y_][x_];
1469 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1470 int64_t xi = a2_i64;
1471 int64_t yi = a5_i64;
1472 int64_t wi = a8_i64;
1474 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1475 if (wi != 0 && yi >= 0 && yi <= (static_cast<int>(src.
getHeight()) - 1)*wi &&
1476 xi >= 0 && xi <= (static_cast<int>(src.
getWidth()) - 1)*wi) {
1477 const float wi_ = (wi >> nbits) + (wi & 0xFFFF) * precision_1;
1478 const float xi_ = ((xi >> nbits) + (xi & 0xFFFF) * precision_1) / wi_;
1479 const float yi_ = ((yi >> nbits) + (yi & 0xFFFF) * precision_1) / wi_;
1481 const int x_ =
static_cast<int>(xi_);
1482 const int y_ =
static_cast<int>(yi_);
1484 const float t = yi_ - y_;
1485 const float s = xi_ - x_;
1487 if (y_ < static_cast<int>(src.
getHeight()) - 1 && x_ < static_cast<int>(src.
getWidth()) - 1) {
1488 const Type val00 = src[y_][x_];
1489 const Type val01 = src[y_][x_ + 1];
1490 const Type val10 = src[y_ + 1][x_];
1491 const Type val11 = src[y_ + 1][x_ + 1];
1492 const float col0 = lerp(val00, val01, s);
1493 const float col1 = lerp(val10, val11, s);
1494 const float interp = lerp(col0, col1, t);
1495 dst[i][j] = vpMath::saturate<Type>(interp);
1496 }
else if (y_ < static_cast<int>(src.
getHeight()) - 1) {
1497 const Type val00 = src[y_][x_];
1498 const Type val10 = src[y_ + 1][x_];
1499 const float interp = lerp(val00, val10, t);
1500 dst[i][j] = vpMath::saturate<Type>(interp);
1501 }
else if (x_ < static_cast<int>(src.
getWidth()) - 1) {
1502 const Type val00 = src[y_][x_];
1503 const Type val01 = src[y_][x_ + 1];
1504 const float interp = lerp(val00, val01, s);
1505 dst[i][j] = vpMath::saturate<Type>(interp);
1507 dst[i][j] = src[y_][x_];
1522 double a0 = T[0][0];
double a1 = T[0][1];
double a2 = T[0][2];
1523 double a3 = T[1][0];
double a4 = T[1][1];
double a5 = T[1][2];
1524 double a6 = affine ? 0.0 : T[2][0];
1525 double a7 = affine ? 0.0 : T[2][1];
1526 double a8 = affine ? 1.0 : T[2][2];
1528 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1529 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1530 double x = a0 * (centerCorner ? j + 0.5 : j) + a1 * (centerCorner ? i + 0.5 : i) + a2;
1531 double y = a3 * (centerCorner ? j + 0.5 : j) + a4 * (centerCorner ? i + 0.5 : i) + a5;
1532 double w = a6 * (centerCorner ? j + 0.5 : j) + a7 * (centerCorner ? i + 0.5 : i) + a8;
1533 if (
vpMath::nul(w, std::numeric_limits<double>::epsilon())) {
1537 x = x / w - (centerCorner ? 0.5 : 0);
1538 y = y / w - (centerCorner ? 0.5 : 0);
1540 int x_lower =
static_cast<int>(x);
1541 int y_lower =
static_cast<int>(y);
1543 if (y_lower >= static_cast<int>(src.
getHeight()) || x_lower >= static_cast<int>(src.
getWidth()) ||
1548 double s = x - x_lower;
1549 double t = y - y_lower;
1551 if (y_lower < static_cast<int>(src.
getHeight())-1 && x_lower < static_cast<int>(src.
getWidth())-1) {
1552 const Type val00 = src[y_lower][x_lower];
1553 const Type val01 = src[y_lower][x_lower + 1];
1554 const Type val10 = src[y_lower + 1][x_lower];
1555 const Type val11 = src[y_lower + 1][x_lower + 1];
1556 const double col0 = lerp(val00, val01, s);
1557 const double col1 = lerp(val10, val11, s);
1558 const double interp = lerp(col0, col1, t);
1559 dst[i][j] = vpMath::saturate<Type>(interp);
1560 }
else if (y_lower < static_cast<int>(src.
getHeight())-1) {
1561 const Type val00 = src[y_lower][x_lower];
1562 const Type val10 = src[y_lower + 1][x_lower];
1563 const double interp = lerp(val00, val10, t);
1564 dst[i][j] = vpMath::saturate<Type>(interp);
1565 }
else if (x_lower < static_cast<int>(src.
getWidth())-1) {
1566 const Type val00 = src[y_lower][x_lower];
1567 const Type val01 = src[y_lower][x_lower + 1];
1568 const double interp = lerp(val00, val01, s);
1569 dst[i][j] = vpMath::saturate<Type>(interp);
1571 dst[i][j] = src[y_lower][x_lower];
1580 bool centerCorner,
bool fixedPoint)
1582 if (fixedPoint && !centerCorner) {
1583 const int nbits = 16;
1584 const int64_t precision = 1 << nbits;
1585 const float precision_1 = 1 /
static_cast<float>(precision);
1586 const int64_t precision2 = 1ULL << (2 * nbits);
1587 const float precision_2 = 1 /
static_cast<float>(precision2);
1589 int64_t a0_i64 =
static_cast<int64_t
>(T[0][0] * precision);
1590 int64_t a1_i64 =
static_cast<int64_t
>(T[0][1] * precision);
1591 int64_t a2_i64 =
static_cast<int64_t
>(T[0][2] * precision);
1592 int64_t a3_i64 =
static_cast<int64_t
>(T[1][0] * precision);
1593 int64_t a4_i64 =
static_cast<int64_t
>(T[1][1] * precision);
1594 int64_t a5_i64 =
static_cast<int64_t
>(T[1][2] * precision);
1595 int64_t a6_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[2][0] * precision) : 0;
1596 int64_t a7_i64 = T.
getRows() == 3 ?
static_cast<int64_t
>(T[2][1] * precision) : 0;
1597 int64_t a8_i64 = precision;
1599 int64_t height_i64 =
static_cast<int64_t
>(src.
getHeight() * precision);
1600 int64_t width_i64 =
static_cast<int64_t
>(src.
getWidth() * precision);
1603 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1604 int64_t xi = a2_i64;
1605 int64_t yi = a5_i64;
1607 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1608 if (yi >= 0 && yi < height_i64 && xi >= 0 && xi < width_i64) {
1609 const int64_t xi_lower = xi & (~0xFFFF);
1610 const int64_t yi_lower = yi & (~0xFFFF);
1612 const int64_t t = yi - yi_lower;
1613 const int64_t t_1 = precision - t;
1614 const int64_t s = xi - xi_lower;
1615 const int64_t s_1 = precision - s;
1617 const int x_ =
static_cast<int>(xi >> nbits);
1618 const int y_ =
static_cast<int>(yi >> nbits);
1620 if (y_ < static_cast<int>(src.
getHeight())-1 && x_ < static_cast<int>(src.
getWidth())-1) {
1621 const vpRGBa val00 = src[y_][x_];
1622 const vpRGBa val01 = src[y_][x_+1];
1623 const vpRGBa val10 = src[y_+1][x_];
1624 const vpRGBa val11 = src[y_+1][x_+1];
1625 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);
1626 const float interpR = (interpR_i64 >> (nbits*2)) + (interpR_i64 & 0xFFFFFFFF) * precision_2;
1628 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);
1629 const float interpG = (interpG_i64 >> (nbits * 2)) + (interpG_i64 & 0xFFFFFFFF) * precision_2;
1631 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);
1632 const float interpB = (interpB_i64 >> (nbits * 2)) + (interpB_i64 & 0xFFFFFFFF) * precision_2;
1634 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1635 vpMath::saturate<unsigned char>(interpG),
1636 vpMath::saturate<unsigned char>(interpB),
1638 }
else if (y_ < static_cast<int>(src.
getHeight())-1) {
1639 const vpRGBa val00 = src[y_][x_];
1640 const vpRGBa val10 = src[y_+1][x_];
1641 const int64_t interpR_i64 =
static_cast<int64_t
>(t_1*val00.
R + t*val10.
R);
1642 const float interpR = (interpR_i64 >> nbits) + (interpR_i64 & 0xFFFF) * precision_1;
1644 const int64_t interpG_i64 =
static_cast<int64_t
>(t_1*val00.
G + t * val10.
G);
1645 const float interpG = (interpG_i64 >> nbits) + (interpG_i64 & 0xFFFF) * precision_1;
1647 const int64_t interpB_i64 =
static_cast<int64_t
>(t_1*val00.
B + t * val10.
B);
1648 const float interpB = (interpB_i64 >> nbits) + (interpB_i64 & 0xFFFF) * precision_1;
1650 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1651 vpMath::saturate<unsigned char>(interpG),
1652 vpMath::saturate<unsigned char>(interpB),
1654 }
else if (x_ < static_cast<int>(src.
getWidth())-1) {
1655 const vpRGBa val00 = src[y_][x_];
1656 const vpRGBa val01 = src[y_][x_+1];
1657 const int64_t interpR_i64 =
static_cast<int64_t
>(s_1*val00.
R + s*val01.
R);
1658 const float interpR = (interpR_i64 >> nbits) + (interpR_i64 & 0xFFFF) * precision_1;
1660 const int64_t interpG_i64 =
static_cast<int64_t
>(s_1*val00.
G + s * val01.
G);
1661 const float interpG = (interpG_i64 >> nbits) + (interpG_i64 & 0xFFFF) * precision_1;
1663 const int64_t interpB_i64 =
static_cast<int64_t
>(s_1*val00.
B + s * val01.
B);
1664 const float interpB = (interpB_i64 >> nbits) + (interpB_i64 & 0xFFFF) * precision_1;
1666 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1667 vpMath::saturate<unsigned char>(interpG),
1668 vpMath::saturate<unsigned char>(interpB),
1671 dst[i][j] = src[y_][x_];
1683 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1684 int64_t xi = a2_i64;
1685 int64_t yi = a5_i64;
1686 int64_t wi = a8_i64;
1688 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1689 if (yi >= 0 && yi <= (static_cast<int>(src.
getHeight()) - 1)*wi &&
1690 xi >= 0 && xi <= (static_cast<int>(src.
getWidth()) - 1)*wi) {
1691 const float wi_ = (wi >> nbits) + (wi & 0xFFFF) * precision_1;
1692 const float xi_ = ((xi >> nbits) + (xi & 0xFFFF) * precision_1) / wi_;
1693 const float yi_ = ((yi >> nbits) + (yi & 0xFFFF) * precision_1) / wi_;
1695 const int x_ =
static_cast<int>(xi_);
1696 const int y_ =
static_cast<int>(yi_);
1698 const float t = yi_ - y_;
1699 const float s = xi_ - x_;
1701 if (y_ < static_cast<int>(src.
getHeight()) - 1 && x_ < static_cast<int>(src.
getWidth()) - 1) {
1702 const vpRGBa val00 = src[y_][x_];
1703 const vpRGBa val01 = src[y_][x_ + 1];
1704 const vpRGBa val10 = src[y_ + 1][x_];
1705 const vpRGBa val11 = src[y_ + 1][x_ + 1];
1706 const float colR0 = lerp(val00.
R, val01.
R, s);
1707 const float colR1 = lerp(val10.
R, val11.
R, s);
1708 const float interpR = lerp(colR0, colR1, t);
1710 const float colG0 = lerp(val00.
G, val01.
G, s);
1711 const float colG1 = lerp(val10.
G, val11.
G, s);
1712 const float interpG = lerp(colG0, colG1, t);
1714 const float colB0 = lerp(val00.
B, val01.
B, s);
1715 const float colB1 = lerp(val10.
B, val11.
B, s);
1716 const float interpB = lerp(colB0, colB1, t);
1718 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1719 vpMath::saturate<unsigned char>(interpG),
1720 vpMath::saturate<unsigned char>(interpB),
1722 }
else if (y_ < static_cast<int>(src.
getHeight()) - 1) {
1723 const vpRGBa val00 = src[y_][x_];
1724 const vpRGBa val10 = src[y_ + 1][x_];
1725 const float interpR = lerp(val00.
R, val10.
R, t);
1726 const float interpG = lerp(val00.
G, val10.
G, t);
1727 const float interpB = lerp(val00.
B, val10.
B, t);
1729 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1730 vpMath::saturate<unsigned char>(interpG),
1731 vpMath::saturate<unsigned char>(interpB),
1733 }
else if (x_ < static_cast<int>(src.
getWidth()) - 1) {
1734 const vpRGBa val00 = src[y_][x_];
1735 const vpRGBa val01 = src[y_][x_ + 1];
1736 const float interpR = lerp(val00.
R, val01.
R, s);
1737 const float interpG = lerp(val00.
G, val01.
G, s);
1738 const float interpB = lerp(val00.
B, val01.
B, s);
1740 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1741 vpMath::saturate<unsigned char>(interpG),
1742 vpMath::saturate<unsigned char>(interpB),
1745 dst[i][j] = src[y_][x_];
1760 double a0 = T[0][0];
double a1 = T[0][1];
double a2 = T[0][2];
1761 double a3 = T[1][0];
double a4 = T[1][1];
double a5 = T[1][2];
1762 double a6 = affine ? 0.0 : T[2][0];
1763 double a7 = affine ? 0.0 : T[2][1];
1764 double a8 = affine ? 1.0 : T[2][2];
1766 for (
unsigned int i = 0; i < dst.
getHeight(); i++) {
1767 for (
unsigned int j = 0; j < dst.
getWidth(); j++) {
1768 double x = a0 * (centerCorner ? j + 0.5 : j) + a1 * (centerCorner ? i + 0.5 : i) + a2;
1769 double y = a3 * (centerCorner ? j + 0.5 : j) + a4 * (centerCorner ? i + 0.5 : i) + a5;
1770 double w = a6 * (centerCorner ? j + 0.5 : j) + a7 * (centerCorner ? i + 0.5 : i) + a8;
1772 x = x / w - (centerCorner ? 0.5 : 0);
1773 y = y / w - (centerCorner ? 0.5 : 0);
1775 int x_lower =
static_cast<int>(x);
1776 int y_lower =
static_cast<int>(y);
1778 if (y_lower >= static_cast<int>(src.
getHeight()) || x_lower >= static_cast<int>(src.
getWidth()) ||
1783 double s = x - x_lower;
1784 double t = y - y_lower;
1786 if (y_lower < static_cast<int>(src.
getHeight())-1 && x_lower < static_cast<int>(src.
getWidth())-1) {
1787 const vpRGBa val00 = src[y_lower][x_lower];
1788 const vpRGBa val01 = src[y_lower][x_lower +1];
1789 const vpRGBa val10 = src[y_lower +1][x_lower];
1790 const vpRGBa val11 = src[y_lower +1][x_lower +1];
1791 const double colR0 = lerp(val00.
R, val01.
R, s);
1792 const double colR1 = lerp(val10.
R, val11.
R, s);
1793 const double interpR = lerp(colR0, colR1, t);
1795 const double colG0 = lerp(val00.
G, val01.
G, s);
1796 const double colG1 = lerp(val10.
G, val11.
G, s);
1797 const double interpG = lerp(colG0, colG1, t);
1799 const double colB0 = lerp(val00.
B, val01.
B, s);
1800 const double colB1 = lerp(val10.
B, val11.
B, s);
1801 const double interpB = lerp(colB0, colB1, t);
1803 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1804 vpMath::saturate<unsigned char>(interpG),
1805 vpMath::saturate<unsigned char>(interpB),
1807 }
else if (y_lower < static_cast<int>(src.
getHeight())-1) {
1808 const vpRGBa val00 = src[y_lower][x_lower];
1809 const vpRGBa val10 = src[y_lower +1][x_lower];
1810 const double interpR = lerp(val00.
R, val10.
R, t);
1811 const double interpG = lerp(val00.
G, val10.
G, t);
1812 const double interpB = lerp(val00.
B, val10.
B, t);
1814 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1815 vpMath::saturate<unsigned char>(interpG),
1816 vpMath::saturate<unsigned char>(interpB),
1818 }
else if (x_lower < static_cast<int>(src.
getWidth())-1) {
1819 const vpRGBa val00 = src[y_lower][x_lower];
1820 const vpRGBa val01 = src[y_lower][x_lower +1];
1821 const double interpR = lerp(val00.
R, val01.
R, s);
1822 const double interpG = lerp(val00.
G, val01.
G, s);
1823 const double interpB = lerp(val00.
B, val01.
B, s);
1825 dst[i][j] =
vpRGBa(vpMath::saturate<unsigned char>(interpR),
1826 vpMath::saturate<unsigned char>(interpG),
1827 vpMath::saturate<unsigned char>(interpB),
1830 dst[i][j] = src[y_lower][x_lower];
Implementation of a matrix and operations on matrices.
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned char B
Blue component.
Implementation of row vector and the associated operations.
Type * bitmap
points toward the bitmap
vpMatrix inverseByLU() const
unsigned int getRows() const
Implementation of a generic 2D array used as base class for matrices and vectors. ...
unsigned char G
Green component.
unsigned int getCols() const
static bool nul(double x, double s=0.001)
static double sqr(double x)
Generic class defining intrinsic camera parameters.
static int round(double x)
unsigned int getHeight() const
unsigned int getSize() const
unsigned char R
Red component.
Defines a rectangle in the plane.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
unsigned int getWidth() const
Definition of the vpImage class member functions.
Defines an oriented rectangle in the plane.