Reorganize image pixels by sorting them by brightness and hue.
from PIL import Image
import matplotlib.pyplot as plt
import cv2
import numpy as np
import math
Resize image to 500 px in width and height calculated from original aspect ratio.
basewidth = 500
img = Image.open('input1080.jpg')
wpercent = (basewidth/float(img.size[0]))
hsize = int((float(img.size[1])*float(wpercent)))
img = img.resize((basewidth,hsize), Image.ANTIALIAS)
img.save('smaller.jpg')
Read images.
big = cv2.imread('input1080.jpg')
small = cv2.imread('smaller.jpg')
Convert them to RGB colorspace, since OpenCV uses BGR by default.
big = cv2.cvtColor(big, cv2.COLOR_BGR2RGB)
small = cv2.cvtColor(small, cv2.COLOR_BGR2RGB)
Comparison of original and scaled images.
%matplotlib notebook
plt.figure(1, figsize=(9,3))
plt.subplot(1,2,1)
plt.imshow(big)
plt.title('Original image')
plt.subplot(1,2,2)
plt.imshow(small)
plt.title('Scaled image')
plt.show()
Read both images' sizes and save size of scaled image.
[w, h, c] = big.shape
print("Big image size: {}x{}".format(w, h))
[w, h, c] = small.shape
print("Small image size: {}x{}".format(w, h))
Convert image into 1D list for sorting.
pixel_list = list()
for i in range(h):
for j in range(w):
pixel_list.append(small[j, i])
Below is a veeery slow sorting algorithm. Don't use it.
# Super slow!
# selection sorting
for i in range(len(pixel_list)):
max_idx = i
max_val = brightness(pixel_list[i])
for j in range(i, len(pixel_list)):
if brightness(pixel_list[j]) > max_val:
max_idx = j
max_val = brightness(pixel_list[j])
# swap
if max_idx != i:
pixel_list[i], pixel_list[max_idx] = pixel_list[max_idx], pixel_list[i]
This function is used to convert 1D image list into 2D image array.
def list_to_image(pixels, width, height):
image = np.zeros((width, height, 3), np.uint8)
print("Number of pixels:", len(pixels))
for i in range(len(pixels)):
y = i % height
x = int((i - y) / height)
image[x, y] = pixels[i]
return image
Functions used as keys in sorting. They return brightness and hue of a pixel.
def brightness(pixel):
return sum(pixel)/3
def hue(pixel):
R, G, B = pixel
return math.atan2(math.sqrt(R) * (G - B), 2 * R - G - B)
Sort by brightness.
sorted_pixels_bright = sorted(pixel_list, key = brightness, reverse = True)
sorted_bright = list_to_image(sorted_pixels_bright, w, h)
Sort by hue.
sorted_pixels_hue = sorted(pixel_list, key = hue, reverse = True)
sorted_hue = list_to_image(sorted_pixels_hue, w, h)
Compare unsorted and sorted images.
Also show their histograms in order to prove, that none of the pixels are changed.
plt.figure(2, figsize=(11,6))
plt.subplot(2,3,1)
plt.title('Original image')
plt.imshow(small)
plt.subplot(2,3,2)
plt.imshow(sorted_bright)
plt.title('Sorted by brightness')
# plt.show()
plt.subplot(2,3,3)
plt.imshow(sorted_hue)
plt.title('Sorted by hue')
# plt.show()
color = ('r', 'g', 'b')
for channel, col in enumerate(color):
hist = cv2.calcHist([small], [channel], None, [256], [0,256])
plt.subplot(2,3,4)
plt.plot(hist, color = col)
plt.xlim([0,256])
plt.title('Histogram for original image')
# plt.show()
for channel, col in enumerate(color):
hist = cv2.calcHist([sorted_bright], [channel], None, [256], [0,256])
plt.subplot(2,3,5)
plt.plot(hist, color = col)
plt.xlim([0,256])
plt.title('Histogram brightness')
# plt.show()
for channel, col in enumerate(color):
hist = cv2.calcHist([sorted_hue], [channel], None, [256], [0,256])
plt.subplot(2,3,6)
plt.plot(hist, color = col)
plt.xlim([0,256])
plt.title('Histogram hue')
plt.show()
by Wojciech Wiertarka