/******************* TO DO ********************* * warpSphericalField: * INPUT: * srcSh: shape (width, height, number of channels) of source image * dstSh: shape of destination image * f: focal length in pixels (provided on the project web page, or measured by yourself) * r: rotation matrix * OUTPUT: * Return an image containing (u,v) coordinates for mapping pixels from * spherical coordinates to planar image coordinates. * Note that this is inverse warping, i.e., this routine will be * actually used to map from planar coordinates to spherical coordinates. * */ CImg<float> WarpSphericalField(CShape srcSh, CShape dstSh, float f, const CTransform3x3 &r) { // Set up the pixel coordinate image dstSh.nBands = 2; CImg<float> uvImg(dstSh.width, dstSh.height, 1, dstSh.nBands); // (u,v) coordinates // Fill in the values for (int y = 0; y < dstSh.height; y++) { //float *uv = &uvImg.Pixel(0, y, 0); for (int x = 0; x < dstSh.width; x++) { // (x,y) is the spherical image coordinates. // (xf,yf) is the spherical coordinates, e.g., xf is the angle theta // and yf is the angle phi float xf = 2*M_PI * (x - 0.5f*dstSh.width) / dstSh.width; float yf = M_PI * (y - 0.5f*dstSh.height) / dstSh.height; // (xt,yt,zt) are intermediate coordinates to which you can // apply the spherical correction float xt=0, yt=0, zt=0; CVector3 p; // *** BEGIN TODO *** // add code to apply the spherical correction, i.e., // compute the Euclidean coordinates, rotate according to // r, and project the point to the z=1 plane at // (xt/zt,yt/zt,1) // // don't forget to deal with points that have negative // z values appropriately, or you'll have each point on // the z=1 plane mapping to two opposite points on the // sphere // *** END TODO *** // Convert back to regular pixel coordinates and store float xn = 0.5f*srcSh.width + xt*f; float yn = 0.5f*srcSh.height + yt*f; uvImg(x, y, 0, 0) = xn; uvImg(x, y, 0, 1) = yn; } } return uvImg; }
/******************* TO DO ********************* * warpRDField: * INPUT: * srcSh: shape (width, height, number of channels) of source image * dstSh: shape of destination image * f: focal length * k1, k2: radial distortion parameters * OUTPUT: * Return an image containing (u,v) coordinates for applying * radial distortion. * Note that this is inverse warping, i.e., this routine will be * actually used to map from planar coordinates with radial distortion * to planar coordinates without radial distortion. * */ CImg<float> WarpRDField(CShape srcSh, CShape dstSh, float f, float k1, float k2) { // Set up the pixel coordinate image dstSh.nBands = 2; CImg<float> uvImg(dstSh.width, dstSh.height, 1, dstSh.nBands); // (u,v) coordinates // Fill in the values for (int y = 0; y < dstSh.height; y++) { //float *uv = &uvImg.Pixel(0, y, 0); //for (int x = 0; x < dstSh.width; x++, uv += 2) for (int x = 0; x < dstSh.width; x++) { // (x,y) is the planar image coordinates // (xf,yf) is the planar coordinates float xf = (x - 0.5f*dstSh.width) / f; float yf = (y - 0.5f*dstSh.height) / f; // (xt,yt) are intermediate coordinates to which you can // apply the radial distortion float xt = 0; float yt = 0; // *** BEGIN TODO *** // add code to distort with radial distortion coefficients // k1 and k2 float r2 = xf*xf + yf*yf; xt = xf / (1.0 + k1*r2 + k2*r2*r2); yt = yf / (1.0 + k1*r2 + k2*r2*r2); // *** END TODO *** // Convert back to regular pixel coordinates and store float xn = 0.5f*srcSh.width + xt*f; float yn = 0.5f*srcSh.height + yt*f; uvImg(x, y, 0, 0) = xn; uvImg(x, y, 0, 1) = yn; /*uv[0] = xn; uv[1] = yn;*/ } } return uvImg; }
/******************* TO DO ********************* * warpSphericalField: * INPUT: * srcSh: shape (width, height, number of channels) of source image * dstSh: shape of destination image * f: focal length in pixels (provided on the project web page, or measured by yourself) * k1, k2: radial distortion parameters (ditto) * r: rotation matrix * OUTPUT: * Return an image containing (u,v) coordinates for mapping pixels from * spherical coordinates to planar image coordinates and applying * radial distortion. * Note that this is inverse warping, i.e., this routine will be * actually used to map from planar coordinates with radial distortion * to spherical coordinates without radial distortion. * */ CFloatImage WarpSphericalField(CShape srcSh, CShape dstSh, float f, float k1, float k2, const CTransform3x3 &r) { // Set up the pixel coordinate image dstSh.nBands = 2; CFloatImage uvImg(dstSh); // (u,v) coordinates // Fill in the values for (int y = 0; y < dstSh.height; y++) { float *uv = &uvImg.Pixel(0, y, 0); for (int x = 0; x < dstSh.width; x++, uv += 2) { // (x,y) is the spherical image coordinates. // (xf,yf) is the spherical coordinates, e.g., xf is the angle theta // and yf is the angle phi float xf = (x - 0.5f*dstSh.width ) / f; float yf = (y - 0.5f*dstSh.height) / f; // (xt,yt,zt) are intermediate coordinates to which you can // apply the spherical correction and radial distortion float xt, yt, zt; CVector3 p; // *** BEGIN TODO *** // add code to apply the spherical correction, i.e., // compute the Euclidean coordinates, rotate according to // r, and project the point to the z=1 plane at // (xt/zt,yt/zt,1), then distort with radial distortion // coefficients k1 and k2 //Spherical warping float xbar = sin(xf) * cos(yf); float ybar = sin(yf); float zbar = cos(xf) * sin(yf); //Do radial distortion float rbar_power2 = xbar * xbar + ybar * ybar; xt = xbar / (1 + k1 * rbar_power2 + k2 * rbar_power2 * rbar_power2); yt = ybar / (1 + k1 * rbar_power2 + k2 * rbar_power2 * rbar_power2); zt = zbar; // *** END TODO *** // Convert back to regular pixel coordinates and store float xn = 0.5f*srcSh.width + xt*f; float yn = 0.5f*srcSh.height + yt*f; uv[0] = xn; uv[1] = yn; } } return uvImg; }
/******************* TO DO ********************* * warpRDField: * INPUT: * srcSh: shape (width, height, number of channels) of source image * dstSh: shape of destination image * f: focal length * k1, k2: radial distortion parameters * OUTPUT: * Return an image containing (u,v) coordinates for applying * radial distortion. * Note that this is inverse warping, i.e., this routine will be * actually used to map from planar coordinates with radial distortion * to planar coordinates without radial distortion. * */ CImg<float> WarpRDField(CShape srcSh, CShape dstSh, float f, float k1, float k2) { // Set up the pixel coordinate image dstSh.nBands = 2; CImg<float> uvImg(dstSh.width, dstSh.height, 1, dstSh.nBands); // (u,v) coordinates // Fill in the values for (int y = 0; y < dstSh.height; y++) { //float *uv = &uvImg.Pixel(0, y, 0); //for (int x = 0; x < dstSh.width; x++, uv += 2) for (int x = 0; x < dstSh.width; x++) { // (x,y) is the planar image coordinates // (xf,yf) is the planar coordinates float xt = (x - 0.5f*dstSh.width) / f; float yt = (y - 0.5f*dstSh.height) / f; // *** BEGIN TODO *** // add code to distort with radial distortion coefficients // k1 and k2 float r = xt * xt + yt * yt; xt = xt * (1 + k1 * r + k2 * r * r); yt = yt * (1 + k1 * r + k2 * r * r); // *** END TODO *** // Convert back to regular pixel coordinates and store float xn = 0.5f*srcSh.width + xt*f; float yn = 0.5f*srcSh.height + yt*f; uvImg(x, y, 0, 0) = xn; uvImg(x, y, 0, 1) = yn; } } return uvImg; }
/******************* TO DO ********************* * warpSphericalField: * INPUT: * srcSh: shape (width, height, number of channels) of source image * dstSh: shape of destination image * f: focal length in pixels (provided on the project web page, or measured by yourself) * k1, k2: radial distortion parameters (ditto) * r: rotation matrix * OUTPUT: * Return an image containing (u,v) coordinates for mapping pixels from * spherical coordinates to planar image coordinates and applying * radial distortion. * Note that this is inverse warping, i.e., this routine will be * actually used to map from planar coordinates with radial distortion * to spherical coordinates without radial distortion. * */ CFloatImage WarpSphericalField(CShape srcSh, CShape dstSh, float f, float k1, float k2, const CTransform3x3 &r) { // Set up the pixel coordinate image dstSh.nBands = 2; CFloatImage uvImg(dstSh); // (u,v) coordinates CVector3 p; p[0] = sin(0.0) * cos(0.0); p[1] = sin(0.0); p[2] = cos(0.0) * cos(0.0); p = r * p; double min_y = p[1]; // Fill in the values for (int y = 0; y < dstSh.height; y++) { float *uv = &uvImg.Pixel(0, y, 0); for (int x = 0; x < dstSh.width; x++, uv += 2) { // (x,y) is the spherical image coordinates. // (xf,yf) is the spherical coordinates, e.g., xf is the angle theta // and yf is the angle phi float xf = (float) ((x - 0.5f*dstSh.width ) / f); float yf = (float) ((y - 0.5f*dstSh.height) / f - min_y); // (xt,yt,zt) are intermediate coordinates to which you can // apply the spherical correction and radial distortion float xt, yt, zt; CVector3 p; // BEGIN TODO // add code to apply the spherical correction, i.e., // compute the Euclidean coordinates, rotate according to // r, and project the point to the z=1 plane at // (xt/zt,yt/zt,1), then distort with radial distortion // coefficients k1 and k2 //change to spherical coordinates p[0] = sin(xf)*cos(yf); p[1] = sin(yf); p[2] = cos(xf)*cos(yf); //rotate by r p = r * p; //normalize to z = 1 plane xt = p[0]/p[2]; yt = p[1]/p[2]; //apply distortion float r = xt*xt + yt*yt; xt = xt*(1 + k1*r + k2*r*r); yt = yt*(1 + k1*r + k2*r*r); // END TODO // Convert back to regular pixel coordinates and store float xn = 0.5f*srcSh.width + xt*f; float yn = 0.5f*srcSh.height + yt*f; uv[0] = xn; uv[1] = yn; } } return uvImg; }