Convert Centroid points generated at Image Size 640 * 640 (image size) to size 622*1186 (image size) - opencv

I want to convert point (i.e 622,622) coordinates to other dimensional coordinates (622*1186) Using OpenCV. i.e I currently plotted the data at Image Size 640 * 640.
Now I want to plot it at 622*1186 Image size. I want to know the formula so that I can convert them. I am working with OpenCV.

Ok, So I am answering my own Question!
The formula to convert the point (x, y) from the original size (width_original, height_original) to a new size (width_new, height_new) is:
x_new = x * width_new / width_original
y_new = y * height_new / height_original
So, in the above case:
x_new = 622 * 1186 / 640 = 622 * 1186 / 640 = 1176.25
y_new = 622 * 1186 / 640 = 622 * 1186 / 640 = 1176.25
So the new coordinates of the point would be (1176.25, 1176.25) in the 622 x 1186 image.

Related

opencv tobytes returns more bytes than expected

I have a image frame of dimension say 224 * 224 * 3. After calling the following lines, the size of returned bytes is 150536 (8 more bytes than 224 * 224 * 3). Is this normal?
mat = cv2.imdecode(image_frame, cv2.IMREAD_COLOR)
mat = cv2.resize(mat, (224, 224))
data_frame = mat[:,:,::-1].tobytes()

Error in radial distortion based on (zoomed in) OpenCV-style camera parameters

Our AR device is based on a camera with pretty strong optical zoom. We measure the distortion of this camera using classical camera-calibration tools (checkerboards), both through OpenCV and the GML Camera Calibration tools.
At higher zoom levels (I'll use 249 out of 255 as an example) we measure the following camera parameters at full HD resolution (1920x1080):
fx = 24545.4316
fy = 24628.5469
cx = 924.3162
cy = 440.2694
For the radial and tangential distortion we measured 4 values:
k1 = 5.423406
k2 = -2964.24243
p1 = 0.004201721
p2 = 0.0162647516
We are not sure how to interpret (read: implement) those extremely large values for k1 and k2. Using OpenCV's classic "undistort" operation to rectify the image using these values seems to work well. Unfortunately this is (much) too slow for realtime usage.
The thumbnails below look similar, clicking them will display the full size images where you can spot the difference:
Camera footage
Undistorted using OpenCV
That's why we want to take the opposite aproach: leave the camera footage be distorted and apply a similar distortion to our 3D scene using shaders. Following the OpenCV documentation and this accepted answer in particular, the distorted position for a corner point (0, 0) would be
// To relative coordinates
double x = (point.X - cx) / fx; // -960 / 24545 = -0.03911
double y = (point.Y - cy) / fy; // -540 / 24628 = -0.02193
double r2 = x*x + y*y; // 0.002010
// Radial distortion
// -0.03911 * (1 + 5.423406 * 0.002010 + -2964.24243 * 0.002010 * 0.002010) = -0.039067
double xDistort = x * (1 + k1 * r2 + k2 * r2 * r2);
// -0.02193 * (1 + 5.423406 * 0.002010 + -2964.24243 * 0.002010 * 0.002010) = -0.021906
double yDistort = y * (1 + k1 * r2 + k2 * r2 * r2);
// Tangential distortion
... left out for brevity
// Back to absolute coordinates.
xDistort = xDistort * fx + cx; // -0.039067 * 24545.4316 + 924.3162 = -34.6002 !!!
yDistort = yDistort * fy + cy; // -0.021906 * 24628.5469 + 440.2694 = = -99.2435 !!!
These large pixel displacements (34 and 100 pixels at the upper left corner) seem overly warped and do not correspond with the undistorted image OpenCV generates.
So the specific question is: what is wrong with the way we interpreted the values we measured, and what should the correct code for distortion be?

OpenCV How to apply camera distortion to an image

I have an rendered Image. I want to apply radial and tangential distortion coefficients to my image that I got from opencv. Even though there is undistort function, there is no distort function. How can I distort my images with distortion coefficients?
I was also looking for the same type of functionality. I couldn't find it, so I implemented it myself. Here is the C++ code.
First, you need to normalize the image point using the focal length and centers
rpt(0) = (pt_x - cx) / fx
rpt(1) = (pt_y - cy) / fy
then distort the normalized image point
double x = rpt(0), y = rpt(1);
//determining the radial distortion
double r2 = x*x + y*y;
double icdist = 1 / (1 - ((D.at<double>(4) * r2 + D.at<double>(1))*r2 + D.at<double>(0))*r2);
//determining the tangential distortion
double deltaX = 2 * D.at<double>(2) * x*y + D.at<double>(3) * (r2 + 2 * x*x);
double deltaY = D.at<double>(2) * (r2 + 2 * y*y) + 2 * D.at<double>(3) * x*y;
x = (x + deltaX)*icdist;
y = (y + deltaY)*icdist;
then you can translate and scale the point using the center of projection and focal length:
x = x * fx + cx
y = y * fy + cy

screen coordinates of a vertex with pointSize bigger than 1

assuming the canvas size is (wx,wy), the exact coordinates of the vertex lower and left is (-1 + 1/wx , -1 + 1/wy).
But when the pointSize is bigger than 1, i dont managed to find a formula.
in this fiddle, https://jsfiddle.net/3u26rpf0/14/ i draw some pixels of size=1 with the following formula for gl_Position :
float p1 = -1.0 + (2.0 * a_position.x + 1.0) / wx ;
float p2 = -1.0 + (2.0 * a_position.y + 1.0) / wy ;
gl_Position=vec4(p1,p2,0.0,1.0);
a_position.x goes from 0 to wx-1 .
a_position.y goes from 0 to wy-1 .
but if you change the value of size in the vertex (see fiddle link)
my formula doesn't work, there is some offset to put.
From the OpenGL ES 2.0 spec section 3.3
Point rasterization produces a fragment for each framebuffer pixel whose center
lies inside a square centered at the point’s (xw, yw), with side length equal to
the point size

Why doesn't opencv report width and height of a IplImage* correctly?

I got the reference image of a video(.avi) so the the width and height of the image must be as the same as the width and height of the video is and it is.
(my video is a CvCapture* and my image is a IplImage*)
Width is 1280 and height is 960;
But when I told OpenCV that if the coordinate of a pixel is in the specific rectangle then do something. All of the width of the image was the width of that rectangle.
const int Y1 = 430, Y2 = 730, X1 = 0, X2 = 1279 ;
for (int i = Y1; i <= Y2; i++)
for (int j = X1; j <= X2; j++)
CV_IMAGE_ELEM(frame_BGR, uchar, i, j) = 255;
But only near 1/5 of the width of the page is now white! Then I X2 = 3000. Then all of the width of the image is now white and silly thing is that when I change X2 = 10000 then code didn't report SEGMENTATION FAULT.
Why the width-reporting is not working correctly?
I run it on both Ubuntu - g++ and and Windows 7 - visual studio 2010. I think my resolution is high. I know that the video is taken by a Nokia 5800 cellphone. It is so important for me, so excuse me if I was very specific!
If the image isn't single channel , you are using CV_IMAGE_ELEM wrongly
It has to be pixel = CV_IMAGE_ELEM( frame_BGR, uchar, row_number, col_number * 3 + color_channel );
So for BGR:
uchar blue = CV_IMAGE_ELEM( frame_BGR, uchar, row_number, col_number * 3 + 0 );
uchar green = CV_IMAGE_ELEM( frame_BGR, uchar, row_number, col_number * 3 + 1 );
uchar red = CV_IMAGE_ELEM( frame_BGR, uchar, row_number, col_number * 3 + 2);
Really CV_IMAGE_ELEM isn't really worth the effort, you might as well just use frame_BGR.ptr(row) to get a pointer to the start of the row and then increment the pointer to give you B,G,R along the row.

Resources