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);
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;
1106 if (method == INTERPOLATION_AREA) {
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;
1131 if (method == INTERPOLATION_NEAREST) {
1132 resizeNearest(I, Ires, static_cast<unsigned int>(i), j, u, v);
1133 }
else if (method == INTERPOLATION_LINEAR) {
1134 resizeBilinear(I, Ires, static_cast<unsigned int>(i), j, u0, v0, xFrac, yFrac);
1135 }
else if (method == INTERPOLATION_CUBIC) {
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;
1155 if (method == INTERPOLATION_AREA) {
1157 }
else if (method == INTERPOLATION_LINEAR) {
1158 resizeSimdlib(I, Ires.
getWidth(), Ires.
getHeight(), Ires, INTERPOLATION_LINEAR);
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);
1178 if (method == INTERPOLATION_NEAREST) {
1179 resizeNearest(I, Ires, static_cast<unsigned int>(i), j, u, v);
1180 }
else if (method == INTERPOLATION_CUBIC) {
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;
1201 if (method == INTERPOLATION_AREA) {
1203 }
else if (method == INTERPOLATION_LINEAR) {
1204 resizeSimdlib(I, Ires.
getWidth(), Ires.
getHeight(), Ires, INTERPOLATION_LINEAR);
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);
1224 if (method == INTERPOLATION_NEAREST) {
1225 resizeNearest(I, Ires, static_cast<unsigned int>(i), j, u, v);
1226 }
else if (method == INTERPOLATION_CUBIC) {
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);
1263 const bool interp_NN = (interpolation == INTERPOLATION_NEAREST) || (interpolation == INTERPOLATION_CUBIC);
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 matrix and operations on matrices.
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
unsigned int getWidth() const
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
Implementation of a generic 2D array used as base class for matrices and vectors. ...
unsigned int getCols() const
unsigned char G
Green component.
static bool nul(double x, double s=0.001)
unsigned int getSize() const
static double sqr(double x)
Generic class defining intrinsic camera parameters.
unsigned int getRows() const
static int round(double x)
unsigned char R
Red component.
vpMatrix inverseByLU() const
unsigned int getHeight() const
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 ...
Definition of the vpImage class member functions.
Defines an oriented rectangle in the plane.