13

Top answer in this link How to pixelate a square image to 256 big pixels with python? uses PIL to pixelate image. Converting image from PIL to cv2.Mat is possible but I'm not allowed to use other library, and I couldn't find any good method using opencv.

Is there any way to pixelate image using OpenCV library only in Python? Any sample image is fine. Solution with pixel size parameter that I can control for later adjustment would be very appreciated.

1

2 Answers 2

28

EDIT^2

With the help of himself, I moved Mark Setchell's answer, which is the above mentioned top answer, to plain OpenCV Python code. (Have a look at the revision history of my answer to see the old version using a loop.)


import cv2

# Input image
input = cv2.imread('images/paddington.png')

# Get input size
height, width = input.shape[:2]

# Desired "pixelated" size
w, h = (16, 16)

# Resize input to "pixelated" size
temp = cv2.resize(input, (w, h), interpolation=cv2.INTER_LINEAR)

# Initialize output image
output = cv2.resize(temp, (width, height), interpolation=cv2.INTER_NEAREST)

cv2.imshow('Input', input)
cv2.imshow('Output', output)

cv2.waitKey(0)

Input (from linked question):

Input

Output:

Output

Disclaimer: I'm new to Python in general, and specially to the Python API of OpenCV (C++ for the win). Comments, improvements, highlighting Python no-gos are highly welcome!

Sign up to request clarification or add additional context in comments.

16 Comments

Why not cv2.resize(...INTER_NEAREST...)?
@MarkSetchell Do you refer to the "first" cv2.resize(...) or the "second" (in your code from the linked answer)? For the latter: I tried that, but I got some interpolated image, and not that "pixelated" kind of. There seem to be differences in PIL and OpenCV regarding this issue - which I assume is the reason, the questioner posted this question in first place.
I just had a go and it seems to work fine for me if I replace all your code after the word "Initialize" with this big = cv2.resize(temp, (w, h), 0, 0, cv2.INTER_NEAREST) Don't worry, you already have my vote anyway ;-)
Cool :-) Teamwork! Ein bisschen Zusammenarbeit ist immer gut :-)
@mLstudent33 I'm not sure I remember why. Sometimes I answer questions more than once because OP asks for something in Python and OpenCV but I can do it much more simply with an ImageMagick one-liner, then later I realise how I could do it with Python and, as it's based on totally distinct technology, I make a new answer to keep things clear. Other times I put 4 different techniques in one answer stackoverflow.com/a/57579290/2836621 because there is no response from OP so I work on different solutions that may appeal more to them. It's quite fluid.
|
1

For anyone looking for alternate solution,

import cv2
import numpy as np

img = cv2.imread('input.png')
height, width, channels = img.shape

pixel_size = 50

# Pad image
pad_x = (pixel_size - width % pixel_size) % pixel_size
pad_y = (pixel_size - height % pixel_size) % pixel_size
img = np.pad(img, ((0, pad_y), (0, pad_x), (0, 0)), mode='reflect')

# Reshape image into blocks and compute average color of each block
h, w, c = img.shape
blocks = np.mean(img.reshape(h//pixel_size, pixel_size, -1, pixel_size, c), axis=(1, 3))

# Repeat average color of each block to fill corresponding region in the image
output = np.repeat(np.repeat(blocks, pixel_size, axis=1), pixel_size, axis=0)

# Remove padding
output = output[:height, :width].astype("uint8")

cv2.imshow('Output', output)
cv2.waitKey(0)

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.