Your calculations are correct, but it is strongly recommended that you do not use the atan(y/x) definition because this calculation does not take into account the quadrant in which the gradient angle is located. Running atan(y/x) with your components will falsely report that the angle will be -45 degrees if that is not true. Instead, use atan2 .
Now the internal elements of imgradient quite simple. I would like to point out that the angle reported by imgradient suggests that the y coordinate increases from bottom to top. In addition, imgradient should indicate an orientation angle indicating the highest rate of change. In the case of images, this indicates that we are moving from dark pixels to light pixels.
The imgradientxy call is called imgradientxy and the fspecial('sobel') call is called if you specify the sobel flag on imgradient . In fact, this part of imgradientxy is something that 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
Please note that fspecial output is negative , as well as the comment provided on this line. This is to ensure that the mask for detecting horizontal edges (i.e. Gy ) is y-down (as is widely known in computer graphics). In particular, the origin of the image is in the upper left corner, and not in the lower left corner.
This is an illustrated view of how the coordinate system is laid out in y -down:

Source: Wikipedia - Rotation Matrix
Thus, when finding the orientation, there is an additional requirement that the gradient orientation angle is relative to the y-up coordinate system, which we used to. Therefore, when you find the gradient orientation angle, you must negate the y coordinate before calculating the angle, so that there is an angle instead regarding a standard agreement.
The determination of the desired gradient is a conventional y coordinate system, increasing from bottom to top. Negation is required, and in fact, if you study the source code for imgradient , this is exactly what is done on line 127 of the code (version R2015a):
Gdir = atan2(-Gy,Gx)*180/pi; %
Perhaps you are asking yourself why it is necessary to cancel the mask and again cancel the y coordinate after searching for the orientation. The reason is that a modified mask is necessary to correctly capture the gradient value, and therefore we discard the mask once and find the gradient value, and then deny the y coordinate so that we can find the angle relative to the usual coordinate system.
In your case, given that Gx = 765 and Gy = -765 , substituting these values ββin the above equation gives:
>> Gy = 765; >> Gx = -765; >> Gdir = atan2(-Gy,Gx)*180/pi Gdir = -135
This makes sense because the direction of the gradient corresponds to the direction of the highest rate of change. -135 degrees means we are pointing southwest, which makes sense when we progress from dark pixels to light pixels.
Now, if you refer to the third imgradient image, the angles indicated by imgradient are really correct. Just draw a line from the dark region to the region of light and see what angle it makes with the x axis, where it is aligned with columns growing to the right. The first angle of +90 degrees makes sense when we move from bottom to top to keep track of the dark area and light. This is a similar situation with the situation when the image is reversed. The third situation is what we saw earlier, and the fourth situation is just the third situation, rotated 180 degrees, and therefore the natural angle of orientation from dark to light is now +45 degrees, and not before -135 degrees.