creating image using polar coordinates (image transformations) - c++

I'm working on image warping. The transformed version of the real coordinates of an image are x and y, and, the polar coordinates of the transformed image are r and theta.
(cylindrical anamorphosis). I have the transformation functions. But Im confused about a certain things. I'm getting the polar coordinates from transformation functions which can easily be converted to cartesian. But how to draw this transformed image? as the new size will be different than the old image size.
EDIT : I have the image as shown in the cylinder. I have the transformation function to convert it into the illusion image as shown. As this image's size is different from the original image, how do I ensure that all my points in the main image are being transformed. Moreover the coordinates of those points in transformed image are polar. Can I use openCV to form the new image using the transformed polar coordinates?
REF: http://www.physics.uoguelph.ca/phyjlh/morph/Anamorph.pdf

You have two problems here. In my understanding, the bigger problem arises because you are converting discrete integral coordinates into floating point coordinates. The other problem is that the resulting image's size is larger or smaller than the original image's size. Additionally, the resulting image does not have to be rectangular, so it will have to be either cropped, or filled with black pixels along the corners.
According to http://opencv.willowgarage.com/documentation/geometric_image_transformations.html there is no radial transformation routine.
I'd suggest you do the following:
Upscale the original image to have width*2, height*2. Set the new image to black. (cvResize, cvZero)
Run over each pixel in the original image. Find the new coordinates of the pixel. Add 1/9 of its value to all 8 neighbors of the new
coordinates, and to the new coordinates itself. (CV_IMAGE_ELEM(...) +=
1.0/9 * ....)
Downscale the new image back to the original width, height.
Depending on the result, you may want to use a sharpening routine.
If you want to KEEP some pixels that go out of bounds, that's a different question. Basically you want to find Min and Max of the coordinates you receive, so for example your original image has Min,Max = [0,1024] and your new MinNew,MaxNew = [-200,1200] you make a function
normalize(int &convertedx,int &convertedy)
{
convertedx = MinNewX + (MaxNewX-MinNewX)/(MaxX-MinX) * convertedx;
convertedy = ...;
}

Related

OpenCV triangulatePoints - what are the correct coordinates to feed it with?

Previously, I was using another method to determine 3D positions from two 2D images. For that (mediocre) method I had to get 2D coordinates with a point of origin in the center of the image. Because of that, I get a lot of negative values. OpenCV normally uses the let bottom corner as the coordinates origin point (no negative values at all)
The app user is supposed to be able to use either method. Can I keep collecting 2D coordinates that way, or do I have to change it? If not, do I have to use the new center point of the image (result of cv::stereoCalibrate) instead of the default one, (frame.cols/2 , frame.rows/2)?
When using OpenCV's triangulatePoints, you need to pass as arguments:
projectionMatrixA - implicitly contains intrinsic camera parameters (focal length & Principal Point Offset which is the pixel offset from the left and from the top that should be considered as 0,0)
projectionMatrixB - besides intrinsic camera parameteres, projection matrix also reflects the position of the camera in relation to some coordinate system. So if you have two identical cameras, the two projection matrices would still differ because they are positioned differently.
2D points that are a result of 3D points being projected using projectionMatrixA
2D points that are a result of 3D points being projected using projectionMatrixB
To answer the question, there is nothing wrong with the fact that 2D points have negative values.
AFAIK, in the calib module, when dealing with 2D points (pixel coordinates), the coordinate (0,0) should always be around the center of the image and not in the top left corner. So naturally, any points in the left region of the image have x < 0, and any point in the upper region of the image have y < 0.

Bilinear interpolation on fisheye filter

I have to implement a fisheye transfromation with bilinear interpolation. After the transformation of one pixel i don't have integer coordinates anymore and I would like to map this pixel on integer coordinates using bilinear interpolation. The problem is that everithing I found on bilinear interpolation on the inetrnete (see for example Wikipedia) does the opposite thing: it gives the value of one non-integer pixel by using the coordinates of four neighbors that have integer coordinates. I would like to do the opposite, i.e. map the one pixel with non-integer coordinates to the four neighbors with integer coordinates. Surely there is something that I am missing and would be helpful to understand where I am wrong.
EDIT:
TO be more clear: Let say that I have the pixel (i,j)=(2,2) of the starting image. After the fisheye transformation I obtain non-integer coordinates, for example (2.1,2.2). I want to save this new pixel to a new image but obviously I don't know in which pixel to save it because of non-integer coordinates. The easiest way is to truncate the coordinates, but the image quality is not very good: I have to use bilinear interpolation. Despite this I don't understand how it works because I want to split my non integer pixel to neighboring pixels with integer coordinates of the new (transformed image), but I found description only of the opposite operation, i.e. finding non-integer coordinates starting from four integer pixels (http://en.wikipedia.org/wiki/Bilinear_interpolation)
Your question is a little unclear. From what I understand, you have a regular image which you want to transform into a fisheye-like image. To do this, I am guessing you take each pixel coordinate {xr,yr} from the regular image, use the fisheye transformation to obtain the corresponding coordinates {xf,yf} in the fisheye-like image. You would like to assign the initial pixel intensity to the destination pixel, however you do not know how to do this since {xf,yf} are not integer values.
If that's the case, you are actually taking the problem backwards. You should start from integer pixel coordinates in the fisheye image, use the inverse fisheye transformation to obtain floating-point pixel coordinates in the regular image, and use bilinear interpolation to estimate the intensity of the floating point coordinates from the 4 closest integer coordinates.
The basic procedure is as follows:
Start with integer pixel coordinates (xf,yf) in the fisheye image (e.g. (2,3) in the fisheye image). You want to estimate the intensity If associated to these coordinates.
Find the corresponding point in the "starting" image, by mapping (xf,yf) into the "starting" image using the inverse fisheye transformation. You obtain floating-point pixel coordinates (xs,ys) in the "starting" image (e.g. (2.2,2.5) in the starting image).
Use Bilinear Interpolation to estimate the intensity Is at coordinates (xs,ys), based on the intensity of the 4 closest integer pixel coordinates in the "starting" image (e.g. (2,2), (2,3), (3,2), (3,3) in the starting image)
Assign Is to If
Repeat from step 1. with the next integer pixel coordinates, until the intensity of all pixels of the fisheye image have been found.
Note that deriving the inverse fisheye transformation might be a little tricky, depending on the equations... However, that is how image resampling has to be performed.
You need to find the inverse fisheye transform first, and use "backward wrap" to go from the destination image to the source image.
I'll give you a simple example. Say you want to expand the image by a non integral factor of 1.5. So you have
x_dest = x_source * 1.5, y_dest = y_source * 1.5
Now if you iterate over the coordinates in the original image, you'll get non-integral coordinates in the destination image. E.g., (1,1) will be mapped to (1.5, 1.5). And this is your problem, and in general the problem with "forward wrapping" an image.
Instead, you reverse the transformation and write
x_source = x_dest / 1.5, y_source = y_dest / 1.5
Now you iterate over the destination image pixels. For example, pixel (4,4) in the destination image comes from (4/1.5, 4/1.5) = (2.6, 2.6) in the source image. These are non-integral coordinates and you use the 4 neighboring pixels in the source image to estimate the color at this coordinate (in our example the pixels at (2,2), (2,3), (3,2) and (3,3))

Opencv Warp perspective whole image

I'm struggling with this problem:
I have the an image and I want to apply a warp perspective to it (I already have the transformation matrix) but instead of the output only having the transformation area (like the example below) I want to be able to see the whole image instead.
EXAMPLE http://docs.opencv.org/trunk/_images/perspective.jpg
Instead of having the transformation region, like this example, I want to transform the whole original image.
How can I achieve this?
Thanks!
It seems that you are computing the perspective transform by selecting the corners of the sudoku grid in the input image and requesting them to be warped at fixed location in the output image. In your example, it seems that you are requesting the top-left corner to be warped at coordinates (0,0), the top-right corner at (300,0), the bottom-left at (0,300) and the bottom-right at (300,300).
This will always result in the cropping of the image area on the left of the two left corners and above the two top corners (i.e. the image area where x<0 or y<0 in the output image). Also, if you specify an output image size of 300x300, this results in the cropping of the image area on the right to the right corners and below the bottom corners.
If you want to keep the whole image, you need to use different output coordinates for the corners. For example warp TLC to (100, 100), TRC to (400,100), BLC to (100,400) and BRC to (400,400), and specify an output image size of 600x600 for instance.
You can also calculate the optimal coordinates as follows:
Compute the default perspective transform H0 (as you are doing now)
Transform the corners of the input image using H0, and compute the minimum and maximum values for the x and y coordinates of these corners. Let's denote them xmin, xmax, ymin, ymax.
Compute the translation necessary to map the point (xmin,ymin) to (0,0). The matrix of this translation is T = [1, 0, -xmin; 0, 1, -ymin; 0, 0, 1].
Compute the optimised perspective transform H1 = T*H0 and specify an output image size of (xmax-xmin) x (ymax-ymin).
This way, you are guaranteed that:
the four corners of your input sudoku grid will form a true square
the output image will be translated so that no useful image data is cropped above or to the left of the grid corners
the output image will be have sized so that no useful image data is cropped below or to the right of the grid corners
However, this will generate black areas since the ouput image is no longer a perfect rectangle, hence some pixels in the output image won't have any correspondence in the input image.
Edit 1: If you want to replace the black areas with something else, you can initialize the destination matrix as you wish and then set the borderMode parameter of the warpPerspective function to BORDER_TRANSPARENT.

Projection of set of 3D points into virtual image plane in opencv c++

Anyone know how to project set of 3D points into virtual image plane in opencv c++
Thank you
First you need to have your transformation matrix defined (rotation, translation, etc) to map the 3D space to the 2D virtual image plane, then just multiply your 3D point coordinates (x, y, z) to the matrix to get the 2D coordinates in the image.
registration (OpenNI 2) or alternative viewPoint capability (openNI 1.5) indeed help to align depth with rgb using a single line of code. The price you pay is that you cannot really restore exact X, Y point locations in 3D space since the row and col are moved after alignment.
Sometimes you need not only Z but also X, Y and want them to be exact; plus you want the alignment of depth and rgb. Then you have to align rgb to depth. Note that this alignment is not supported by Kinect/OpenNI. The price you pay for this - there is no RGB values in the locations where depth is undefined.
If one knows extrinsic parameters that is rotation and translation of the depth camera relative to color one then alignment is just a matter of making an alternative viewpoint: restore 3D from depth, and then look at your point cloud from the point of view of a color camera: that is apply inverse rotation and translation. For example, moving camera to the right is like moving the world (points) to the left. Reproject 3D into 2D and interpolate if needed. This is really easy and is just an inverse of 3d reconstruction; below, Cx is close to w/2 and Cy to h/2;
col = focal*X/Z+Cx
row = -focal*Y/Z+Cy // this is because row in the image increases downward
A proper but also more expensive way to get a nice depth map after point cloud rotation is to trace rays from each pixel till it intersects the point cloud or come sufficiently close to one of the points. In this way you will have less holes in your depth map due to sampling artifacts.

accessing a transformed texture's pixel data

How do i access the TRANSFORMED pixel data for a texture, after it has been transformed (rotated and scaled) by D3DXMatrixTransformation2D() and texture->SetTransform()?
I'm trying to do 2D pixel perfect collision detection and it's impossible if you can only access the untransformed pixel data using texture->LockRect().
Anybody got any ideas?
This will not achieve the results you wish. With the SetTransform method you set a transformation which is applied before the texture is drawn. So it wont morph your image that you can read out the pixel values.
What you could do is to project world coordinates to UV coordinates of your texture and then read out the according pixel value and compare it and do your collision resolution there.
I guess you use the inverse matrix of the matrix you created by D3DXMatrixTransformation2D().