简体   繁体   中英

Python 3: Converting image to grayscale

I'm trying to do an exercise in John Zelle's "Python Programming: An Introduction to Computer Science". I downloaded a special graphics package for his book ( graphics.py , which is on the linked website). The question reads as follows:

Write a program that converts a color image to grayscale. The user supplies the name of a file containing a GIF or PPM image, and the program loads the image and displays the file. At the click of the mouse, the program converts the image to grayscale. The user is then prompted for a filename to store the grayscale image in.

You will probably want to go back and review the Image object from the graphics library (Section 4.8.4). The basic idea for converting the image is to go through it pixel by pixel and convert each one from color to an appropriate shade of gray. A gray pixel created by setting its red, green, and blue components to have the same brightness. So, color_rgb(0, 0, 0) is black, color_rgb(255, 255, 255) is white, and color_rgb(127, 127, 127) is a gray "halfway" in between. You should use a weighted average of the original rgb values to determine the brightness of the gray. Here is the pseudocode for the grayscale algorithm [for some reason the four-space indent is not working on preview]:

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

Note: the pixel operations in the Image class are rather slow, so you will want to use relatively small images ( not 12 megapixels) to test your program.


I've been working on this for hours. This is the latest version of my code:

# 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()

I finally got it so Python's not giving me any error messages. But all the program does is load the image, take a couple of mouse clicks, and then close. I've been entering the input file as U:\\My Pictures\\yay.gif, and the output file as U:\\My Pictures\\yay2.gif. But I just searched my computer and U:\\My Pictures\\yay2.gif doesn't exist. What am I doing wrong? This is NOT for a class by the way--there's no instructor for me to ask.

Maybe I should follow up in the post instead. I added the save function, but I got an image with a 200x200 grayscale box and the rest of it in color. So, here are some lines I changed:

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

And I get the following error message: Traceback (most recent call last):
File "C:\\Python31\\grayscale.py", line 31, in
main()
File "C:\\Python31\\grayscale.py", line 22, in main
r, g, b = image.getPixel(row, column)
File "C:\\Python31\\lib\\graphics.py", line 810, in getPixel
value = self.img.get(x,y)
File "C:\\Python31\\lib\\tkinter_ init _.py", line 3301, in get
return self.tk.call(self.name, 'get', x, y)
_tkinter.TclError: pyimage1 get: coordinates out of range

I understand that I probably need to change the anchor point of the image to the center. But I can only determine that by the image's width and height, and I have to have uploaded the image first to get those values. Is there a workaround?

You aren't saving the image. Notice that the variable outfileName is never used. You should be passing it to some sort of save function. took a quick look at graphics.py, I think this is what you need:

EDIT

To solve the issue with it only converting one corner, do this instead, your old code was only converting the first 200x200 pixels. I also changed range to xrange, not necessary but more efficient.

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

I know this is an old post but. I think your problem is the actual image you are using. Change the image resolution to 200 pixels per inch.

在设置之后我没有看到outfileName任何使用 - 换句话说,你似乎永远不会结果保存到该文件(或任何其他文件)。

Best to keep it simple. The program asks to save the file, which was forgotten at the end, and to use getMouse() to obtain the "current pixel" which you use getX() and getY(). Here is a better sample using graphics.py

grayscale.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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM