Getting list of pixel values from PIL

前端 未结 9 1072
感动是毒
感动是毒 2020-11-27 15:07

Guys, I\'m looking for a bit of assistance. I\'m a newbie programmer and one of the problems I\'m having at the minute is trying to convert a black & white .jpg

相关标签:
9条回答
  • 2020-11-27 15:42

    If you have numpy installed you can try:

    data = numpy.asarray(im)
    

    (I say "try" here, because it's unclear why getdata() isn't working for you, and I don't know whether asarray uses getdata, but it's worth a test.)

    0 讨论(0)
  • 2020-11-27 15:46

    Python shouldn't crash when you call getdata(). The image might be corrupted or there is something wrong with your PIL installation. Try it with another image or post the image you are using.

    This should break down the image the way you want:

    from PIL import Image
    im = Image.open('um_000000.png')
    
    pixels = list(im.getdata())
    width, height = im.size
    pixels = [pixels[i * width:(i + 1) * width] for i in xrange(height)]
    
    0 讨论(0)
  • 2020-11-27 15:51

    I assume you are getting an error like.. TypeError: 'PixelAccess' object is not iterable...?

    See the Image.load documentation for how to access pixels..

    Basically, to get the list of pixels in an image, using PIL:

    from PIL import Image
    i = Image.open("myfile.png")
    
    pixels = i.load() # this is not a list, nor is it list()'able
    width, height = i.size
    
    all_pixels = []
    for x in range(width):
        for y in range(height):
            cpixel = pixels[x, y]
            all_pixels.append(cpixel)
    

    That appends every pixel to the all_pixels - if the file is an RGB image (even if it only contains a black-and-white image) these will be a tuple, for example:

    (255, 255, 255)
    

    To convert the image to monochrome, you just average the three values - so, the last three lines of code would become..

    cpixel = pixels[x, y]
    bw_value = int(round(sum(cpixel) / float(len(cpixel))))
    # the above could probably be bw_value = sum(cpixel)/len(cpixel)
    all_pixels.append(bw_value)
    

    Or to get the luminance (weighted average):

    cpixel = pixels[x, y]
    luma = (0.3 * cpixel[0]) + (0.59 * cpixel[1]) + (0.11 * cpixel[2])
    all_pixels.append(luma)
    

    Or pure 1-bit looking black and white:

    cpixel = pixels[x, y]
    if round(sum(cpixel)) / float(len(cpixel)) > 127:
        all_pixels.append(255)
    else:
        all_pixels.append(0)
    

    There is probably methods within PIL to do such RGB -> BW conversions quicker, but this works, and isn't particularly slow.

    If you only want to perform calculations on each row, you could skip adding all the pixels to an intermediate list.. For example, to calculate the average value of each row:

    from PIL import Image
    i = Image.open("myfile.png")
    
    pixels = i.load() # this is not a list
    width, height = i.size
    row_averages = []
    for y in range(height):
        cur_row_ttl = 0
        for x in range(width):
            cur_pixel = pixels[x, y]
            cur_pixel_mono = sum(cur_pixel) / len(cur_pixel)
            cur_row_ttl += cur_pixel_mono
    
        cur_row_avg = cur_row_ttl / width
        row_averages.append(cur_row_avg)
    
    print "Brighest row:",
    print max(row_averages)
    
    0 讨论(0)
  • 2020-11-27 15:55
    pixVals = list(pilImg.getdata())
    

    output is a list of all RGB values from the picture:

    [(248, 246, 247), (246, 248, 247), (244, 248, 247), (244, 248, 247), (246, 248, 247), (248, 246, 247), (250, 246, 247), (251, 245, 247), (253, 244, 247), (254, 243, 247)]
    
    0 讨论(0)
  • 2020-11-27 15:56
    data = numpy.asarray(im)
    

    Notice:In PIL, img is RGBA. In cv2, img is BGRA.

    My robust solution:

    def cv_from_pil_img(pil_img):
        assert pil_img.mode=="RGBA"
        return cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGBA2BGRA)
    
    0 讨论(0)
  • 2020-11-27 15:58

    Not PIL, but scipy.misc.imread might still be interesting:

    import scipy.misc
    im = scipy.misc.imread('um_000000.png', flatten=False, mode='RGB')
    print(im.shape)
    

    gives

    (480, 640, 3)
    

    so it is (height, width, channels). So you can iterate over it by

    for y in range(im.shape[0]):
        for x in range(im.shape[1]):
            color = tuple(im[y][x])
            r, g, b = color
    
    0 讨论(0)
提交回复
热议问题