I am new to metal. I want to draw a semi circle. Any ideas or suggestions to draw a semi circle. I tried using tesselation
float u = patch_coord.x;
float v = patch_coord.y;
float w = patch_coord.z;
float x = u * patchIn.control_points[0].position.x + v * patchIn.control_points[1].position.x + w * patchIn.control_points[2].position.x;
float y = u * patchIn.control_points[0].position.y + v * patchIn.control_points[1].position.y + w * patchIn.control_points[2].position.y;
float2 tangent = normalize(float2(x, y)) / 25;
When I normalize always it is in the middle of the screen. I want to draw circle in my finger touch.
Related
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
I have a point and an angle in OpenCV, how can I draw that using those parameters and not using 2 points?
Thanks so much!
Just use the equation
x2 = x1 + length * cos(θ)
y2 = y1 + length * sin(θ)
and θ should be in radians
θ = angle * 3.14 / 180.0
In OpenCV you can rewrite the above equation like
int angle = 45;
int length = 150;
Point P1(50,50);
Point P2;
P2.x = (int)round(P1.x + length * cos(angle * CV_PI / 180.0));
P2.y = (int)round(P1.y + length * sin(angle * CV_PI / 180.0));
Done!
I need to rotate a single point expressed in cartesian XYZ coordinates about the Z axis. The following 2 attempts are not working properly - I believe the first one is more correct..
I tried to rotate the points using the math on this website: http://farside.ph.utexas.edu/teaching/336k/newton/node153.html
// Rotate the XYZ coordinate for the pin image
if ( [satName isEqualToString:#"pin"] ) {
double x = xyz.x;
double y = xyz.y;
double radians = self.timeSinceOpenGlStarted;
x = x * cos(radians) + y * sin(radians);
y = -x * sin(radians) + y * cos(radians);
xyz.x = x;
xyz.z = y;
}
I also tried this function by extracting the points after GLKMatrix4Rotate:
// This function rotates XYZ a certain of radians about the origin and gives back XYZ
- (GLKVector4)rotateXYZCoordinates:(XYZ*)coords {
// Get the current modelview matrix
GLKMatrix4 currMat = self.effect.transform.modelviewMatrix;
// Print the coords before
NSLog(#"Before: %f %f %f",coords->x,coords->y,coords->z);
NSLog(#"Rotation Before: %f %f %f",currMat.m00,currMat.m10,currMat.m20);
// Construct the rows in the new matrix
float d = sqrt( pow(currMat.m00,2) + pow(currMat.m10,2) + pow(currMat.m20,2) );
GLKVector4 columnToInsert0 = GLKVector4Make(d, 0, 0, coords->x);
GLKVector4 columnToInsert1 = GLKVector4Make(0, d, 0, coords->y);
GLKVector4 columnToInsert2 = GLKVector4Make(0, 0, d, coords->z);
GLKVector4 columnToInsert3 = GLKVector4Make(0, 0, 0, 1);
// Build the new Matrix
GLKMatrix4 noTranslationInfo = GLKMatrix4SetRow(currMat, 0, columnToInsert0);
noTranslationInfo = GLKMatrix4SetRow(noTranslationInfo, 1, columnToInsert1);
noTranslationInfo = GLKMatrix4SetRow(noTranslationInfo, 2, columnToInsert2);
noTranslationInfo = GLKMatrix4SetRow(noTranslationInfo, 3, columnToInsert3);
// Throw the world translation coordinates in the matrix
noTranslationInfo.m30 = ( noTranslationInfo.m30 );
noTranslationInfo.m31 = ( noTranslationInfo.m31 );
noTranslationInfo.m32 = ( noTranslationInfo.m32 );
// Now rotate the matrix so many angles
noTranslationInfo = GLKMatrix4Rotate(noTranslationInfo, self.timeSinceOpenGlStarted, 0, 0, 1);
// Latch the output
coords->x = noTranslationInfo.m30;
coords->y = noTranslationInfo.m31;
coords->z = noTranslationInfo.m32;
// Print the coords After
NSLog(#"AFter: %f %f %f",coords->x,coords->y,coords->z);
NSLog(#"Rotation After: %f %f %f",noTranslationInfo.m00,noTranslationInfo.m10,noTranslationInfo.m20);
}
I have a globe spinning along the Z axis and a billboarded sprite specified at a specific spherical coordinate ( representing a lat/lon location ) and need the ability to have the point rotate along with the earth or not.
What am I doing wrong? How do I calculate a new X and Y coordinate ( Z is constant ) to rotate an XYZ point around the Z axis when I know the number of radians I want to rotate? Thanks!
UPDATE: Now I've tried this:
// Rotate the XYZ coordinate for the pin image
/* http://www.blitzbasic.com/Community/posts.php?topic=70536
;rotate offset around Z axis
newx# = x# * Cos#(zr#) - y# * Sin#(zr#)
newy# = x# * Sin#(zr#) + y# * Cos#(zr#)
x# = newx#
y# = newy#
;rotate offset around X axis
newy# = y# * Cos#(xr#) - z# * Sin#(xr#)
newz# = y# * Sin#(xr#) + z# * Cos#(xr#)
y# = newy#
z# = newz#
;rotate offset around Y axis
newx# = z# * Sin#(-yr#) + x# * Cos#(-yr#)
newz# = z# * Cos#(-yr#) - x# * Sin#(-yr#)
x# = newx#
z# = newz#
*/
if ( [satName isEqualToString:#"pin"] && self.shouldAnimate == YES ) {
//NSLog(#"ONE %f %f %f %f",xyz.x,xyz.y,xyz.z,sqrt(pow(xyz.x, 2)+pow(xyz.y,2)+pow(xyz.z,2)));
double x = xyz.x;
double y = xyz.y;
double z = xyz.z;
NSLog(#"%f",self.timeSinceOpenGlStarted); // Values like: 32521.473728
double zr = self.timeSinceOpenGlStarted;
double yr = 0.0f;
double xr = 0.0f;
// Rotations must be in this order: Z then X then Y
// Rotate around Z
x = x * cos(zr) - y * sin(zr);
y = x * sin(zr) + y * cos(zr);
// Rotate around X
y = y * cos(xr) - z * sin(xr);
z = y * sin(xr) + z * cos(xr);
// Rotate around Y
x = z * sin(-yr) + x * cos(-yr);
z = z * cos(-yr) + x * sin(-yr);
// Get the coordinates back
xyz.x = x;
xyz.y = y;
xyz.z = z;
//NSLog(#"TWO %f %f %f %f",xyz.x,xyz.y,xyz.z,sqrt(pow(xyz.x, 2)+pow(xyz.y,2)+pow(xyz.z,2)));
}
The problem is that my image dances around the lat/lon it should be at - it almost does a figure 8.
I either don't understand what you want to achieve or these methods of yours are a bit strange. If you need to rotate a single point around centre (0,0,0) around Z axis (on the XY plane) then you should use something like this:
float x, y;
float currentAngle;
float radius = sqrt(x*x + y*y);
x = radius*cos(currentAngle);
y = radius*sin(currentAngle);
To make it even easier you can simply use radius (which should be constant in your case) and the angle in radians. In this case you only need last 2 lines of this snippet.
It looks like you are adding each frame to your angle. You can compute an "delta angle" just the angle to rotate from the previous frame, or to use the angle as it is now but apply the rotation to the initial orientation, not to last frame's result.
I have an image, and I place a rectangle on the image. Then I rotate the image. How do I get the center of the rectangle on the rotated image?
Or can I rotate a rectangle somehow to put on rotated image? I think in this case rotation must be done along same point with point used to rotate image.
This is the image with a rectangle placed on it.
This is the rotated image.
Here is the code I use to rotate my image:
cv::Mat frame, frameRotated;
frame = cv::imread("lena.png");
cv::Rect rect(225,250,150,150);
cv::rectangle(frame, rect, cv::Scalar(0,0,255),2);
int theta = 30;
double radians = theta * PI / 180.0;
double sin = abs(std::sin(radians));
double cos = abs(std::cos(radians));
int newWidth = (int) (frame.cols * cos + frame.rows * sin);
int newHeight = (int) (frame.cols * sin + frame.rows * cos);
cv::Mat targetMat(cv::Size(newWidth, newHeight), frame.type());
int offsetX = (newWidth - frame.cols) / 2;
int offsetY = (newHeight - frame.rows) / 2;
frame.copyTo(targetMat.rowRange(offsetY, offsetY + frame.rows).colRange(offsetX, offsetX + frame.cols));
cv::Point2f src_center(targetMat.cols/2.0F, targetMat.rows/2.0F);
cv::Mat rot_mat = cv::getRotationMatrix2D(src_center, theta, 1.0);
cv::warpAffine(targetMat, frameRotated, rot_mat, targetMat.size());
imshow("frame", frame);
imshow("rotated frame", frameRotated);
EDIT
Suppose I have a point in the rotated image, how do I get corresponding point in the original image using rotation matrix?
You only need to use rot_mat to transform the original center of the rect. I tested the below and it works:
cv::Rect r(250, 350, 20, 30);
cv::Point2d c(r.x + r.width / 2, r.y + r.height / 2);
// c is center of rect
// get c's location in targetMat when frame is copied
c.x += offsetX;
c.y += offsetY;
int theta = 30;
double radians = theta * M_PI / 180.0;
cv::Point2d src_center(targetMat.cols/2.0F, targetMat.rows/2.0F);
cv::Mat rot_mat = cv::getRotationMatrix2D(src_center, theta, 1.0);
// now transform point using rot_mat
double *x = rot_mat.ptr<double>(0);
double *y = rot_mat.ptr<double>(1);
Point2d dst(x[0] * c.x + x[1] * c.y + x[2],
y[0] * c.x + y[1] * c.y + y[2]);
// dst is center of transformed rect
EDIT
To transform a point from the rotated image you just need to reverse the process:
// undo translation
Point2d dst1(dst.x - x[2], dst.y - y[2]);
// undo rotation
Point2d dst2(x[0] * dst1.x - x[1] * dst1.y, -y[0] * dst1.x + y[1] * dst1.y);
// undo shift
Point2d in_unrotated_image(dst2.x - offsetX, dst2.y - offsetY);
You can translate any point in your source Mat to rotated Mat by multiplying with the Rotation matrix.
If you need to translate X,Y and given T=1, you can do this by Mat multiplication
| cosθ sinθ Tx | | X | | _X |
| | * | Y | = | |
| -sinθ cosθ Ty | | 1 | | _Y |
where Tx and Ty is the translation along the x and y see OpenCV Doc.
Suppose you need to find the centre (cent_x,cent_y) of source Mat in rotated Mat
Mat rot_mat = getRotationMatrix2D(src_center, theta, 1.0); //Find the rotation matrix
Mat co_Ordinate = (Mat_<double>(3,1) << cent_x,cent_y,1); //Create 3x1 matrix with input co-ordinates.
Mat rst=rot_mat*co_Ordinate; // Multiply rotation matrix with input co-ordinate matrix
trans_x=(int)rst.at<double>(0,0); //First row of result will be x
trans_y=(int)rst.at<double>(1,0); //Second row of result will be y.
Hopes these helpful....
I've solved the problem in second question.
I used the same code provided in the accepted answer and create rotation matrix with minus theta.
I better explain my problem with an Image
I have a contour and a line which is passing through that contour.
At the intersection point of contour and line I want to draw a perpendicular line at the intersection point of a line and contour up to a particular distance.
I know the intersection point as well as slope of the line.
For reference I am attaching this Image.
If the blue line in your picture goes from point A to point B, and you want to draw the red line at point B, you can do the following:
Get the direction vector going from A to B. This would be:
v.x = B.x - A.x; v.y = B.y - A.y;
Normalize the vector:
mag = sqrt (v.x*v.x + v.y*v.y); v.x = v.x / mag; v.y = v.y / mag;
Rotate the vector 90 degrees by swapping x and y, and inverting one of them. Note about the rotation direction: In OpenCV and image processing in general x and y axis on the image are not oriented in the Euclidian way, in particular the y axis points down and not up. In Euclidian, inverting the final x (initial y) would rotate counterclockwise (standard for euclidean), and inverting y would rotate clockwise. In OpenCV it's the opposite. So, for example to get clockwise rotation in OpenCV: temp = v.x; v.x = -v.y; v.y = temp;
Create a new line at B pointing in the direction of v:
C.x = B.x + v.x * length; C.y = B.y + v.y * length;
(Note that you can make it extend in both directions by creating a point D in the opposite direction by simply negating length.)
This is my version of the function :
def getPerpCoord(aX, aY, bX, bY, length):
vX = bX-aX
vY = bY-aY
#print(str(vX)+" "+str(vY))
if(vX == 0 or vY == 0):
return 0, 0, 0, 0
mag = math.sqrt(vX*vX + vY*vY)
vX = vX / mag
vY = vY / mag
temp = vX
vX = 0-vY
vY = temp
cX = bX + vX * length
cY = bY + vY * length
dX = bX - vX * length
dY = bY - vY * length
return int(cX), int(cY), int(dX), int(dY)