int shomwarp(float *X, int W, int H, double M[9], float *x, int w, int h, int o) { // if low order-interpolation, evaluate right away if (o == 0 || o == 1 || o == 2 || o == -3) return homwarp(X, W, H, M, x, w, h, o); // otherwise, pre-filtering is required bool r = prepare_spline(x, w, h, 1, o); if (!r) return 2; // warp the points for (int j = 0; j < H; j++) for (int i = 0; i < W; i++) { double p[2] = {i, j}; apply_homography(p, M, p); p[0] += 0.5; // solve a mis-alignement convention p[1] += 0.5; float *out = X + (j*W + i); evaluate_spline_at(out, x, w, h, 1, o, p[0], p[1]); } return 0; }
static void naive_affine_map_using_spline(float *y, int out_w, int out_h, float *x, int w, int h, int pd, double A[6], int order) { float *fx = malloc(w * h * pd * sizeof*fx); for (int i = 0; i < w * h * pd; i++) fx[i] = x[i]; bool r = prepare_spline(fx, w, h, pd, order); if (!r) exit(fprintf(stderr,"prepare spline failed (ord=%d)\n",order)); //if (1) { // char buf[FILENAME_MAX]; // snprintf(buf,FILENAME_MAX,"/tmp/prepared_spline_%d.tiff",order); // iio_save_image_float_vec(buf, fx, w, h, pd); //} double invA[6]; invert_affinity(invA, A); for (int j = 0; j < out_h; j++) for (int i = 0; i < out_w; i++) { double p[2] = {i, j}; apply_affinity(p, A, p); float *out = y + (j * out_w + i) * pd; evaluate_spline_at(out, fx, w, h, pd, order, p[0], p[1]); } free(fx); }
/// Apply geometric transform to image. /// /// The transformation \a map is applied to the image \a in and the result /// stored in \a im. If \a adjustSize is \c true, \a im will be sized so that /// it contains all the transformed rectangle, otherwise it stays at original /// size. /// /// The returned pair of integers is the offset of the returned image \a im /// with respect to original image \a in. If \a adjustSize is \c false, this is /// (0,0), otherwise the location of upper-left corner of \a im in pixel /// coordinates of \a in. /// /// Interpolation is done by spline. Anti-aliasing filter is optional. /// /// \a vOut is the background value to put at pixels outside image. std::pair<int,int> map_image(LWImage<float> in, libNumerics::Homography map, LWImage<float>& im, int order, bool adjustSize, bool antiAlias, float vOut) { int w = in.w, h = in.h; float zoomOut = antiAlias? static_cast<float>( minZoomOut(map.mat(), w, h) ): 1.0f; const libNumerics::Homography oriMap(map); const int oriW=w, oriH=h; std::pair<int,int> offset(0,0); if(adjustSize) { offset = boundingBox(map, w, h); free(im.data); im = alloc_image<float>(w, h, in.comps); } if(zoomOut < 1.0f) { float zoomIn = 1.0f / zoomOut; // GF: added some extra space int wZoom=(int)std::ceil(w*zoomIn*1.5), hZoom=(int)std::ceil(h*zoomIn*1.5); LWImage<float> imZoom = alloc_image<float>(wZoom,hZoom,in.comps); libNumerics::matrix<double> mapZ(3,3); mapZ = 0.0; mapZ(0,0) = zoomIn; mapZ(1,1) = zoomIn; mapZ(2,2) = 1.0; map.mat() = mapZ*map.mat(); map_image(in, map, imZoom, order, false, false, vOut); float sigma = 0.8f*sqrt(zoomIn*zoomIn-1.0f); gauss_convol(imZoom, sigma); map.mat() = 0.0; map.mat()(0,0)=zoomOut; map.mat()(1,1)=zoomOut; map.mat()(2,2)=1.0; in = imZoom; } LWImage<float> tmp = alloc_image(in); if( prepare_spline(tmp,order) ) { libNumerics::Homography inv = map.inverse(); const int stepComp = im.stepComp(); float* out = new float[im.comps]; float* pixOut = im.data; for(int i = 0; i < im.h; i++) for(int j = 0; j < im.w; j++) { double x=j+offset.first, y=i+offset.second; inv(x,y); for(int k=0; k < im.comps; k++) out[k] = vOut; interpolate_spline(tmp, order, static_cast<float>(x+.5), static_cast<float>(y+.5), out); for(int k=0; k < im.comps; k++) pixOut[k*stepComp] = out[k]; pixOut += im.step(); } delete [] out; } free(tmp.data); if(zoomOut < 1.0f) { free(in.data); // Was allocated above if(! is_number(vOut)) { // Put back mask libNumerics::Homography inv = oriMap.inverse(); const int stepComp = im.stepComp(); float* pixOut = im.data; for(int i = 0; i < im.h; i++) for(int j = 0; j < im.w; j++) { double x=j+offset.first, y=i+offset.second; inv(x,y); if(x<0 || x>=oriW || y<0 || y>=oriH) for(int k=0; k < im.comps; k++) pixOut[k*stepComp] = NaN; pixOut += im.step(); } } } return offset; }