Jython 将图片转换为灰度然后取反
Posted
技术标签:
【中文标题】Jython 将图片转换为灰度然后取反【英文标题】:Jython convert picture to grayscale and then negate it 【发布时间】:2013-06-14 00:39:00 【问题描述】:请多多包涵,我几周前才开始使用 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 中定义它们,它会给出灰度值。
我了解为什么会收到此错误,但不知道如何格式化我的代码以保存名称值。我查看了有关局部和全局变量/名称的问题;但在我所学的基本语法中,我无法弄清楚如何做到这一点。
问题是:
如何为原始(红色、绿色、蓝色)创建名称并获取它们的值,以便稍后在另一个函数中使用?我尝试过的所有内容都返回了更改后的(灰度)值。
【问题讨论】:
【参考方案1】:您需要将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
中,我们使用 Python 的 zip
函数对 getPixels(pic)
和 original_pixels
进行迭代
为了完整起见,我想指出,此代码不应用于在实际应用程序中处理真实图像 - 应改为使用专门的图像处理库。 p>
【讨论】:
【参考方案2】:在函数体内声明的变量是局部变量,即它们只存在于该函数内部。要写入函数内的 全局 变量,您必须首先将其声明为:
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
【讨论】:
【参考方案3】:正如我在评论中所建议的,我将使用标准模块 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')
)
【讨论】:
【参考方案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
....................... ............................
【讨论】:
以上是关于Jython 将图片转换为灰度然后取反的主要内容,如果未能解决你的问题,请参考以下文章
MATLAB应用实战系列(七十一)-MATLAB实战应用案例:图像处理将灰度图片变成负片&彩色图片转换成灰度图片
MATLAB应用实战系列(七十一)-MATLAB实战应用案例:图像处理将灰度图片变成负片&彩色图片转换成灰度图片