I am trying to learn how to animate dots and update their x and y positions from frame to frame. I have found a tutorial online, and I am really struggling with the formulas that are used in dx and dy:
dots.speed = 3; %degrees/second
dots.duration = 5; %seconds
dots.direction_deg = 30; %degrees (clockwise from straight up)
dots.direction_rad = dots.direction_deg * pi /180 %direction converted to radians
% Calculate the distance travelled by a dot (in degrees), which is the speed (degrees/second) divided by the frame rate (frames/second).
dx = dots.speed*sin(dots.direction_rad)/display.frameRate;
dy = -dots.speed*cos(dots.direction_rad)/display.frameRate;
With my knowledge in trigonometry, I end up with these formulas for dx and dy:
Cos(angle) = Adjacent/Hypotenuse --> cos(dots.direction_rad) = 1/dx (1 is the distance from the origin to a point on the circle,which is equal to 1 radian). --> dx = 1/cos(dots.direction_rad) --> the distance is then equal to :
dots.speed*1/cos(dots.direction_rad)*display.frameRate
Sin(angle) = Opposite/Hypotenuse --> sin(dots.direction_rad) = dy/1 --> the distance is then equal to :
dots.speed * sin(dots.direction_rad) / display.frameRate.
My formulas are not giving the expected result. So what I am doing wrong. I don't seem to understand how the dx and dy were computed in the tutorial. Please help! thanks
Related
I have been struggeling with this quiz question. This was part of FSG 2022 registration quiz and I can't figure out how to solve it
At first I thought that I can use extrinsic and intrinsic parameters to calculate 3D coordinates using equations described by Mathworks or in this article. Later I realized that the distance to the object is provided in camera frame, which means that this could be treat as a depth camera and convert depth info into 3d space as described in medium.com article
this article is using formula show below to calculate x and y coordinates and is very similar to this question, yet I can't get the correct solution.
One of my Matlab scripts attempting to solve it:
rot = eul2rotm(deg2rad([102 0 90]));
trans = [500 160 1140]' / 1000; % mm to m
t = [rot trans];
u = 795; % here was typo as pointed out by solstad.
v = 467;
cx = 636;
cy = 548;
fx = 241;
fy = 238;
z = 2100 / 1000 % mm to m
tmp_x = (u - cx) * z / fx;
tmp_y = (v - cy) * z / fy;
% attempt 1
tmp_cords = [tmp_x; tmp_y; z; 1]
linsolve(t', tmp_cords)'
% result is: 1.8913 1.8319 -0.4292
% attempt 2
tmp_cords = [tmp_x; tmp_y; z]
rot * tmp_cords + trans
% result is: 2.2661 1.9518 0.4253
If possible I would like to see the calculation process not any kind of a python code.
Correct answer is under the image.
Correct solution provided by the organisers were 2.030, 1.272, 0.228 m
The task states that the object's euclidean (straight-line) distance is 2.1 m. That doesn't mean its distance along z is 2.1 m. Those two only coincide if there is no x or y component in the object's translation to the camera frame.
The z component of the object's translation will be less than 2.1 meters.
You need to take a ray/vector for the screen space coordinates (normalized) and multiply that by the euclidean distance.
v_x = (u - cx) / fx;
v_y = (v - cy) / fy;
v_z = 1;
v = [v_x; v_y; v_z];
dist = 2.1;
tmp = v / norm(v) * dist;
The rotation may be an issue. Roll happens around X, then pitch happens around Y, and then yaw happens around Z. These operations are applied in that order, i.e. inner to outer.
R_Z * R_Y * R_X * v
My rotation matrix is
[[ 0. 0.20791 0.97815]
[ 1. 0. 0. ]
[ 0. 0.97815 -0.20791]]
That camera, taking the usual (X right, Y down, Z far) frame, would be looking, upside down, out the windshield, and slightly down.
Make sure that eul2rotm() does the right thing (specify axis order as 'XYZ') or that you use something else.
You can use rotvec2mat3d() to build individual rotation matrices from an axis-angle encoding.
Perhaps also review different MATLAB conventions regarding matrix multiplication: https://www.mathworks.com/help/images/migrate-geometric-transformations-to-premultiply-convention.html
I used Python and scipy.spatial.transform.Rotation.from_euler('xyz', [R_roll, R_pitch, R_yaw], degrees=True).as_matrix() to arrive at the sample solution.
Properly, the task should have specified a frame conversion step between vehicle and camera because the differing views are quite confusing, with a car having +X being forward and a camera having +Z being forward...
In addition to Christoph Rackwitz answer, which is correct and should get all the credited, here is a working Matlab script:
rot = eul2rotm(deg2rad([90 0 102]));
trans = [500 160 1140]' / 1000; % mm to m
u = 795;
v = 467;
cx = 636;
cy = 548;
fx = 241;
fy = 238;
v_x = (u - cx) / fx;
v_y = (v - cy) / fy;
v_z = 1;
v = [v_x; v_y; v_z];
dist = 2.1;
tmp = v / norm(v) * dist;
rot * tmp + trans
I’m searching for a method that returns a CGPoint and Angle for each of n items around a rounded rect / squircle (I’m aware those shapes are different but suspect they don’t make a relevant visual difference in my case. Therefore I’m searching for the easiest solution).
Something like this:
func getCoordinates(of numberOfPoints: Int, in roundedRect: CGRect, with cornerRadius: CGFloat) -> [(CGPoint, Angle)] {
// ... NO IDEA HOW TO COMPUTE THIS
}
My ultimate goal is to draw something like this (points distributed with equal angles):
Unfortunately my math skills are not sufficient.
Pseudocode. Used center as cx, cy, w and h as half-width and half-height, r as corner radius.
Calculate angle in side for-loop, add phase to start from needed direction (0 from OX axis, Pi/2 from OY axis)
for (i = 0..n-1):
angle = i * 2 * math.pi / n + phase
Get unit vector components for this direction and absolute values
dx = cos(angle)
dy = sin(angle)
ax = abs(dx)
ay = abs(dy)
Find vertical or horizontal for this direction and calculate point relative to center (we work in the first quadrant at this moment):
if ax * h > ay * w:
x = w
y = w * ay / ax
else:
y = h
x = ax * h / ay
Now we have to correct result if point is in rounded corner:
if (x > w - r) and (y > h - r):
recalculate x and y as below
Here we have to find intersection of the ray with circle arc.
Circle equation
(x - (w-r))^2 + (y - (h-r))^2 = r^2
(x - wr)^2 + (y - hr)^2 = r^2 //wr = w - r, hr = h - r
Ray equation (t is parameter)
x = ax * t
y = ay * t
Substitute in circle eq:
(ax*t - wr)^2 + (ay*t - hr)^2 = r^2
ax^2*t^2 - 2*ax*t*wr + wr^2 + ay^2*t^2 -2*ay*t*hr + hr^2 -r^2 = 0
t^2*(ax^2+ay^2) + t*(-2*ax*wr - 2*ay*hr) + (wr^2 +hr^2 - r^2) = 0
t^2* a + t* b + c = 0
Solve this quadratic equation for unknown t, get larger root, and find intersection point substituting t into ray equation.
Now we want to put result into correct quadrant:
if dx < 0:
x = -x
if dy < 0:
y = -y
and shift them by center coordinates
dx += cx
dy += cy
That's all.
I have a video stream coming from a 180 degree fisheye camera. I want to do some image-processing to convert the fisheye view into a normal view.
After some research and lots of read articles I found this paper.
They describe an algorithm (and some formulas) to solve this problem.
I used tried to implement this method in a Matlab. Unfortunately it doesn't work, and I failed to make it work. The "corrected" image looks exactly like the original photograph and there's no any removal of distortion and secondly I am just receiving top left side of the image, not the complete image but changing the value of 'K' to 1.9 gives mw the whole image, but its exactly the same image.
Input image:
Result:
When the value of K is 1.15 as mentioned in the article
When the value of K is 1.9
Here is my code:
image = imread('image2.png');
[Cx, Cy, channel] = size(image);
k = 1.5;
f = (Cx * Cy)/3;
opw = fix(f * tan(asin(sin(atan((Cx/2)/f)) * k)));
oph = fix(f * tan(asin(sin(atan((Cy/2)/f)) * k)));
image_new = zeros(opw, oph,channel);
for i = 1: opw
for j = 1: oph
[theta,rho] = cart2pol(i,j);
R = f * tan(asin(sin(atan(rho/f)) * k));
r = f * tan(asin(sin(atan(R/f))/k));
X = ceil(r * cos(theta));
Y = ceil(r * sin(theta));
for k = 1: 3
image_new(i,j,k) = image(X,Y,k);
end
end
end
image_new = uint8(image_new);
warning('off', 'Images:initSize:adjustingMag');
imshow(image_new);
This is what solved my problem.
input:
strength as floating point >= 0. 0 = no change, high numbers equal stronger correction.
zoom as floating point >= 1. (1 = no change in zoom)
algorithm:
set halfWidth = imageWidth / 2
set halfHeight = imageHeight / 2
if strength = 0 then strength = 0.00001
set correctionRadius = squareroot(imageWidth ^ 2 + imageHeight ^ 2) / strength
for each pixel (x,y) in destinationImage
set newX = x - halfWidth
set newY = y - halfHeight
set distance = squareroot(newX ^ 2 + newY ^ 2)
set r = distance / correctionRadius
if r = 0 then
set theta = 1
else
set theta = arctangent(r) / r
set sourceX = halfWidth + theta * newX * zoom
set sourceY = halfHeight + theta * newY * zoom
set color of pixel (x, y) to color of source image pixel at (sourceX, sourceY)
I have tried several different solutions but no luck so far.
- (CGPoint)contractLineTemp:(CGPoint)point :(CGPoint)circle :(float)circleRadius {
CGFloat x,y;
x = point.x - circle.x;
y = point.y - circle.y;
CGFloat theta = atan2(x, y);
CGPoint newPoint;
newPoint.x = circle.x + circleRadius * sin(theta);
newPoint.y = circle.y + circleRadius * cos(theta);
return newPoint;
}
- (CGPoint)contractLineTemp:(CGPoint)startPoint :(CGPoint)endPoint :(float)scaleBy {
float dx = endPoint.x - startPoint.x;
float dy = endPoint.y - startPoint.y;
float scale = scaleBy * Q_rsqrt(dx * dx + dy * dy);
return CGPointMake (endPoint.x - dx * scale, endPoint.y - dy * scale);
}
Both of these solutions kind of work. If I draw the line to the center of the circle you can see that it intersects the circle exactly where it should.
http://www.freeimagehosting.net/le5pi
If I use either of the solutions above and draw to the circumference of the circle depending on the angle it is no longer going towards the center of the circle. In the second image the line should be in the middle of the right edge of the circle and going straight right.
http://www.freeimagehosting.net/53ovs
http://www.freeimagehosting.net/sb3b2
Sorry for the links. I am to new to currently post images.
Thanks for you help.
It's easier to treat this as a vector problem. Your second approach is close, but you don't correctly scale the vector between the two points. It's easier to work with a normalized vector in this case, although you have to assume that the distance between the two points on the line is non-zero.
Given:
double x0 = CIRC_X0; /* x-coord of center of circle */
double y0 = CIRC_Y0; /* y-coord of center of circle */
double x1 = LINE_X1; /* x-coord of other point on the line */
double y1 = LINE_Y1; /* y-coord of other point on the line */
Then the vector between the two points is (vx,vy):
double vx = x1 - x0;
double vy = y1 - y0;
It's easier to work with a unit vector, which we can get by normalizing (vx,vy):
double vmag = sqrt(vx*vx + vy*vy);
vx /= vmag; /* Assumption is vmag > 0 */
vy /= vmag;
Now, any point along the line can be described as:
x0 + dist * vx
y0 + dist * vy
where dist is the distance from the center. The intersection of the circle and the line must be a distance of CIRC_RADIUS from the center, so:
double x_intersect = x0 + CIRC_RADIUS * vx;
double y_intersect = y0 + CIRC_RADIUS * vy;
I think that there may be a convention conflict on what theta, x and y are. The atan2 function yields values in the range -pi..pi, by taking the convention of theta as the angle growing from the X axis towards Y. However you are considering theta as the angle from Y to X.
Try changing the code:
CGFloat theta = atan2(y, x);
CGPoint newPoint;
newPoint.x = circle.x + circleRadius * cos(theta);
newPoint.y = circle.y + circleRadius * sin(theta);
Although your formulae are consistent within a coordinate system, it may have conflict with the screen/display device coordinate system.
As I wanted to animate an image in projectile motion,
My code is as follows, but it did not reach the target and give projectile animation, any help please?
-(void)timeLine
{
dTime += 0.1;
.................
double s_x = inVel * cos(angle1) ; // the X speed
double s_y = inVel * sin(angle1) ; // the Y speed
NSLog(#"sx = %i",s_x);
NSLog(#"sy = %i",s_y);
x = oX + (s_x * dTime);
y = oY + ( ( s_y * dTime) - (0.5 * 9.8 * dTime * dTime));
NSLog(#"x = %i",x);
NSLog(#"y = %i",y);
imageViewForAnimation.x += x;
imageViewForAnimation.y -= y;
}
imageViewForAnimation.x += x;
imageViewForAnimation.y -= y;
These lines don't seem right to me. You are calculating the actual x and y each time, not the difference moved since the last time. I'm also uncertain why one was being added and one was being subtracted, but that's beside the point. Basically, try changing the lines to
imageViewForAnimation.x = x;
imageViewForAnimation.y = y;
Also, you're doing some calculations over and over which only need to be done once. v_x == s_x (or it should within floating point error) as well as v_y == s_y. You only need to calculate v_x and V_y once beforehand rather than calculating them every time you update the coordinates.