image(x,y,A) fails on log axis depending on axis's limits

Hi The question is pretty much self explanatory given the following example
The following code works:
figure
A = rand(200,200,3);
axes('XScale','log','YScale','log')
hold on
image([1e1 1e2],[1e2 1e4],A)
The following code doesn't work:
figure
A = rand(200,200,3);
axes('XScale','log','YScale','log')
hold on
image([1e1 1e2],[1e2 1e5],A)
The only difference between the two codes is the y coordinate of the top corner (1e4 in the first example, 1e5 in the second).
Why does this happen and how can I fix it?

3 Comments

Well, that's certainly interesting. Unfortunately, since image is a built-in function we can't look at the cause for the error. You would be better off raising a bug report with mathworks.
You can get the same problem by changing the YData property of your first image object:
figure
A = rand(200,200,3);
axes('XScale','log','YScale','log')
hold on
im = image([1e1 1e2],[1e2 1e4],A) %OK
im.YData = [100 1e5] %kaboom!
I investigated it a little more and what seams to matter is the ration y(2)/y(1) (or x(2)/x(1) ).
The command works until the ration is smaller than 398.999999999999971578...

Sign in to comment.

 Accepted Answer

From the MATLAB Technical Support:

---------------------------------------------------------------------------------------------------

Hello Luca,

I am writing in reference to your Technical Support Case #03035296 regarding 'image(x,y,A) fails on log axis depending on corner position'.

I apologize for taking some time to respond.

After collaborating with my colleagues, we have found that currently it is a bug at our end. Thank you for reporting this issue. I apologize for any inconvenience this may have caused you.

The issue lies in how an image object is rendered. MATLAB adds a small padding on all sides of the image to better support image visualization in cases where axis scale is linear. However, this padding currently is applied as a percentage of image dimension. Hence, causes the image to overflow in the invalid range of the log scale, namely, for negative values.

One possible workaround is to carefully manage the image "XData" and "YData" to make sure that the padding does not end up on the negative side of the log scale. The padding for "XData" is computed using 1/(2*imageDimInX) * (X2- X1). This should be restricted to be greater than "X1". Similarly for YData.

This padding is then added to "XData" and "YData" before being used for rendering.

Please be assured that the development team have been made aware of the issue and will consider it. They might consider fixing it in future releases of MATLAB.

Please feel free to reply to this mail if you have any other related questions. I will be happy to reopen this case and assist you further.

Sincerely, Niraj Gadakari MathWorks Technical Support Department

---------------------------------------------------------------------------------------------------

More Answers (1)

XData and YData are locations of pixel centers. You have to use the upper and lower values and the resolution to calculate where the lowest edge of the pixel would be. If it would be 0 or negative then the image cannot be displayed on a log plot.

7 Comments

Sorry Walter, but I don't get your answer. From the image doc
image(x,y,C) specifies the image location. Use x and y to specify the locations of the corners corresponding to C(1,1) and C(m,n). To specify both corners, set x and y as two-element vectors.
the lower left corner of the image (the pixel with the lowest coordinates) is therefore at x = 10, y = 100. Both positive.
Al the other pixels will be between x = 10 and x = 1e2 and between 1e2 and 1e5.
All the values should therefore be positive.
Why you think in this example the lowest edge of the pixel to be negative?
"Two-element vector — Use the first element as the location for the center of CData(1,1) and the second element as the location for the center of CData(m,n), where [m,n] = size(CData). Evenly distribute the centers of the remaining CData elements between those two points.
The height of each pixel is determined by the expression:
(YData(2)-YData(1))/(size(CData,1)-1)"
For the case giving you trouble that would be (1e5-1e2)/(200-1) so the pixel centers are 502.010050251256 apart. The edge would be 1e2-(502.010050251256/2) = -151.005025125628
If we do
syms y
solve(eps==1e2-(y-1e2)/199/2)
ans =
89846812566041395001/2251799813685248
>> vpa(ans)
ans =
39899.999999999999911626247239838
which is to say just slightly less than 4E4: an upper bound greater than that will result in the lower edge being below zero for an image with 200 pixels.
The equation you provided is certainly valid for linear axes. However for logarithmic axes it shouldn't be like that.
Consider the output of the following code
figure
axes('XScale','log','YScale','log')
hold on
image([10 100],[10 100],rand(20,20,3))
If we look at the y coordinate of the pixel centres, we see that the distance between the first two rows is equal to 9.272-8.143 = 1.1290 , while the distance between the last two rows is equal to 95.94-84.26 = 11.68 . Both are different from the value provided by your equation that would be (100 - 10)/19 = ~4.74.
What is constant is indeed not the difference, but the difference of the logarithm (indeed log(95.94)-log(84.26) = log(9.272)-log(8.143)).
In other words, the spacing is a logarithmic spacing (as logspace) instead than a linear spacing (as linspace).
I don't know the internal code of image, but this must be done somewhere, since in the example above the pixel height is ( correctly! ) constant in logarithmic scale.
What can be noticed from the above example is that, despite the fact that the pixels are correctly spaced on the logarithmic scale, the two corners does not match the input provided (10,10) and (100,100).
I agree with you, moreover, that what I said is all referred to the pixel's centres. When matlab computes the corner of the pixels starting from their centers, it is possible (i think, but I haven't done the math) that it has a negative value of x or y.
However I think that this should be a situation that MATLAB must be able to handle, as the inputs are all valid!
I correct myself regarding the last point.
The distance between two column is equal to
log(dx) = (log(x(2)) - log((x(1))) / size(A,2);
The left edge of the leftmost column of pixel should be calculated as
log(x_leftcorner) = log(x(1)) - log(dx)/2;
x_leftcorner = 10^(log(x(1)) - log(dx)/2);
that is always positive.
What I had observed in the past was that MATLAB continues to use the linear formula for the purpose of prediction of whether to draw the image or not, but that once it comes to draw the image, it just draws it linearly as if log axes were not in effect. I did not check this out in detail, though.
Years ago I posted,
"When the fixed half pixel outside margin is translated to coordinates in log space, the result can be outside of the current XLim. When that happens, the image is largely clipped out. If you set the XLim manually and then adjust the XData to be close to but not quite at the XLim, the image will occupy most of the plot space, disappearing if the margin would project over the XLim."
At the end of the day, it turned out to be a bug in the image(...) function. See below for the full explanation of the Technical Support Team

Sign in to comment.

Products

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!