1

I am using matplotlib (unsure as to the version) on python v2.7 to produce an image containing circles for use with an OOF2 analysis. The circles need to have pixels composed entirely of the same RGB values (#000000), however when the circles are generated, there is a ring of "greys" around the edge. coll_intra = matplotlib.collections.PatchCollection(circle_intra, facecolors='black', edgecolors='black')

Changing edgecolors between 'black' and 'none' has an effect, but does not set the values to be absolutely equal.
Circles with rings of "grey" around them:
Circles with rings of "grey" around them.

Is there a way to adjust this in my script, or do I need to brute-force it in another program? (e.g. MSPaint).

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
PBH
  • 11
  • 1
  • Maybe I'm missing something but I don't see any grey rings in your image. Also are these "artefacts" produced on the live plot or in the saved image? This seems a lot like the effect of a smoothness operation when "changing" images (rescale, convert, etc.). Also check if your screen is not using some kind of special filter (I'm just saying this because I really do not see any grey rings, its all black and white). – armatita Feb 27 '17 at 09:37

1 Answers1

0

Some grey colors can be present in the picture due to antialiasing.
One has to distinguish between the antialiasing that is performed by matplotlib and the one that may be present in the image viewer (e.g. the browser).

Concerning matplotlib, there is the option to turn antialiasing off by setting antialiased = False. Most artists and collections do have this option. So in this case

PatchCollection(...,antialiased=False)

would do the trick.

To observe the difference consider the following script. Setting antialiased to True (which is the default) outputs 121 different grey shades in the picture, while setting it to False leaves us with only 2 (black and white).

antialiased=True:
enter image description here
antialiased=False:
enter image description here

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
from matplotlib.collections import PatchCollection

antialiased=False

N = 3
x = [1,2];y=[1,1]
radii = [0.5,.4]
patches = []
for x1, y1, r in zip(x, y, radii):
    patches.append(Circle((x1, y1), r))

coll_intra = PatchCollection(patches, facecolors='black', edgecolors='black',antialiased=antialiased)

fig, ax = plt.subplots(figsize=(2,1))
ax.set_aspect("equal")
ax.axis("off")
ax.set_xlim([0,3])
ax.set_ylim([0,2])
ax.add_collection(coll_intra)


#count the number of different colors
#https://stackoverflow.com/questions/7821518/matplotlib-save-plot-to-numpy-array
#https://stackoverflow.com/questions/40433211/how-can-i-get-the-pixel-colors-in-matplotlib
fig.canvas.draw()
data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
data = data.reshape((int(len(data)/3), 3))
data = np.vstack({tuple(row) for row in data})

print len(data) # prints 121 for antialiased=True
                    #          2 for antialiased=False

plt.show()

(The method for counting the colors is adapted from this and this question.)

Community
  • 1
  • 1
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Thank you very much, this solved my problem exactly. – PBH Feb 28 '17 at 02:15
  • Good to hear that. If this answers your question, consider [accepting](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) and upvoting it, otherwise feel free to refine your question. – ImportanceOfBeingErnest Feb 28 '17 at 06:51