Как я могу проверить, является ли изображение сепией? - PullRequest
0 голосов
/ 23 января 2020

Есть много постов, в которых рассказывается, как конвертировать изображения в сепия, но я пытаюсь выяснить, как определить, является ли изображение УЖЕ сепия ( без явной подготовки модели ML для простой классификации).

Я попытался написать функцию для монохроматизма, но она не работает. Любая помощь будет оценена.

pic = Image.open(file)

pixel_values = list(pic.getdata())

for subpixels in pixel_values:
            if abs(subpixels[0] - subpixels[1]) < 50 and abs(subpixels [1] - subpixels [2]) < 50 and abs(subpixels[0] - subpixels[2]) < 50:
                count += 1
            else:
                pass

if count / len(subpixels) > .5:
            print('is chromatic')

Ответы [ 2 ]

2 голосов
/ 24 января 2020

Я бы придерживался идеи использовать цветовое пространство HSV для идентификации областей с цветами, подобными сепии - как также упоминалось в одном из комментариев. Тем не менее, я бы выполнил обработку, используя NumPy и OpenCV , поскольку операции с массивами выполняются намного быстрее, чем итерирование пикселей в Pillow (PIL).

Вот мое решение:

import cv2
from matplotlib import pyplot as plt
import numpy as np
from PIL import Image

# Calculate "sepia mask" using HSV color space; empirically set parameters
def sepia_mask(img):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    sepia_lower = np.array([np.round( 30 / 2), np.round(0.10 * 255), np.round(0.10 * 255)])
    sepia_upper = np.array([np.round( 45 / 2), np.round(0.60 * 255), np.round(0.90 * 255)])
    return cv2.inRange(hsv, sepia_lower, sepia_upper)

# "Sepia kernel" for filtering; https://amin-ahmadi.com/2016/03/24/sepia-filter-opencv/
sepia_kernel = np.array([
    [0.272, 0.534, 0.131],
    [0.349, 0.686, 0.168],
    [0.393, 0.769, 0.189]])

# Read image via Pillow; processing using OpenCV; sepia filtering
image_pil = Image.open('path/to/your/image.png')
image = np.flip(np.array(image_pil), 2)
sepia = cv2.transform(image, sepia_kernel)

# Outputs and sepia percentages
plt.figure(1, figsize=(9, 9))
plt.subplot(2, 2, 1), plt.imshow(np.flip(image, 2)), plt.title('Original image')
plt.subplot(2, 2, 2), plt.imshow(sepia_mask(image), cmap='gray')
perc = cv2.countNonZero(sepia_mask(image)) / np.prod(image.shape[:2])
plt.title('Sepia mask [' + str(perc) + ']')
plt.subplot(2, 2, 3), plt.imshow(np.flip(sepia, 2)), plt.title('Sepia filtered image')
plt.subplot(2, 2, 4), plt.imshow(sepia_mask(sepia), cmap='gray')
perc = cv2.countNonZero(sepia_mask(sepia)) / np.prod(sepia.shape[:2])
plt.title('Sepia mask [' + str(perc) + ']')
plt.tight_layout()
plt.show()

Вот несколько примерных выводов:

Output

В зависимости от фактического "сепия" "вы хотите обнаружить, вам нужно адаптировать параметры в методе sepia_mask. Как видите, я подсчитал некоторые «проценты сепии». Установите некоторые ограничения для классификации сепия / не сепия.

Надеюсь, что помогает!

----------------------------------------
System information
----------------------------------------
Platform:    Windows-10-10.0.16299-SP0
Python:      3.8.1
Matplotlib:  3.2.0rc1
NumPy:       1.18.1
OpenCV:      4.1.2
Pillow:      7.0.0
----------------------------------------
1 голос
/ 24 января 2020

Вот еще один способ измерить количество цвета сепии на изображении в Python / OpenCV. Просто получите средний цвет изображения, а затем различие между средним и вашим определенным цветом сепии. Это не измеряет пространственно, сколько пикселей настроено на сепию, как в методе ниже HansHirse. Он просто измеряет общую разницу цветов.

Изображение 1 (с оттенками сепии):

enter image description here

Изображение 2 (с голубыми тонами):

enter image description here

import cv2
import numpy as np

# read images
img1 = cv2.imread('bear_sepia.png')
img2 = cv2.imread('bear_blue.png')

# compute mean color
mean1 = np.mean(img1, axis=(0,1))
mean2 = np.mean(img2, axis=(0,1))

print("img1_mean =",mean1)
print("img2_mean =",mean2)

# define sepia color
sepia = (20,66,112)

# compute inverse root mean squared difference as percent
# 100 is pure sepia color
inv_rmse1 = 100.0 * (1 - np.sqrt( ((mean1[0] - sepia[0])**2 + (mean1[1] - sepia[1])**2 + (mean1[2] - sepia[2])**2)/3 ) / 255.0)
inv_rmse2 = 100.0 * (1 - np.sqrt( ((mean2[0] - sepia[0])**2 + (mean2[1] - sepia[1])**2 + (mean2[2] - sepia[2])**2)/3 ) / 255.0)

print("percent_sepia_img1 =",inv_rmse1)
print("percent_sepia_img2 =",inv_rmse2)

cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
cv2.waitKey()


Результаты:

img1_mean = [ 54.11960236  84.72731845 115.33092206]
img2_mean = [200.27158686  76.78135771  76.78135771]

percent_sepia_img1 = 91.15556648084234
percent_sepia_img2 = 58.34117845977803


...