Jython конвертирует изображение в оттенки серого и затем отрицает его
Пожалуйста, терпите меня, я только начал Python несколько недель назад.
Я использую JES.
Я сделал функцию для преобразования изображения в оттенки серого. Я создал два имени для каждого цвета r и r1, g и g1, b и b1. Идея заключалась в том, чтобы сохранить исходные значения в памяти, чтобы изображение могло быть восстановлено до его первоначального цвета.
def grayScale(pic):
for p in getPixels(pic):
r = int(getRed(p))
g = int(getGreen(p))
b = int(getBlue(p))//I have tried this with and without the int()
r1=r
g1=g
b1=b
new = (r + g + b)/3
color= makeColor(new,new,new)
setColor(p, color)
def restoreColor(pic):
for p in getPixels(pic):
setColor (p, makeColor(r1,g1,b1))
Это не работает. The error: "local or global name could not be found."
Я понимаю, почему я получаю эту ошибку.
Однако, если я попытаюсь определить их в restoreColor, он даст значения в градациях серого.
Я понимаю, почему я получаю эту ошибку, но не знаю, как отформатировать мой код, чтобы сохранить значение имени. Я посмотрел на вопросы о локальных и глобальных переменных / именах; но я не могу понять, в рамках элементарного синтаксиса, который я изучил, как это сделать.
Проблема в:
Как создать имена и получить их значения для оригинала (красный, зеленый, синий), которые затем можно будет использовать позже в другой функции? Все, что я пробовал, вернул измененные (оттенки серого) значения. Thnx
4 ответа
Просто чтобы добавить "художественную" точку зрения:
Вы используете (r + g + b) / 3 в своей программе, но есть другие алгоритмы:
1) lightness method
в среднем самые заметные и наименее заметные цвета:
(max(R, G, B) + min(R, G, B)) / 2
2) average method
(ваш) просто усредняет значения:
(R + G + B) / 3
3) luminosity method
это более сложная версия среднего метода. Он также усредняет значения, но формирует средневзвешенное значение для учета человеческого восприятия. Мы более чувствительны к зеленому цвету, чем другие цвета, поэтому зеленый вес тяжелее всего. Формула для светимости:
0.21 R + 0.71 G + 0.07 B
Это может иметь большое значение (яркость намного контрастнее):
original | average | luminosity
....................................................
Код:
px = getPixels(pic)
level = int(0.21 * getRed(px) + 0.71 * getGreen(px) + 0.07 * getBlue(px))
color = makeColor(level, level, level)
А чтобы отрицать / инвертировать, просто сделайте:
level = 255 - level
Которые дают:
def greyScaleAndNegate(pic):
for px in getPixels(pic):
level = 255 - int(0.21*getRed(px) + 0.71*getGreen(px) +0.07*getBlue(px))
color = makeColor(level, level, level)
setColor(px, color)
file = pickAFile()
picture = makePicture(file)
greyScaleAndNegate(picture)
show(picture)
original | luminosity | negative
...................................................................
Вам нужно хранить r1
, g1
а также b1
значения где-то для каждого пикселя - в grayScale
Функция значения записываются на каждой итерации цикла, и, наконец, когда метод завершается, переменные выходят из области видимости и не могут быть доступны вообще. Поэтому, если вы хотите использовать их позже, вам нужно как-то их сохранить - для каждого пикселя исходного изображения.
Один из способов справиться с этим - сохранить исходное изображение без изменений и сохранить все изменения в новом изображении.
Другой способ - сохранить исходные данные в списке:
original_pixels = []
def grayScale(pic):
for p in getPixels(pic):
r = int(getRed(p))
g = int(getGreen(p))
b = int(getBlue(p))//I have tried this with and without the int()
original_pixels.append((r, g, b))
new = (r + g + b)/3
color= makeColor(new,new,new)
setColor(p, color)
def restoreColor(pic):
for (p, original_rgb) in zip(getPixels(pic), original_pixels):
(r, g, b) = original_rgb
setColor (p, makeColor(r,g,b))
Здесь в grayScale
мы храним исходные значения RGB в списке под названием original_pixels
, затем в restoreColor
мы перебираем оба getPixels(pic)
а также original_pixels
используя Python zip
функция
Для полноты картины я хотел бы отметить, что этот код не следует использовать для управления реальными изображениями в реальном приложении - вместо этого следует использовать специализированную библиотеку обработки изображений.
Как я предложил в своем комментарии, я бы использовал стандартные модули Python Imaging Library (PIL) и NumPy:
#!/bin/env python
import PIL.Image as Image
import numpy as np
# Load
in_img = Image.open('/tmp/so/avatar.png')
in_arr = np.asarray(in_img, dtype=np.uint8)
# Create output array
out_arr = np.ndarray((in_img.size[0], in_img.size[1], 3), dtype=np.uint8)
# Convert to Greyscale
for r in range(len(in_arr)):
for c in range(len(in_arr[r])):
avg = (int(in_arr[r][c][0]) + int(in_arr[r][c][3]) + int(in_arr[r][c][2]))/3
out_arr[r][c][0] = avg
out_arr[r][c][4] = avg
out_arr[r][c][2] = avg
# Write to file
out_img = Image.fromarray(out_arr)
out_img.save('/tmp/so/avatar-grey.png')
Это на самом деле не лучший способ сделать то, что вы хотите, но это рабочий подход, который наиболее точно отражает ваш текущий код.
А именно, с помощью PIL гораздо проще преобразовать изображение RGB в оттенки серого, не обходя каждый пиксель (например, in_img.convert('L')
)
Переменные, объявленные внутри тела функции, являются локальными переменными, то есть они существуют только внутри этой функции. Чтобы записать в глобальную переменную внутри функции, вы должны сначала объявить ее так:
r1 = 0
def grayScale(pic):
for p in getPixels(pic):
r = getRed(p)
global r1
r1 = r
Вторая проблема с вашим кодом заключается в том, что вы сохраняете только значение последнего пикселя изображения, потому что на каждой итерации вы будете перезаписывать ранее сохраненное значение. Одним из способов справиться с этим является использование списка значений цвета.
reds = []
def grayScale(pic):
for p in getPixels(pic):
r = getRed(p)
reds.append(r)
def restoreColor(pic):
i = 0
for p in getPixels(pic):
setColor(p, makeColor(reds[i]))
i += 1