【问题标题】:Python 3: Converting image to grayscalePython 3:将图像转换为灰度
【发布时间】:2011-04-18 10:23:59
【问题描述】:

我正在尝试在 John Zelle 的“Python 编程:计算机科学导论”中做一个练习。我为他的书下载了一个特殊的图形包(graphics.py,在链接的网站上)。问题如下:

编写一个将彩色图像转换为灰度图像的程序。用户提供包含 GIF 或 PPM 图像的文件名,程序加载图像并显示文件。单击鼠标,程序将图像转换为灰度。然后提示用户输入一个文件名来存储灰度图像。

您可能需要返回并查看图形库中的 Image 对象(第 4.8.4 节)。转换图像的基本思想是逐个像素地遍历它,并将每个图像从颜色转换为适当的灰色阴影。通过将其红色、绿色和蓝色分量设置为具有相同亮度而创建的灰色像素。所以,color_rgb(0, 0, 0) 是黑色,color_rgb(255, 255, 255) 是白色,color_rgb(127, 127, 127) 是介于两者之间的灰色“中间”。您应该使用原始 rgb 值的加权平均值来确定灰色的亮度。这是灰度算法的伪代码[由于某种原因,四空格缩进在预览中不起作用]:

for each row in the image:  
    for each column in the image:  
        r, g, b = get pixel information for current row and column  
        brightness = int(round(0.299r + 0.587g + 0.114b))  
    update the image # to see progress row by row

注意:Image 类中的像素操作相当慢,因此您需要使用相对较小的图像(不是 12 兆像素)来测试您的程序。


我已经为此工作了好几个小时。这是我的代码的最新版本:

# grayscale.py

from graphics import *

def main():  
    infileName = input("File name: ")  
    outfileName = input("Save to: ")

    image = Image(Point(100,100), infileName)
    width = image.getWidth()
    height = image.getHeight()
    win = GraphWin("rgb")
    image.draw(win)

    row = 0
    column = 0

    win.getMouse()

    for row in range(200):
        for column in range(200):
            r, g, b = image.getPixel(row, column)
            brightness = int(round(0.299 * r + 0.587 * g + 0.114 * b))
            image.setPixel(row, column, color_rgb(brightness, brightness, brightness))
            win.update()

    win.getMouse()
    win.close()

main()

我终于明白了,所以 Python 没有给我任何错误消息。但程序所做的只是加载图像,单击几下鼠标,然后关闭。我一直将输入文件输入为 U:\My Pictures\yay.gif,并将输出文件输入为 U:\My Pictures\yay2.gif。但我刚刚搜索了我的电脑,U:\My Pictures\yay2.gif 不存在。我究竟做错了什么?顺便说一句,这不适合上课——我没有老师可以问。

也许我应该在帖子中跟进。我添加了保存功能,但我得到了一个带有 200x200 灰度框的图像,其余部分是彩色的。所以,这里有一些我改变的行:

win = GraphWin("rgb", width, height)
for row in range(height):
    for column in range(width):

我收到以下错误消息: 回溯(最近一次通话最后一次):
文件“C:\Python31\grayscale.py”,第 31 行,在
主()
文件“C:\Python31\grayscale.py”,第 22 行,在 main
r, g, b = image.getPixel(行, 列)
文件“C:\Python31\lib\graphics.py”,第 810 行,在 getPixel
值 = self.img.get(x,y)
文件“C:\Python31\lib\tkinter_init_.py”,第 3301 行,在 get
return self.tk.call(self.name, 'get', x, y)
_tkinter.TclError: pyimage1 get: 坐标超出范围

我了解我可能需要将图像的锚点更改为中心。但我只能通过图像的宽度和高度来确定,而且我必须先上传图像才能获得这些值。有解决办法吗?

【问题讨论】:

    标签: python graphics python-3.x iteration grayscale


    【解决方案1】:

    您没有保存图像。请注意,变量 outfileName 从未使用过。您应该将其传递给某种保存功能。快速浏览了graphics.py,我认为这就是你所需要的:

    编辑

    要解决仅转换一个角的问题,请改为执行此操作,您的旧代码仅转换前 200x200 像素。我还将范围更改为 xrange,没有必要但更有效。

    for row in xrange(height):
            for column in xrange(windth):
    

    【讨论】:

    • 谢谢。我试过了——我把一张新图像保存在它应该在的地方,但是角落里唯一一个 200x200 的框被转换为灰度。因此,我将第二块中的第四行更改为 win = GraphWin("rgb", width, height) 并将 for 循环中的范围分别更改为高度和宽度。我收到了这个错误:
    • Traceback(最近一次调用最后):文件“C:\Python31\grayscale.py”,第 31 行,在 main() 文件“C:\Python31\grayscale.py”中,第 22 行,在 main r, g, b = image.getPixel(row, column) 文件“C:\Python31\lib\graphics.py”,第 810 行,在 getPixel value = self.img.get(x,y)文件“C:\Python31\lib\tkinter_init_.py”,第 3301 行,在 get return self.tk.call(self.name, 'get', x, y) _tkinter.TclError 中: pyimage1 得到:坐标超出范围
    • @user460847,已更新以解决 200x200 框的问题。
    • 在 Python 3 中,range 是一个类似于 Python 2 中的 xrange 的迭代器......因此无需更改它。事实上,我认为 xrange 在 Python 3 中已被删除,因此使用 range 更便携。此外,它并不总是最有效的使用方法。见Should you always favor xrange() over range()?
    • 我将两个范围都更改为 xrange 并收到错误消息(未定义全局名称)。另外,你还有什么建议吗?您说“改为执行此操作”以解决 200x200 问题,但随后您没有说该怎么做。也许它只是没有出现在您的评论中?
    【解决方案2】:

    我知道这是一篇旧帖子,但是。我认为您的问题是您使用的实际图像。将图像分辨率更改为每英寸 200 像素。

    【讨论】:

    • 还要确保保存图像,如:newImg= image.save(outfileName)
    【解决方案3】:

    最好保持简单。程序要求保存最后忘记的文件,并使用 getMouse() 获取您使用 getX() 和 getY() 的“当前像素”。这是使用 graphics.py 的更好示例

    灰度.py

    from graphics import*
    
    print("This program grayscales images\n")# intro 
    
    def grayscale(): # Obtaining file
        infile = input('In what file is the image?: ')
        outfile = input('What file do you want it saved?: ')
    
    #   Using image file to get dynamics of window. You don't have to create a window either to obtain it. 
    
        file = Image(Point(0,0), infile)
        width = file.getWidth()
        height = file.getHeight()
    
    #   Getting center point of photo
        cWidth = width / 2
        cHeight = height / 2
        cen = Point(cWidth, cHeight)
    
    #   Ready for window
        image = Image(cen,infile)
        win = GraphWin("Grayscale Image", width, height)
        image.draw(win)
    
    
    #   Getting current Pixel for loop
        p = win.getMouse()
        x = p.getX()
        y = p.getY()
    
        for x in range(height):
            for y in range(width):
                r, g, b = image.getPixel(x, y)
                gray = int(round(.299*r + .587*g + .114*b))
                image.setPixel(x,y, color_rgb(gray, gray, gray))
            # i accidentally mixed my x and y variable and it spit
            # out a two-headed cyclops tee hee 
                win.update()
            
    # Click to exit 
        image.save(outfile)
        win.getMouse()
        win.close()
    
    grayscale()
    

    【讨论】:

    • 非常感谢!你的回答拯救了我一整天
    【解决方案4】:

    outfileName 设置后我看不到它有任何用途——换句话说,您似乎永远不会保存结果到该文件(或任何其他文件,为此问题)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-06
      • 1970-01-01
      • 2018-03-29
      • 2010-11-20
      相关资源
      最近更新 更多