Adobe Photoshop-style posterization and OpenCV

Your question specifically seems to be asking about a level of 2. But what about levels more than 2. So i have added a code below which can posterize for any level of color.

import numpy as np
import cv2

im = cv2.imread('messi5.jpg')

n = 2    # Number of levels of quantization

indices = np.arange(0,256)   # List of all colors 

divider = np.linspace(0,255,n+1)[1] # we get a divider

quantiz = np.int0(np.linspace(0,255,n)) # we get quantization colors

color_levels = np.clip(np.int0(indices/divider),0,n-1) # color levels 0,1,2..

palette = quantiz[color_levels] # Creating the palette

im2 = palette[im]  # Applying palette on image

im2 = cv2.convertScaleAbs(im2) # Converting image back to uint8

cv2.imshow('im2',im2)
cv2.waitKey(0)
cv2.destroyAllWindows()

This code uses a method called palette method in Numpy which is really fast than iterating through the pixels. You can find more details how it can be used to speed up code here : Fast Array Manipulation in Numpy

Below are the results I obtained for different levels:

Original Image :

enter image description here

Level 2 :

enter image description here

Level 4 :

enter image description here

Level 8 :

enter image description here

And so on...


The coolest "posterization" I have seen uses Mean Shift Segmentation. I used the code from the author's GitHub repo to create the following image (you need to uncomment line 27 of Maincpp.cpp to perform the segmentation step).

enter image description here


We can do this quite neatly using numpy, without having to worry about the channels at all!

import cv2
im = cv2.imread('1_tree_small.jpg')
im[im >= 128]= 255
im[im < 128] = 0
cv2.imwrite('out.jpg', im)

output:

enter image description here

input:

enter image description here


Use cv::LUT(). It is simplest and fastest way.

cv::Mat posterize(const cv::Mat &bgrmat, uint8_t lvls)
{
    cv::Mat lookUpTable(1, 256, CV_8U);
    uchar* p = lookUpTable.ptr();
    float step = 255.0f / lvls;
    for(int i = 0; i < 256; ++i)
        p[i] = static_cast<uchar>(step * std::floor(i / step));
    cv::Mat omat;
    cv::LUT(bgrmat,lookUpTable,omat);
    return omat;
}