Closed
Description
Bug report
Bug summary
With imshow(), image interpolation gives wrong results near pixels with values exceeding vmax. A large rectangular region (given by the interpolation kernel size) is filled with color corresponding to maximum value.
Code for reproduction
t = zeros((50, 50))
t[10, 10] = 1
t[10, 20] = 2
imshow(t, vmin=0, vmax=1, interpolation='lanczos')
Actual outcome
Expected outcome
Ok with matplotlib 2.0.0
Matplotlib version
- Operating System: macOS
- Matplotlib Version: 2.0.1, 2.0.2
- Python Version: 2.7
- Jupyter Version (if applicable):
- Other Libraries:
matplotlib installed via conda-forge
Metadata
Metadata
Assignees
Labels
Type
Projects
Relationships
Development
No branches or pull requests
Activity
dstansby commentedon May 16, 2017
Can confirm this on master - the problem bisects to 1a7c4ef
QuLogic commentedon May 16, 2017
Does #8300 help with this then?
tacaswell commentedon May 16, 2017
No, I do not expect #8300 to help with this.
The issue is that Agg does some aggressive clipping (not sure exactly when in the interpolation steps) so I am not sure that the 2.0 case is actually interpolating correctly (ex a value that should have been scaled to 2 in the normalized units is clipped to 1 before it is interpolated).
More generally, poisoning every screen pixel that include out-of-range source pixels seems like the 'right' thing to do.
geggo commentedon May 18, 2017
Hi,
thanks for all responses.
Indeed, changes of commit 1a7c4ef induced the new behaviour, and it seems this was intentionally. I am missing the background why. But from my point of view this very strict handling of over/under values is not a good way: My current use case is displaying real-world grayscale images, to adjust contrast I set vmin/vmax. Some pixel values are outside this range, with the new behaviour they mess up the result, with the old they just saturate - a very natural behaviour.
With some testing and looking at the sources, I could observe that Agg clips values after interpolation, in this sense interpolation is done correctly, only the information about under/over values is lost. To recover this, I am currently playing with an approach to compare the interpolation result of the raw image and one with values scaled by 0.5. If the interpolation results don't match up, there must have been some clipping. Do you think this makes sense?
Or would it be better to modify Agg, such that for float data clipping can be suppressed?
Gregor
tacaswell commentedon May 23, 2017
Doing the interpolation twice is almost certainly too expensive. Comparing where pixels == 1 or 0 in the output plane and are in the mask where they have been poisoned might be a better approach? I am definitely open to changing this (I was thinking much more about nan / inf when I did this before) and it would break some of the degeneracy in over/under regions overlapping.
Another reasonable idea may be to just scale down the input to [.1, .9] so we can do the clipping our selves.
This will still not correctly capture pixels where the interpolation pushes the result value out of range despite everything around it being with-in range (which I think some of the higher-order interpolations can do.
We have a vendored version of the last non-gpl version of Agg which has slightly divereged from upstream. We are not the only project with a vendored-and-changed Agg and it does cause problems (like seg-fault problems) so I am wary of making aggressive changes to Agg it's self, but using different functions from Agg is on the table.
geggo commentedon May 23, 2017
geggo commentedon May 24, 2017
First results, I tried the approach to scale the image values to 0.25-0.75 before interpolation, so clipping for the unscaled image can be detected, for a proper assignment of under/over mask. This needs very few changes
Demonstration of the outcome for different strength of the outliers (1%, 10%, 100%, 1000% of max) with over/under masking based on values after interpolation (new approach):
for comparison result with mpl 2.0.0, where over/under mask relies on interpolating the raw over/under mask:
tacaswell commentedon May 25, 2017
I like it! The oscillations around the strong peak from the higher-order kernels is wild, but I think correct.
Why rescale the values in plane 1, wouldn't it be simpler to just compare them against [.25, .75]?
I also do not understand the 5% margin.
Is the over/under pair in the top-right symetric? It looks like the red one is a bit weaker than the cyan one.
17 remaining items