在高中时,我们开始使用Python,并要求我们使用Pillow
模块对小型图像处理器进行编程。目标是打开一个文件,然后选择一个过滤器。
我尝试编程的第一个滤镜是更改色温。 但是tkinter还有一个极简主义的界面,它显示了一些按钮,并且可以正常工作。
这是打开文件的功能
def Ouvrir():
fichier = askopenfilename(title="Ouvrir une image",filetypes=[('jpg files','.jpg'),('all files','.*')])
global img
img =Image.open(fichier)
l, h = img.size
img.show() #visualisation de l'image
global img2
img2 = img #img2 est une copie de img
它将创建一个从文件中加载的全局img
图像对象。然后l
和h
会加载图像的宽度和高度。
为输出图像创建了另一个全局对象图像img2
,它是img
的副本。
然后是处理图像的功能
def filtreTC(): #Filtre permettant de changer la température de couleur
coef = sliderTC.get() / 100 #On récupère le coefficient à partir de l'échelle. Le coefficient compris entre -1 et 1: -1 = froid (image bleu-vert), 0 = neutre, 1 = chaud (image orangée)
fenTC.destroy() #On ferme la fenêtre
if(coef <= 0): #Calcul des coefficients rouges, verte et bleus
coefR = 1 + coef
coefV = 1 + (coef / 2)
coefB = 1
else:
coefR = 1
coefV = 1 - (coef / 2)
coefB = 1 - coef
for y in range(0, h, 1):
for x in range(0, l, 1):
r, v, b = img.getpixel((x, y))
r = int(float(r * coefR))
v = int(float(v * coefV))
b = int(float(b * coefB))
img2.putpixel((x, y), (r, v, b))
img2.show()
这是一个循环扫描整个图像并从img
提取一个像素,将其rgb值乘以其相应系数的循环,然后将该像素放入img2
问题是它不起作用。它没有给出任何错误,但是当它显示img2
时,它与img1
相同,就像putpixel
函数没有执行任何操作一样。
我检查了很多事情,所以我知道问题既不是rgb值也不是x / y坐标。
img2 = img
代替img2 = Image.new("RGB", (l, h))
,但得到的是黑色图像。img2.putpixel((x, y), (r, v, b))
替换为img2.putpixel((100, 100), (127, 127, 127))
,这样我应该在左上角附近得到一个灰色像素。但是我仍然有黑色图像。然后我尝试删除
global img2
img2 = img
从打开文件并放入文件的功能
img2 = Image.new("RGB", (l, h))
在fenTC.destroy()
之后,我得到了:
Exception in Tkinter callback
Traceback (most recent call last):
File "e:\xxxx\programmes\anaconda\lib\tkinter\__init__.py", line 1702, in __call__
return self.func(*args)
File "H:\ISN\Programmes\TP-image\projet.py", line 62, in filtreTC
img2.show()
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\Image.py", line 2016, in show
_show(self, title=title, command=command)
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\Image.py", line 2876, in _show
_showxv(image, **options)
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\Image.py", line 2881, in _showxv
ImageShow.show(image, title, **options)
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\ImageShow.py", line 51, in show
if viewer.show(image, title=title, **options):
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\ImageShow.py", line 75, in show
return self.show_image(image, **options)
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\ImageShow.py", line 95, in show_image
return self.show_file(self.save_image(image), **options)
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\ImageShow.py", line 91, in save_image
return image._dump(format=self.get_format(image), **self.options)
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\Image.py", line 639, in _dump
self.save(filename, format, **options)
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\Image.py", line 1969, in save
save_handler(self, fp, filename)
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\BmpImagePlugin.py", line 319, in _save
(rawmode, stride, -1))])
File "e:\xxxx\programmes\anaconda\lib\site-packages\PIL\ImageFile.py", line 512, in _save
e.setimage(im.im, b)
SystemError: tile cannot extend outside image
基本上,除了以下内容之外,我不知道这是什么意思
:SystemError: tile cannot extend outside image
我检查了x和y坐标,它们从未越过边界,所以我不明白这是什么错误。
我花了几个小时尝试找出问题所在,并尝试了许多不同的方法,但没有一个起作用。所以我认为最好寻求帮助
答案 0 :(得分:2)
您的问题是您没有创建副本。 img2 = img
创建对同一对象的另一个引用,而不是新的单独图像。
要创建实际副本,请使用image.copy()
method:
img2 = img.copy()
接下来,我将不使用循环和getpixel()
/ putpixel()
组合。您正在为出现多次的RGB值做双重工作。如果使用image.point()
方法,则可以对图像中每个波段中的每个唯一值使用公式,并将循环遍历所有像素到库中(快得多)。它还可以为您复制图像!
您需要创建一个表;对于R,G和B值从0到255的值,计算可能的结果,并将这3 * 256个结果放入长列表中:
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
img2 = img1.point(coefR + coefG + coefB)
结果表用于图像中的每个唯一颜色值。
您还可以将RGB图像分成单独的波段,将不同的系数公式作为函数应用到每个单独的波段,然后将波段重新组合为新图像:
r, g, b = img.split()
g = g.point(lambda i: i * (1 - (coef / 2)))
if coef <= 0:
r = r.point(lambda i: i * (1 + coef))
else:
b = b.point(lambda i: i * (1 - coef))
img = Image.merge('RGB', (r, g, b))
在创建图像滤镜时,您确实希望将输入图像作为函数参数传递,而不是使用全局变量。还要传递系数:
def filtreTC(source_image, coef):
coefG = [i * (1 - (coef / 2)) for i in range(256)]
if coef <= 0:
coefR = [i * (1 + coef) for i in range(256)]
coefB = list(range(256))
else:
coefR = list(range(256))
coefB = [i * (1 - coef) for i in range(256)]
return source_image.point(coefR + coefG + coefB)
然后,可以根据需要将调用结果存储在全局变量中,但是该函数现在可以独立运行,并且可以在具有RGB PIL图像对象的任何地方重新使用。您可以使用滑块值调用该函数:
coef = sliderTC.get() / 100
fenTC.destroy()
img2 = filtreTC(img, coef)
在个人资料图片中使用以上内容
系数为0.75,可以得到:
-0.75会导致: