Skip to content

Instantly share code, notes, and snippets.

@kenichinakanishi
Last active November 10, 2020 05:33
Show Gist options
  • Save kenichinakanishi/4327cff12ddc51f44903c07f384ce8d0 to your computer and use it in GitHub Desktop.
Save kenichinakanishi/4327cff12ddc51f44903c07f384ce8d0 to your computer and use it in GitHub Desktop.
def image_histogram(img_path,
plot=True,
plot_raw = True,
max_intensity = 1000000,
print_threshold_diagnostics = False,
color_width = 1000,
return_proportion = False):
""" Takes in an image, and plots a histogram of color population against (hue,lightness) pairs.
If an image has a population of n (n = color_width) pixels with a specific
(hue,lightness) pair that make up more than pct_threshold of an image, we tag that image as artificial.
Parameters
----------
img_folder: Path or str
Fold with images to examine.
plot: bool
Plot histogram or not.
plot_raw: bool
Plot raw images or not.
max_intensity: int
Ceiling value for the hue:lightness pair populations. This value will affect the pixel proportion if too low.
print_threshold_diagnostics: bool
Prints diagnositic information (number of hue/lightness pairs, how many are accounted for in calculating the proportion of the final image.)
color_width: int
How many of the most populous hue:lightness pairs to sum together to determine the proportion of the final image they occupy.
return_proportion: bool
Should the function return the color proportion coverage value.
Returns:
----------
Color proportion coverage value (if return_proportion=True)
Histogram (if plot=True)
Raw Image (if plot_raw=True)
"""
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import colorsys
from PIL import Image
# Open image and get dimensions
img_file = Image.open(img_path).convert('RGB')
img = img_file.load()
[xs,ys] = img_file.size
max_intensity = max_intensity
hues = {}
# For each pixel in the image file
for x in range(0, xs):
for y in range(0, ys):
# Get the RGB color of the pixel
[r, g, b] = img[x, y]
# Normalize pixel color values
r /= 255.0
g /= 255.0
b /= 255.0
# Convert RGB color to HSL
[h, l, s] = colorsys.rgb_to_hls(r, g, b)
# Count how many pixels have matching (h, l)
if h not in hues:
hues[h] = {}
if l not in hues[h]:
hues[h][l] = 1
else:
if hues[h][l] < max_intensity:
hues[h][l] += 1
# Decompose the hues object into a set of one dimensional arrays
h_ = []
l_ = []
i = []
colours = []
for h in hues:
for l in hues[h]:
h_.append(h)
l_.append(l)
i.append(hues[h][l])
[r, g, b] = colorsys.hls_to_rgb(h, l, 1)
colours.append([r, g, b])
# Plot if wanted
raw_image = Image.open(img_path)
raw_image = np.asarray(raw_image)
if plot==True:
fig = plt.figure(figsize=(12,5))
fig.set_facecolor("white")
ax = plt.subplot2grid((2,6), (0,0), colspan=4, rowspan=2, projection='3d')
ax.scatter(h_, l_, i, s=30, c=colours, lw=0.5, edgecolors='black')
ax.set_xlabel('Hue')
ax.set_ylabel('Lightness')
ax.set_zlabel('Population')
# Plot raw image if wanted
if plot_raw == True:
ax2 = plt.subplot2grid((2,6), (0,4), colspan=2, rowspan=2)
ax2.imshow(raw_image)
ax2.title.set_text(f'Raw Image: {img_path.name}')
plt.tight_layout()
plt.show()
# Determine if the image we're examining is artificially generated
n_greatest = sum(sorted(i, reverse=True)[:color_width])
picture_size = xs*ys
if print_threshold_diagnostics == True:
print(f'There are {len(i)} hue/lightness pairs in this image.')
print(f'Population of {color_width} hue/lightness pairs with the largest populations = {n_greatest}')
print(f'This represents {n_greatest/picture_size*100:.2f}% of the total pixels in the image.')
if return_proportion == True:
return n_greatest/picture_size
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment