Apply MatplotLib Or Custom Colormap To OpenCV Image


Answer :

For Python >= 2.7, cmapy packages this functionality in a convenient way. Install it with:

Python 2.7:

pip install cmapy 

Python 3.x:

pip3 install cmapy 

Or, for Anaconda (from conda-forge):

conda install -c conda-forge cmapy  

And use it like this:

import cv2 import matplotlib.pyplot as plt import cmapy  # Read image. img = cv2.imread('imgs/woman.png')  # Colorize. img_colorized = cv2.applyColorMap(img, cmapy.cmap('viridis'))  # Display plt.imshow(img_colorized) plt.show() 

Different colormaps give something like this:

See all the available colormaps in action here.

Disclaimer: I wrote cmapy (because I needed this functionality for another project), and internally, it does pretty much the same as the other answers.


In recent versions of OpenCV (starting with 3.3), there's an overload of applyColorMap, which allows you to provide a custom colormap (either 1 or 3 channel). I've modified verified.human's code to simply generate a colormap suitable to use with this function.

I've taken few more opportunities to simplify the code:

  • ScalarMappable.to_rgba can return bytes (in range 0-255) directly when you set bytes argument to True.
  • We can use array indexing with negative step size to remove the alpha channels as well as switch from RGB to BGR in one step

Code:

import cv2 import numpy as np from matplotlib import pyplot as plt   def get_mpl_colormap(cmap_name):     cmap = plt.get_cmap(cmap_name)      # Initialize the matplotlib color map     sm = plt.cm.ScalarMappable(cmap=cmap)      # Obtain linear color range     color_range = sm.to_rgba(np.linspace(0, 1, 256), bytes=True)[:,2::-1]      return color_range.reshape(256, 1, 3)   image_gray = cv2.imread('cage.png', cv2.IMREAD_GRAYSCALE) image_bgr = cv2.applyColorMap(image_gray, get_mpl_colormap('bwr'))  cv2.imshow('image with colormap', image_bgr) cv2.waitKey() 

Answering my own question because I did not find an easy solution on StackOverflow:

def apply_custom_colormap(image_gray, cmap=plt.get_cmap('seismic')):      assert image_gray.dtype == np.uint8, 'must be np.uint8 image'     if image_gray.ndim == 3: image_gray = image_gray.squeeze(-1)      # Initialize the matplotlib color map     sm = plt.cm.ScalarMappable(cmap=cmap)      # Obtain linear color range     color_range = sm.to_rgba(np.linspace(0, 1, 256))[:,0:3]    # color range RGBA => RGB     color_range = (color_range*255.0).astype(np.uint8)         # [0,1] => [0,255]     color_range = np.squeeze(np.dstack([color_range[:,2], color_range[:,1], color_range[:,0]]), 0)  # RGB => BGR      # Apply colormap for each channel individually     channels = [cv2.LUT(image_gray, color_range[:,i]) for i in range(3)]     return np.dstack(channels)   image_gray = cv2.imread('./lena.jpg', cv2.IMREAD_GRAYSCALE) image_bgr = apply_custom_colormap(image_gray, cmap=plt.get_cmap('bwr'))  cv2.imshow('image with colormap', image_bgr) cv2.waitKey(0) 

Produces the image:

enter image description here


Comments

Popular posts from this blog

Are Regular VACUUM ANALYZE Still Recommended Under 9.1?

Can Feynman Diagrams Be Used To Represent Any Perturbation Theory?