Error wanting to convert an int to a tuple in python

0
def negativo_grises(im):
    tiempoIn = time.time()
    ruta = ("C:/Users/HardSoft/Desktop/Imagenes/" +im)
    im = Image.open(ruta)
    im.show()
    im6 = im
    i = 0
    while i < im6.size[0]:
        j = 0
        while j < im6.size[1]:
            gris = im6.getpixel((i,j))
            valor = 255 - gris
            im6.putpixel((i,j), valor)
            j+=1
        i+=1
    im6.show()
    tiempoFin = time.time()
    print('El proceso tardo: ', tiempoFin - tiempoIn, 'segundos')

    
asked by Jonh Kennedy 15.04.2018 в 04:42
source

1 answer

1

If your image does not have each pixel defined by a single value ( modes l o L ) Image.getpixel will return a tuple with the value of each channel, for example (100, 100 ,125, 255) in RGBA (values of each channel). The same goes for RGB , CMYK , YCbCr , LAB or HSV .

Taking into account the above, you can not subtract a tuple from an integer as the error says. You have several options depending on what you are looking for, an option that will work for you but that is a bit brute force is to convert the image to L or l mode directly:

imgray = img.convert('L')

Three important observations:

  • Using a while is little "python" and is also considerably more inefficient than a for to iterate over the image.

  • When you make im6 = im you are not creating a copy of the image , you simply assign the im6 identifier to the object reference pointed to by im . Both identifiers point to the same object in memory (to the same image). This implies that when you modify im6 with putpixel it also modifies im (in fact both are the same). To make a copy do im6 = im.copy()

  • To invert the image, the shape you use is not the most efficient ( putpixel is usually not). For example ImageChops.invert does this same thing:

    from PIL import Image, ImageChops
    
    im = Image.open(ruta)
    ImageChops.invert(img.convert('L')).show()
    

Your code could look like this:

import time
import os
from PIL import Image, ImageChops



def negativo_grises(im):
    tiempoIn = time.time()
    ruta = os.path.join("D:\Reproductor", im)
    img = Image.open(ruta)
    print(img.mode)
    imgray = img.convert('L')

    for i in range(imgray.size[0]):    
        for j in range(imgray.size[1]):
            imgray.putpixel((i,j), 255 - imgray.getpixel((i,j)))

    print('El proceso tardo: {} segundos.'.format(time.time() - tiempoIn))

    img.show()
    imgray.show()

negativo_grises("ejemplo.png")

If you want to apply the same transformation to each channel of an RGB image, for example, you could do:

pixel = tuple(255 - ch for ch in imgray.getpixel((i,j)))
imgray.putpixel((i,j), pixel)

If you are going to work intensively with the pixels of the image it may be better to pass it to a NumPy array and vectorize the operations as much as possible.

    
answered by 15.04.2018 в 06:34