Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adobe Photoshop-style posterization and OpenCV

It seems Adobe Photoshop does posterization by quantizing each color channel separately, based on the number of levels specified. So for example, if you specify 2 levels, then it will take the R value, and set it to 0 if your R value is less than 128 or 255 if your value is >= 128. It will do the same for G and B.

Is there an efficient way to do this in python with OpenCV besides iterating through each pixel and making that comparison and setting the value separately? Since an image in OpenCV 2.4 is a NumPy ndarray, is there perhaps an efficient way to do this calculation strictly through NumPy?

like image 922
steve8918 Avatar asked Jun 16 '12 14:06

steve8918


Video Answer


2 Answers

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...

like image 196
Abid Rahman K Avatar answered Nov 17 '22 09:11

Abid Rahman K


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

like image 21
fraxel Avatar answered Nov 17 '22 09:11

fraxel