Reputation: 239
So i noticed for me and a few of my colleagues that when we display a binary array using matplotlib.pyplot's imshow function the edges of the displayed image seems altered. For a while i thought it was just a visual artifact, but ran into further trouble with it today.
By the way i am running with matplotlib: 3.2.2 and numpy: 1.19.1
If i create a small binary array and plot it it you can see a small "halo" to the binary box in the image. It is not very obvious but it is there:
import matplotlib.pyplot as plt
import numpy as np
img=np.zeros((100,100))
img[25:60,25:60]=50
plt.imshow(img)
It will become more apparent if i change the cmap for the plot.
my_cmap = plt.cm.get_cmap('prism')
my_cmap.set_under('black')
plt.imshow(img,cmap=my_cmap, vmin=1)
The displayed array should only have 0's as background and 1's in the box, but the box is displayed as a green box with a red/yellow border.
With previous versions of pyplot i have not had this issue and it does become a problem when i do object detection and i want to display them and my other wise binary objects end up like this:
I hope you can help me with this
Upvotes: 0
Views: 1350
Reputation: 80339
imshow
doesn't know about your data being discrete or even binary. Default it adds some interpolation. You can suppress the smooth interpolation using imshow(...., interpolation='none')
(or interpolation='nearest'
).
Note that the default mode is 'antialiased'
for which the effect is different depending on the number of screen pixels occupied by an image pixel.
See the official matplotlib documentation for more details.
Here is some test code comparing the default and the 'none'
interpolation mode for different image sizes:
from matplotlib import pyplot as plt
import numpy as np
x = np.round(10 + np.random.uniform(-.1, .1, (100, 100)).cumsum(axis=0).cumsum(axis=1))
x[x % 2 == 0] = x.max() + 1
fig, axes = plt.subplots(2, 6, figsize=(14, 5))
for i, axrow in enumerate(axes):
for j, ax in enumerate(axrow):
k = 10 * (j + 5)
ax.imshow(x[-k:, -k:], cmap='Dark2', interpolation=None if i == 0 else 'none')
ax.set_title("size={}\ninterpolation={}".format(k, 'None' if i == 0 else "'none'"))
plt.tight_layout()
plt.show()
Here is another example, using the 'seismic' colormap and only two data values. This colormap has dark blue and red at the extremes and white near the center, which shows the interpolation much more pronunciated:
Upvotes: 2