The goal is to rotate an image so that the bounding boxes including the hand instances are all axis aligned. Please see the following examples. The first image is the original one and the second image is the rotated version where the left hand (It's left in the image) is axis aligned and the third image is also a rotated version where the right hand is axis aligned.
Now given four points indicating the hand bounding box, we have to calculate the rotated degree. Let me take the left hand (It's left in the original image) as an example. Assuming the four points are [p1_x, p1_y], [p2_x, p2_y], [p3_x, p3_y], [p4_x, p4_y]. The line formed by[p1_x, p1_y] and [p2_x, p2_y] indicates the wrist and p1, p2, p3, p4 are clockwise. So the yellow line is formed by p1_x, p1_y] and [p4_x, p4_y].
My idea is the calculate the degree between the yellow line and the horizontal axis. For the left hand, the degree is about -10 and for the right hand the degree is about -110.
My problem is how to calculate these degrees?
Useatan2d to calculate the 4-quadrant inverse arctangent. For the line segment joining [p1_x, p1_y] and [p4_x, p4_y], do:
atan2d(p4_y-p1_y,p4_x-p1_x)
Related
As an input of my code, I need to have some positions on my picture: the positions are in pixels and the origin (0,0) is in the CORNER top left of my picture
The problem is that when I run my code which maps the positions on my picture, the origin shifts to the bottom left :
So my question is : how could I also shift my input (positions of my picture1) so that it is relevant with the code process?
Thank you for your help,
Aude
Adding an answer with a bit detail:
In computers, image processing etc it is the norm to have the (0,0) pixel in the top left corner. However, it is understandable that when you have x,y data, you'd want to plot it together with the image. Here some solutions:
imshow(image);
axis xy; % This line sets up the axis in a standard coordinate system
you can revert it with axis ij
Often, this is not enough. As imshow assumes that each pixel is in integer index position, and you may not have that. Maybe your data is in milimeters, or in any other arbitrary units. A solution to that is using imagesc
imagesc(img);
is equivalent to imashow(img);axis xy. Additionally, you can choose arbitrary matrices for pixel locations as imagesc(x,y,img);
Finally, you can flipud your data for plotting, but I suggest you do that inline with the plot, so you dont modify the data itself.
imshow(flipud(img))
With images you reverse the Y axis:
set(ax,'YDir','reverse');
That would depend on your code. Maybe you can do it on-the-fly so you'll get the desired output right away.
If not just flip the output. You could use flipud for that.
https://de.mathworks.com/help/matlab/ref/flipud.html
I am finding the gradient of an image. For now I am simply using a 5 x 5 image. I am more interested in finding the direction of the gradient but I am not getting the results manually on paper as I get them using MATLAB function imgradient. Please refer to the following images to know more about the input images and the Sobel filter that is used here to find the gradient of an image. One of the 3 x 3 sobel operator used here is the one that I get using the function
f1 = fspecial('sobel');
and the other one is obtained by just transposing the f1.
Please note that I am trying to find the direction of only one pixel here that is rounded by red color. Here in the first two cases my result matches with that i obtain using imgradient function but in the third case imgradient gives -135 degree whereas I am getting it to be -45. Please help me find the error.
Also please explain how to interpret the following gradient directions as shown in the follwing image.
Your calculations are correct but it is highly recommended that you don't use the atan(y/x) definition because this calculation is not cognizant of the quadrant that the angle of the gradient resides in. Doing atan(y/x) with your components would falsely report the angle to be -45 degrees when that isn't correct. You should use atan2 instead.
Now the internals of imgradient are quite straight forward. I'd like to point out that the angle reported by imgradient is assuming that the y coordinate is increasing from bottom to top. In addition, imgradient should report the angle of orientation that is pointing to the greatest rate of change. In the case of images, this points in the direction where we progress from dark pixels to light pixels.
First a call to imgradientxy is called and a call to fspecial('sobel') is made if you provide the sobel flag to imgradient. In fact, this portion of imgradientxy is what is important to remember (starting at line 75: MATLAB R2015a):
case 'sobel'
h = -fspecial('sobel'); %// Align mask correctly along the x- and y- axes
Gx = imfilter(I,h','replicate'); %'
if nargout > 1
Gy = imfilter(I,h,'replicate');
end
Notice that the negative of the output of fspecial is performed as well as the comment provided at that line. This is to ensure that the mask to detect horizontal edges (i.e. Gy) is y-down (as it is commonly known in computer graphics). Specifically, the origin of the image is at the top-left corner and not the bottom left.
This is a pictorial representation of how the coordinate system is laid out in y-down:
Source: Wikipedia - Rotation Matrix
As such, when finding the orientation there is an additional requirement to ensure that the angle of the orientation of the gradient is with respect to the y-up coordinate system which is what we're used to. Therefore when you are finding the angle of orientation of the gradient, you need to negate the y coordinate before calculating the angle so that the angle is with respect to the standard convention instead.
Pursuing the definition of the gradient that you seek is the conventional system of the y coordinate increasing from bottom to top. The negation is required and in fact if you examine the source code for imgradient, this is precisely what is being done at line 127 of the code (version R2015a):
Gdir = atan2(-Gy,Gx)*180/pi; %// Radians to degrees
You may be asking yourself why there is a need to negate the mask and again negate the y coordinate after to find the orientation. The reason why is because the modified mask is required to properly capture the magnitude of the gradient and so we negate the mask once and find the gradient magnitude and then we negate the y coordinate so that we can find the angle with respect to the conventional coordinate system.
In your case, given that Gx = 765 and Gy = -765, substituting these quantities into the above equation yields:
>> Gy = 765;
>> Gx = -765;
>> Gdir = atan2(-Gy,Gx)*180/pi
Gdir =
-135
This makes sense because the gradient direction corresponds to the direction towards the greatest rate of change. -135 degrees means that we're pointing to the south west which does make sense as we are progressing from dark pixels to light pixels.
Now if you consult your third example image, the angles reported by imgradient are indeed correct. Simply draw a line from the dark area to the light area and see what angle it makes with the x axis where it is aligned with the columns increasing towards the right. The first angle of +90 degrees makes sense as we are moving from bottom to top to follow the dark area and light. This is a similar situation with the situation where the image is reversed. The third situation is what we have seen before and the fourth situation is simply the third situation rotated by 180 degrees and so naturally the angle of orientation from dark to light is now +45 degrees as opposed to -135 degrees previously.
Area integral invariant is a type of signature used in image processing. Does anyone know the algorithm for the computation of AII?
i.e. I want to calculate the area enclosed by a boundary and the intersected circle...
the boundary is not a curve with a equation but from a arbitrary profile. The image below is just a schematic drawing. The real boundary can be much more complex with the enclosed area in various positions of the boundary, i.e. top, bottom, left side...
The red area. I am using MATLAB and the image is mostly binary ones.
If you know the equation of the circle and the line then its quite easy, if you are doing this in an image.
Select the pixels that are inside the circle (easily done with the equation of the circle). If you need to compute the AII as a ratio, then count the pixels you have.
Separate the pixels above and below the line. You can do this easily if you know the equation of the line, or the value of the line in each column. Go column by column and discard the pixels that are above the value of the line. Count the result.
That's it! If you want the AII without a ratio, then the number of pixels in 2 is the result. If you want it as a ratio, divide the number of pixels of 2 by the number of pixels of 1.
If you only have the image and no equations, you can still select all the pixels you want by giving your algorithm one pixel in the area you want to calculate and then recusivly check all neighbors and add them to you area, if they are white. When you are done, just count the pixels you have. The result is in some sense the are of the region you wanted.
I am doing work on symmetric images where I would like to define a symmetric (polar) coordinate space. Basically for the left image, I want 0 degrees to be defined along the right horizontal axis (as is the default). However, for the right image, I want 0 degrees to be defined along the left horizontal axis.
I know a phase shift of pi would do the trick. However, for comparison purposes, I am trying to keep the range of angles the same, [-pi : pi).
In the above color plot of the rotations in an object, note that they are both defined in the same direction. Ideally I'd like to see the colors of the right object flipped across its vertical axis.
I should note that these angles are calculated by taking the arctan(y/x) of the perimeter coordinates when measured from the centroid. Is there a different trig function that may result in the proper symmetry? I couldn't seem to come up with one while still claiming it was representative of direction.
This is a continuation of this question : Finding Squares in Image
I followed the steps in my answer there : https://dsp.stackexchange.com/a/7526/818, And I got the answer as given below :
But at the end of that answer, I have explained a problem, and that is my question.
Explanation :
I already have the centroids of detected squares from step 1 in the previous link (and those detected squares are marked in mask_image below):
I created a grid image as below ( I know their centroid values also) :
I also found which point in grid image to be mapped to corresponding point in mask_image.
With that information, I applied scipy.interpolate.griddata(), and then OpenCV's cv2.remap() function.
And its result is given below :
As you can see, all the squares except the two at center are clipped. It is like, output contain only the region inside a boundary drawn connecting all the centroids of the mask_image.
Scene becomes more worse below :
The case is more worse when the last square (yellow) or any other square in four corners is not detected in first step. Consider last one is not detected. Then below is the result I get and you can see a slant cut at the bottom (marked with yellow color):
Question :
Why remap function not working beyond the points I have given ? And what should I do to remap it without clipping ?
I thought it would work for the full image even if I give some points, which are not at edges.
Expected Output :
Below is the output I expected at the end of my operation. (Region inside red boundary is what I got actually got now )
Looking for some good suggestions ...
UPDATE :
I also add the code here. Only remapping part code is added. Full code is too big to be added here :
# ideal - the grid image - http://i.stack.imgur.com/3QudG.png
# centroids - list of centroids of the squares in mask_image - http://i.stack.imgur.com/jh6bQ.png
# match_pts - list of centroids of the squares in grid image corresponding to squares in mask_image
# warped - the final image obtained after remap - http://i.stack.imgur.com/O26ZA.png
grid_x,grid_y = np.meshgrid(np.arange(ideal.shape[1]),np.arange(ideal.shape[0]))
dst = np.array(centroids)
src = np.array(match_pts)
grid_z = griddata(dst,src,(grid_x,grid_y),method='cubic')
map_x_32 = grid_z[:,:,0].astype('float32')
map_y_32 = grid_z[:,:,1].astype('float32')
warped = cv2.remap(ideal, map_x_32, map_y_32, cv2.INTER_CUBIC)
Also added the datas like centroids, match_pts etc, so that if someone want to try it out, they can directly use the data instead of finding it from image : gist.github.com/4540887
Step 1: Whatever final binary image you are getting from analyzing in B,G,R,H,S,V plane, in that image do a blob counting algorithm.
Step 2: Find the largest blob on basis of area or contour length. Since your blobs will be mostly parallelogram types so area or contour, any one will do.
Step 3: With the largest blob (since largest blob is the best blob resembling your real world squares) try to find the orientation of the blob...this you can get by a fitting a best fit rectangle OR you can get the corner points...get the slope of the lines joining them (in both horizon and vertical direction).
Step 4: Once you get the two slopes draw two lines running through the axis of the blob. for axis you can average the corner points or you can use the centroid (center of mass)...I would go with average of corner points...
Step 5: Since in each horizontal and vertical direction, spacing is equal (ideally horizontal and vertical spacing are also equal as it comes from your ideal square picture but we will not assume it..) just need to locate the possible centroids of the other parallelograms
BOTTOM LINE: If any one square gets detected perfectly you can make the whole grid. Just keep marking centers at an interval of 2H (H = horizontal width of biggest blob) along the horizontal axis of the biggest blob and at an interval of 2V (V = vertical height of biggest blob) vertically along the vertical axis of the blob.
Some pics to support