Search code examples
pythonpython-3.ximagefiltergrayscale

Convert an image to grayscale using a limited amount of shades?


I am looking to convert images to grayscale, but would like to limit the amount of shades to 4-5. The reason for this is because I am trying to create a layered 'paper cutout' effect of the images so that I can use it as a base for some artwork I am working on in which I have 5 shades of black-white to work with.

If you have better ideas of how to achieve this with Python, I'm all ears. It would be super convenient if a filter like this already existed in Python but I can't seem to find anything. Appreciate it.

The project end result is to look something like this: Image


Solution

  • You can use PIL to quantize this:

    enter image description here

    into this:

    enter image description here

    like this:

    #!/usr/bin/env python3
    
    from PIL import Image
    
    # Load image and make greyscale
    im = Image.open('artistic-swirl.jpg').convert('L')
    
    # Quantize down to 5 shades and save
    qu = im.quantize(5)
    qu.save('result.png')
    
    print(f'Colours: {qu.getcolors()}')
    

    Sample Output

    You can see the list of 5 resulting colours (palette indices) and their frequency of occurrence below:

    Colours: [(32047, 0), (34515, 1), (59838, 2), (70181, 3), (53419, 4)]
    

    You can equally check the colours with ImageMagick like this:

    magick identify -verbose result.png
    

    Sample Output

    Image:
      Filename: result.png
      Format: PNG (Portable Network Graphics)
      Mime type: image/png
      Class: PseudoClass
      Geometry: 500x500+0+0
      Units: Undefined
      Colorspace: sRGB
      Type: Grayscale
      Base type: Undefined
      Endianness: Undefined
      Depth: 8-bit
      Channel depth:
        Red: 8-bit
        Green: 8-bit
        Blue: 8-bit
      Channel statistics:
        Pixels: 250000
        Red:
          min: 106  (0.415686)
          max: 166 (0.65098)
          mean: 133.412 (0.523186)
          median: 139 (0.545098)
          standard deviation: 19.4166 (0.0761436)
          kurtosis: -0.979496
          skewness: 0.129338
          entropy: 0.972589
        Green:
          min: 106  (0.415686)
          max: 166 (0.65098)
          mean: 133.412 (0.523186)
          median: 139 (0.545098)
          standard deviation: 19.4166 (0.0761436)
          kurtosis: -0.979496
          skewness: 0.129338
          entropy: 0.972589
        Blue:
          min: 106  (0.415686)
          max: 166 (0.65098)
          mean: 133.412 (0.523186)
          median: 139 (0.545098)
          standard deviation: 19.4166 (0.0761436)
          kurtosis: -0.979496
          skewness: 0.129338
          entropy: 0.972589
      Image statistics:
        Overall:
          min: 106  (0.415686)
          max: 166 (0.65098)
          mean: 133.412 (0.523186)
          median: 139 (0.545098)
          standard deviation: 19.4166 (0.0761436)
          kurtosis: -0.979485
          skewness: 0.129339
          entropy: 0.972589
      Colors: 5
      Histogram:
             53419: (106,106,106) #6A6A6A srgb(106,106,106)
             70181: (125,125,125) #7D7D7D grey49
             59838: (139,139,139) #8B8B8B srgb(139,139,139)
             34515: (153,153,153) #999999 grey60
             32047: (166,166,166) #A6A6A6 grey65
      Colormap entries: 5
      Colormap:
        0: (166,166,166,1) #A6A6A6FF grey65
        1: (153,153,153,1) #999999FF grey60
        2: (139,139,139,1) #8B8B8BFF srgba(139,139,139,1)
        3: (125,125,125,1) #7D7D7DFF grey49
        4: (106,106,106,1) #6A6A6AFF srgba(106,106,106,1)
      Rendering intent: Perceptual
      Gamma: 0.454545
      Chromaticity:
        red primary: (0.64,0.33)
        green primary: (0.3,0.6)
        blue primary: (0.15,0.06)
        white point: (0.3127,0.329)
      Matte color: grey74
      Background color: white
      Border color: srgb(223,223,223)
      Transparent color: none
      Interlace: None
      Intensity: Undefined
      Compose: Over
      Page geometry: 500x500+0+0
      Dispose: Undefined
      Iterations: 0
      Compression: Zip
      Orientation: Undefined
      Properties:
        date:create: 2022-06-30T13:25:02+00:00
        date:modify: 2022-06-30T13:25:02+00:00
        png:IHDR.bit-depth-orig: 4
        png:IHDR.bit_depth: 4
        png:IHDR.color-type-orig: 3
        png:IHDR.color_type: 3 (Indexed)
        png:IHDR.interlace_method: 0 (Not interlaced)
        png:IHDR.width,height: 500, 500
        png:PLTE.number_colors: 5
        png:sRGB: intent=0 (Perceptual Intent)
        signature: ff62d5806f38bc0228513619c9822015bc70ee8466714b0317441e89ff3b815b
      Artifacts:
        verbose: true
      Tainted: False
      Filesize: 15193B
      Number pixels: 250000
      Pixel cache type: Memory
      Pixels per second: 90.1415MP
      User time: 0.000u
      Elapsed time: 0:01.002
      Version: ImageMagick 7.1.0-33 Q16-HDRI arm 20040 https://imagemagick.org
    

    Keywords: Python, image processing, quantize, reduce colours.