How to find height and width of a rectangle in OpenCV? - c++

How can I find the width and height of a rectangle drawn with the function cvRectangle with the following parameters?
cvRectangle( input1, cvPoint(200,178), cvPoint(190,110),color ,1, 8 );

You set the parameters, so calculating width and height should be trivial, shouldn't it? width = (200-190) and height = (178-110). But, as #bubble suggests, since you're most likely dealing with pixels, don't forget to add 1, resulting in (200 - 190) + 1 for width and (178 - 110) + 1 for height.
Or do you expect cvRectangle to give you some rectangle "object" you can get these values from? It doesn't.

Related

How to convert a 3D point cloud to a depth image?

For my work I have to convert a point cloud to a grey scale (depth) image meaning that the z coordinate of each XYZ point in the cloud represents a shade of grey. For mapping a Z coordinate from the [z_min, z_max] interval to the [0..255] interval I used the map function of Arduino:
float map(float x, float in_min, float in_max, float out_min, float out_max)
{ return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; }
With that done I need to write the result to an image, the problem being that the clouds that I have can have millions of points so I can't just write them 1 by 1 to an image in order. Let's say that I have 3000x1000 ordered XY points. How would I do if I wanted to write them to a 700x300 pixels image? I hope the question is clear, thanks in advance for answering.
I have managed to find a solution to my problem. It is a fairy long algorithm for stack overflow but bear with me. The idea is write a vector of XY grey scale points as a pgm file.
Step 1: cloud_to_greyscale - function that converts an XYZ Point Cloud into a vector of XY grey scale points and that receives a cloud as a parameter:
for each point pt in cloud
point_xy_greyscale.x <- pt.x
point_xy_greyscale.y <- pt.y
point_xy_greyscale.greyscale <- map(pt.z, z_min, z_max, 0, 255)
greyscale_vector.add(point_xy_greyscale)
loop
return greyscale_vector
Step 2: greyscale_to_image - function that writes the previously returned vector as a greyscale_image, a class that has a width, a height and a _pixels member corresponding to a double dimensional array of unsigned short usually. The function receives the following parameters: a greyscale_vector (to be turned into the image) and an x_epsilon that will help us delimit the x pixel coordinates for our points, knowing that the x point coordinates are floats (and thus not suitable as array indices).
A little background info: I work on something called widop clouds so in my 3D space x is the width, y is the depth and z is the height. Also worth noting is the fact that y is an integer so for my problem, the height of the image is easy to find: it's y_max - y_min. To find the width of the image, follow the algorithm below and if it isn't clear I will answer any questions and I'm open to suggestions.
img_width <- 0; // image width
img_height <- y_max - y_min + 1 // image height
// determining image width
for each point greyscale_xy_point in greyscale_vector
point_x_cell <- (pt.x - x_min) * x_epsilon * 10
if point_x_cell > img_width
img_width <- point_x_cell + 1
loop
// defining and initializing image with the calculated height and width
greyscale_img(img_width, img_height)
// initializing greyscale image points
for y <- 0 to greyscale_img.height
for x <- 0 to greyscale_img.width
greyscale_img[y][x] = 0
loop
loop
// filling image with vector data
for each point point_xy_greyscale in greyscale_vector
image_x = (point_xy_greyscale.x - x_min) * x_epsilon * 10
image_y = point_xy_greyscale.y - y_min
greyscale_image[image_y][image_x] = point_xy_greyscale.greyscale
loop
return greyscale_image
The only thing left to do is to write the image to the file, but that is easy to do, you can just find the format rules in the previous link related to the pgm format. I hope this helps someone.
EDIT_1: I added a picture of the result. It is supposed to be a railway and the reason it's fairly dark is that there are some objects that are tall so ground objects are darker.
depth image of railway

Qt 5.5 draw filled pie

The image below shows the grey pie, I would like to draw this using Qt 5.5
X increases left to right
Y increases top to bottom
I have a start angle and an end angle which represents to the top and bottom of the arc, I am calculating the arc angle using:
double dblArcAngle = fmod(mcfltElevMaxLimit - mcfltElevMinLimit + 180.0, 360.0) - 180.0;
Where:
mcfltElevMaxLimit is 60 and mcfltElevMinLimit is -10
The call to drawPie looks like this:
objOffscrPainter.drawPie(QRect(rctGeom.left() + mcintElevLeftMargin
,rctGeom.top() + mcintElevBottomMargin
,rctGeom.width() - mcintElevLeftMargin
,rctGeom.height() - mcintElevBottomMargin)
,mcfltElevMaxLimit * 16, dblArcAngle * 16);
What I get is a very small polyline about midway up where the pie should be.
(edit), just read in the documentation that both startAngle and spanAngle parameters 2 and 3 should be multiplied by 16, which does produce a pie, not in the correct orientation and not filled to the center but its progress.
(edit 2), more progress, the image below now shows the results I'm getting, the rectangle I'm passing is the outer rectangle and includes the axis, yet for some reason the pie is offset???
What I want to accomplish is the pie tucked into the bottom left aligned with the white axis and filling the image.
It looks like the passed rectangle is used to determine the center point for the pie. If this is correct then the center of the rectangle must be adjusted to be the origin (bottom left) and the size also adjusted to fill the display.
The rectangle in a first parameter of QPainter::drawPie is a bounding box of a circle which contains your arc. So, to draw what you need try something like this:
objOffscrPainter.drawPie(QRect(center.x() - r, center.y() - r, 2 * r, 2 * r)
,16*mcfltElevMaxLimit, 16*dblArcAngle);
(where center is a center of your arc)
It seems that in your case center is a QPoint(0, 0), so you can use this code:
objOffscrPainter.drawPie(-r, -r, 2*r, 2*r, 16*mcfltElevMaxLimit, 16*dblArcAngle);
(we can call it without QRect too, see the documentation)

Draw circles using for-loop Qt c++

I want to draw 7 circles using Qt in C++
I want to use a for loop;
However, I am unable to, I actually wanted to used the width of the window to equally space my circles which is not working out as well. Where am I wrong. I am new to programming. :)
Here is my code:
for (int i = 0; i <= 6;i++)
{
int x = 0;
int y = (width()/6);
x =y+x;
canvas.drawEllipse(x, 40, 20, 20);
}
Okay I was working on it and now I have five circles with this code
int x = 0;
for (int i = 0; i <= 6;i++)
{
x = x+(width()/6);
canvas.drawEllipse(x, 40, 20, 20);
}
But I want the first circle to start at
canvas.drawEllipse(0, 40, 20, 20);
In addition how can I change the color of one circle if I am switching from one page to another. Its an application with about 7 pages and each circle would represent a page so for example if I am on page 1 circle 1 should be green.
I have been told to create a function for this but how do I go about it referencing my pages and the circles. Thanks.
Let's do some math here.
Let Screen_Width be the width of the screen, in pixels.
Let Screen_Height be the height of the screen, in pixels.
The width of an ideal circle is the same as the diameter, or 2 * radius.
However, this is reality, sow we have to account for line widths.
So the actual width of a circle is: Diameter + 2 * Circle_Line_Width;
Also, this being reality and not ideal conditions, we would like spacing between the circles.
Let Spacing be the distance, in pixels between the outer lines of the circles.
Let Circle_Quantity be the number of circles.
So, the total width occupied by the circle is:
Circle_Width = Diameter + 2 * Circle_Line_Width + (Space_Between_Circles / 2);
The space available for a circle (with spacing) is:
Available_Circle_Space = Screen_Width / Circle_Quantity;
Now comes the trick, locating the centers of the circles.
Let's find out the values of the circle properties.
Solving for the diameter:
Diameter = Circle_Width / (2 * Circle_Line_Width + (Space_Between_Circles/2));
Remember, the center of the circle will be the midpoint of the diameter, which is Diameter / 2.
So, the first center point is:
0 /*Left edge ordinate */
+ (Space_Between_Circles/2)
+ Circle_Line_Width
+ (Diameter / 2)
The next center point is at:
Previous_Center_Point
+ (Space_Between_Circles/2)
+ Circle_Line_Width
+ (Diameter / 2)
This should show you how to make a for loop to draw all the circles.
Switch around the two statements in the loop:
int x = 0;
for (int i = 0; i <= 6;i++)
{
canvas.drawEllipse(x, 40, 20, 20); //0 on 1st iteration
x = x+(width()/6); //x = 0 + (width()/6), which will be used on 2nd iteration, etc.
}
To use x as 0 in the first loop, you save adding width()/6 until after you've first used it.

Positioning a widget involving intersection of line and a circle?

Here is the problem I'm trying to solve for my game.
I have this scenario:
I'm trying to solve for the position and size of the green rectangle. The circle is at 50%, 40% of the screen and its radius is proportional to the height of the screen.
The green rectangle must always be 10 pixels away from the bottom. Its left corner must be 10 pixels away also. And as can be seen in the image, the distance from the top right corner until the rectangle touches the circle is 10 pixels also.
Another constraint is that the green rectangle must always be 3 times wider than its height (aspect ratio).
Given these constraints, how can I solve for the position and size of the green rectangle?
Essentially, the Game Window can have a bunch of different aspect ratios so the green rectangle must look good in any of these situations.
I'm not necessarily looking for code but just an idea on how this could be solved.
Thanks
The thing to do in these situations is to describe the constraints mathematically, and see if it simplifies. This is an essential skill for geometric processing.
Let's assume the bottom left corner of the image area is (0,0). That puts the bottom-left corner of the rectangle at (10,10); we'll call the top-right corner (x1,y1). I'll assume you've already calculated where the circle will be since that's pretty straight-forward, we'll call the center (x2,y2) and the radius r.
The first constraint: the rectangle is 3 times wider than it is tall.
x1-10 = 3 * (y1-10) or x1 = 3 * (y1-10) + 10 or x1 = 3*y1 - 20
The second constraint: x1,y1 lies 10 pixels away from the circle. If we describe another circle 10 pixels larger than the first, the point will lie on it.
(x1-x2)^2 + (y1-y2)^2 = (r+10)^2
Substituting for x1:
(3*y1 - 20 - x2)^2 + (y1-y2)^2 = (r+10)^2
This is great, because r, x2, and y2 are known; the only unknown left is y1. Let's see if we can gather all the y1's together.
(3*y1 + (-20 - x2))^2 + (y1-y2)^2 = (r+10)^2
3^2*y1^2 + 2*(3*y1*(-20-x2) + (-20-x2)^2 + y1^2 + 2*y1*-y2 + y2^2 = (r+10)^2
3^2*y1^2 + y1^2 + 6*(-20-x2)*y1 + 2*-y2*y1 + y2^2 = (r+10)^2
(3^2+1)*y1^2 + (-120 - 6*x2 - 2*y2)*y1 + y2^2 = (r+10)^2
At this point it's looking almost like a quadratic equation. One more little tweak:
10 * y1^2 + (-120 - 6*x2 - 2*y2) * y1 + (y2^2 - (r+10)^2) = 0
The final step is to apply the Quadratic Formula.
a*y1^2 + b*y1 + c = 0
a = 10
b = (-120 - 6*x2 - 2*y2)
c = (y2^2 - (r+10)^2)
y1 = (-b +/- sqrt(b^2 - 4*a*c)) / 2*a
There are two possible answers from the quadratic equation, but one of them will put the rectangle on the far side of the circle. It should be easy to eliminate that case.
What you have there is a classic circle-line intersection problem. You know a point on the line - the bottom left corner of the rectangle. And you know the slope of the line (from the aspect ratio). The circle you intersect with can be your red circle shifted left by 10 to give you your 10 pixel gap. The intersection will be the top right corner of the desired rectangle. That should be enough for an idea.

OpenGL - GlVertex relative/absolute position

Imagen I have a list of 2D points (x,y) that describe a 2D terrain in my simple game.
I have then glVertex() to draw all those points in GL_POINTS mode.
Then I have a Ball that also has it's (x,y) coordinates.
I want the ball to have a definite size in relation to everything else (such as the terrain).
How should I set the values of the (x,y) coordinates to draw everything the size I want it?
Having a 600x400 screen.
I am troubled also because glVertex2f(1,1) will draw a primitive point on the upper right corner. So 1 represents to go 100% to the right or top. But the screen is 600x400 so I can't have dimensions of equal length on x and y axis.
Since 0 is 0% (absolute left/bottom) and 1 is 100% (absolute right/top), you just have to find a point in between that will line up with the pixels.
For example. Say your ball is 20x20 pixels. This means that it is 5% of the screen tall and 3.33% of the screen wide. Therefore, the square surrounding your ball would have the following vertices:
void drawBall()
{
glVertex2f(ball.x - (20/600)/2, ball.y - (20/400)/2);
glVertex2f(ball.x - (20/600)/2, ball.y + (20/400)/2);
glVertex2f(ball.x + (20/600)/2, ball.y + (20/400)/2);
glVertex2f(ball.x + (20/600)/2, ball.y - (20/400)/2);
}
See how I'm dividing the width of the ball by the width of the screen to get a floating point value that works with glVertex2f? Also, ball.x and ball.y should be a floating point value between 0 and 1.
I divide these numbers by 2 because I'm assuming that (ball.x, ball.y) is the coordinate of the center of the ball, so half of the addition goes on either side of the center.
You can write your own function that draws the vertices and that takes pixels in arguments:
#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 400
void glVertex_pixels(const double x,const double y){
glVertex2d(x * 2.0 / (double)WINDOW_WIDTH - 1.0, 1.0 - y * 2.0 / (double)WINDOW_HEIGHT);
}
You can also use a macro:
#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 400
#define glVertex_pixels(x,y) glVertex2d((double)(x) * 2.0 / (double)WINDOW_WIDTH - 1.0, 1.0 - (double)(y) * 2.0 / (double)WINDOW_HEIGHT);
No matter which of the above codes you use, the use of this function is simple. For example, the following code draws a vertex 10 pixels from the left side and 20 pixels from the top side:
glVertex_pixels(10,20);