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, это даст значения в градациях серого.

Я понимаю, почему я получаю эту ошибку, но не знаю, как форматировать мой код, чтобы сохранить значение имени. Я просмотрел вопросы о локальных и глобальных переменных/именах; но я не могу сообразить, как это сделать с помощью того элементарного синтаксиса, который я выучил.

Проблема в:

Как мне создать имена и получить их значения для оригинала (красный, зеленый, синий), которые я могу использовать позже в другой функции? Все, что я пробовал, вернуло измененные (оттенки серого) значения. спасибо


person Community    schedule 17.06.2013    source источник


Ответы (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

........введите здесь описание изображения............ ...........введите здесь описание изображения......... ................введите здесь описание изображения.... .......

person Gauthier Boaglio    schedule 26.06.2013

Переменные, объявленные внутри тела функции, являются локальными переменными, т. е. существуют только внутри этой функции. Чтобы записать в глобальную переменную внутри функции, вы должны сначала объявить ее как таковую:

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
person Esenti    schedule 17.06.2013

Вам нужно где-то хранить значения 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.

Для полноты картины я хотел бы отметить, что этот код не следует использовать для работы с реальными изображениями в реальном приложении — вместо этого следует использовать специализированную библиотеку обработки изображений.

person Sergey    schedule 17.06.2013

Как я предложил в своем комментарии, я бы использовал стандартные модули 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'))

person jedwards    schedule 17.06.2013