26

I have some color plots that I need to be saved in grayscale. Is there an easy way to do this without changing the plotting formats?

2
  • 4
    There were some discussion around that, see convert figure from color to BW/grayscale. Don't know whether the set_gray attribute is available or not in the latest release of matplotlib. Commented May 16, 2011 at 18:29
  • You could use imagemagick afterward: convert -type Grayscale old.png new.png I think there is already something on SO cf link Commented May 17, 2011 at 20:53

6 Answers 6

15

There is an easy solution:

plt.imsave(filename, image, cmap='gray')
Sign up to request clarification or add additional context in comments.

Comments

9

It's currently awkward to do directly from matplotlib, but in "the future" they plan to support a set_gray(True) call on the figure (see the mailing list thread here).

Your best options will be to save it in color and convert it, either in python with PIL:

import Image
Image.open('color.png').convert('L').save('bw.png')

or from the command line with imagemagick:

convert -type Grayscale color.png bw.png

1 Comment

Like the other answers, this answer is not very satisfactory because it rasterizes the plot.
5

Actually, this was asked before. Here is a pretty good answer, which comes 2nd on google (as of today):
Display image as grayscale using matplotlib

And the solution is VERY similar to Suki's...

Oh, well, I am bored, so I post here also a full blown code:

import numpy as np
import pylab as p
xv=np.ones(4)*.5
yv=np.arange(0,4,1)
xv1=np.ones(4)*-.5
yv1=np.arange(0,4,1)

#red vertical line on the right
yv2=np.arange(0,1.5,0.1)
xv2=np.ones_like(yv2)*.7

#red vertical line on the left
yv3=np.arange(0,2,0.01)
xv3=np.ones_like(yv3)*-0.7

###
xc=np.arange(-1.4,2,0.05)
yc=np.ones_like(xc)*1

fig = p.figure()
ax1 = fig.add_subplot(111)
#adjustprops = dict(left=0.12, bottom=0.2, right=0.965, top=0.96, wspace=0.13, hspace=0.37)
#fig.subplots_adjust(**adjustprops)
ax1.plot(xv,yv, color='blue', lw=1, linestyle='dashed')
ax1.plot(xv1,yv1, 'green', linestyle='dashed')
ax1.plot(np.r_[-1:1:0.2],np.r_[-1:1:0.2],'red')
ax1.plot(xc,yc, 'k.', markersize=3)

p.savefig('colored_image.png')

import matplotlib.image as mpimg
import matplotlib.cm as cm
import Image

figprops = dict(figsize=(10,10), dpi=100)
fig1 = p.figure(**figprops)
#fig1 = p.figure()
#ax1 = fig.add_subplot(111)
adjustprops = dict()
image=Image.open('colored_image.png').convert("L")
arr=np.asarray(image)
p.figimage(arr,cmap=cm.Greys_r)
p.savefig('grayed.png')
p.savefig('grayed.pdf',papertype='a4',orientation='portrait')

This will produce a graph in color, than read it, convert it to gray scale, and will save a png and pdf.

2 Comments

This answer is not very good because it requires rasterizing the plot and any fonts in it. The rasterization occurs when you convert to .png. It would be better to write a pdf to the filesystem and then convert that to grayscale, perhaps using ghostscript.
"import Image" no longer works. Instead use "from PIL import Image"
4

I am struggling with this issue too. As far as I can tell, matplotlib doesn't support direct conversion to grayscale, but you can save a color pdf and then convert it to grayscale with ghostscript:

gs -sOutputFile=gray.pdf -sDEVICE=pdfwrite -sColorConversionStrategy=Gray -dProcessColorModel=/DeviceGray -dNOPAUSE -dBATCH -dAutoRotatePages=/None color.pdf

5 Comments

why not just use the grayscale style sheet? matplotlib.org/examples/style_sheets/plot_grayscale.html
That doesn't actually convert a color plot to grayscale. It just makes some elements gray by default. I have plots that I want to export as both color for a web page and convert to gray for printing.
You can use the style sheets within a context manager. Wrap your calls to a non-data processing plotting function with those.
I don't understand this suggestion. Why does a context manager help? How is data processing relevant?
if you plotting function does a lot of data processing, making multiple calls to it will slow down the flow of your program. But pre-processing the data and then calling a simpler plotting function within a colorful then grayscale style context manager should be pretty manageable.
0

And to add to Mu Mind's solution

If for whatever reason you want to avoid writing it to a file you can use StringIO like a file:


 import Image
 import pylab
 from StringIO import StringIO

 pylab.plot(range(10),[x**2 for x in range(10)])

 IO = StringIO()
 pylab.savefig(IO,format='png')
 IO.seek(0)

 #this, I stole from Mu Mind solution
 Image.open(IO).convert('L').show()

1 Comment

Like the other answers, this answer is not very satisfactory because it rasterizes the plot.
0

Developed from Ian Goodfellow's answer, here is a python script that generates and runs a ghostscript command that converts a PDF into grayscale. It is preferable to the answers that rasterise to PNG as it retains the vector representation of the plot.

import subprocess
import sys 

def pdf_to_grayscale(input_pdf, output_pdf):
    try:
        # Ghostscript command to convert PDF to grayscale
        ghostscript_cmd = [
            "gs",
            "-sDEVICE=pdfwrite",
            "-sColorConversionStrategy=Gray",
            "-sProcessColorModel=DeviceGray",
            "-dCompatibilityLevel=1.4",
            "-dNOPAUSE",
            "-dQUIET",
            "-dBATCH",
            f"-sOutputFile={output_pdf}",
            input_pdf
        ]

        # Execute Ghostscript command using subprocess
        subprocess.run(ghostscript_cmd, check=True)

        print("PDF converted to grayscale successfully.")
    except subprocess.CalledProcessError:
        print("Error occurred during PDF conversion to grayscale.")

if __name__ == "__main__":
    assert len(sys.argv) == 3, "Two args: input pdf and output pdf"    
    pdf_to_grayscale(sys.argv[1], sys.argv[2])

Save it as to_gray.py and run it like this:

python to_gray.py test.pdf gray.pdf

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.