запуск 2 эквивалентных частей кода Python 3.7.6 с использованием библиотеки PIL в блокноте Jupyter, НО получение разных результатов - PullRequest
0 голосов
/ 19 февраля 2020

Я запускаю 2 Python 3.7.6 скриптов, которые полагаются на библиотеку PIL в записной книжке Jupyter и получают разные результаты, и я не могу определить, почему. Я считаю, что две части должны быть эквивалентны, а результат идентичен. Может кто-нибудь сказать мне, почему второй блок не генерирует тот же вывод, что и первый?

По сути, код должен делать то же самое, разбивать изображение на его цветовые каналы RGB, умножать каждый канал на один из 3 различных интенсивности, а затем объединить каналы обратно в составное изображение. Вот исходное изображение:

original image

Единственная разница между двумя кодовыми блоками состоит в том, что в одном я делаю разбиение внутри самого внутреннего для l oop а в другом я делаю разбиение вне циклов for, копирую результат в переменную и затем присваиваю копию внутри самого l oop.

В первом разделе я вызываю функцию разбиения изображения в самом внутреннем l oop в первом сегменте и назначьте его переменной кортежа изображения:

img_tmp = image.split()

во втором, я называю это вне внешнего l oop и назначьте его переменной кортежа изображения, а затем назначьте эту переменную второй переменной внутри самой внутренней l oop, чтобы сбросить значение каждый раз до конца.

source = image.split()
...
for ...:
    for ...:
        img_tmp = source

1-й кодовый блок (работает правильно):

import PIL
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

# read image and convert to RGB
image=Image.open("readonly/msi_recruitment.gif")
image=image.convert('RGB')

# read True Type font
fnt=ImageFont.truetype("readonly/fanwood-webfont.ttf", size=50)

# source = image.split()

# initialize key constants and variables
R,G,B = 0,1,2
intensity = [0.1, 0.5, 0.9]
images = []
images_meta = []
banner_height = 70
banner_margin = 10
txt_color = 'rgb(255,255,255)' # white

# build a list of 9 images, 3 for each color channel with the appropriate color intensity
for channel in [R,G,B]:

    # multiply each channel by appropriate color intensity factor
    for i_factor in intensity:
#       img_tmp = source # split the original image into 3 separate channels (images) with 1 for each color
        img_tmp = image.split()
        img_band = img_tmp[channel].point(lambda x: x*i_factor) # multiply the channel color by the intensity factor
        img_tmp[channel].paste(img_band) # replace the selected channel image with its color corrected version
        img_out = Image.merge(image.mode, img_tmp) #  merge all 3 channels back into one image
        images.append(img_out)  # add the updated image to the list
        images_meta.append('channel {} intensity {}'.format(channel, i_factor))  # update the metadata

# create a contact sheet of 3 rows with one row per color channel displaying 
# an image with 3 different color intensities

first_image=images[0]
contact_sheet=PIL.Image.new(first_image.mode, (first_image.width*3,first_image.height*3 + banner_height*3))
x=0
y=0

# initialize the drawing context with the contact sheet as background
banner = ImageDraw.Draw(contact_sheet)

for i,img in enumerate(images):

    # Lets paste the current image into the contact sheet
    contact_sheet.paste(img, (x, y) )

    # now draw the text and create a banner below the corresponding image
    banner.text((x, y + first_image.height + banner_margin), images_meta[i], font=fnt, fill=txt_color)

    # Now we update our X position. If it is going to be the width of the image, then we set it to 0
    # and update Y as well to point to the next "line" of the contact sheet.
    if x+first_image.width == contact_sheet.width:
        x=0
        y=y+first_image.height + banner_height
    else:
        x=x+first_image.width

# resize and display the contact sheet
contact_sheet = contact_sheet.resize((int(contact_sheet.width/2),int(contact_sheet.height/2) ))
display(contact_sheet)

contact_sheet.save('assignment_1.pdf')

результирующее изображение:

image processed correctly


2-й кодовый блок (запускается, но не обрабатывает изображение правильно):

import PIL
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

# read image and convert to RGB
image=Image.open("readonly/msi_recruitment.gif")
image=image.convert('RGB')

# read True Type font
fnt=ImageFont.truetype("readonly/fanwood-webfont.ttf", size=50)

source = image.split()

# initialize key constants and variables
R,G,B = 0,1,2
intensity = [0.1, 0.5, 0.9]
images = []
images_meta = []
banner_height = 70
banner_margin = 10
txt_color = 'rgb(255,255,255)' # white

# build a list of 9 images, 3 for each color channel with the appropriate color intensity
for channel in [R,G,B]:

    # multiply each channel by appropriate color intensity factor
    for i_factor in intensity:
        img_tmp = source # split the original image into 3 separate channels (images) with 1 for each color
        img_band = img_tmp[channel].point(lambda x: x*i_factor) # multiply the channel color by the intensity factor
        img_tmp[channel].paste(img_band) # replace the selected channel image with its color corrected version
        img_out = Image.merge(image.mode, img_tmp) #  merge all 3 channels back into one image
        images.append(img_out)  # add the updated image to the list
        images_meta.append('channel {} intensity {}'.format(channel, i_factor))  # update the metadata

# create a contact sheet of 3 rows with one row per color channel displaying 
# an image with 3 different color intensities

first_image=images[0]
contact_sheet=PIL.Image.new(first_image.mode, (first_image.width*3,first_image.height*3 + banner_height*3))
x=0
y=0

# initialize the drawing context with the contact sheet as background
banner = ImageDraw.Draw(contact_sheet)

for i,img in enumerate(images):

    # Lets paste the current image into the contact sheet
    contact_sheet.paste(img, (x, y) )

    # now draw the text and create a banner below the corresponding image
    banner.text((x, y + first_image.height + banner_margin), images_meta[i], font=fnt, fill=txt_color)

    # Now we update our X position. If it is going to be the width of the image, then we set it to 0
    # and update Y as well to point to the next "line" of the contact sheet.
    if x+first_image.width == contact_sheet.width:
        x=0
        y=y+first_image.height + banner_height
    else:
        x=x+first_image.width

# resize and display the contact sheet
contact_sheet = contact_sheet.resize((int(contact_sheet.width/2),int(contact_sheet.height/2) ))
display(contact_sheet)

contact_sheet.save('assignment_1.pdf')```

image not processing correctly

1 Ответ

0 голосов
/ 19 февраля 2020

Brifly: Python не дублирует список / кортеж при назначении новой переменной.


Во второй версии, когда вы присваиваете

 img_tmp = source 

, тогда Pythond не ' создать копию данных, но только псевдоним для оригинала. Поэтому, когда вы изменяете img_tmp, вы также изменяете source, и в следующем l oop вы работаете с измененной версией, а не с оригинальной.

Вам нужно

 import copy

 img_tmp = copy.deepcopy(source) 

или (потому что это кортеж с 3 массивами)

 img_tmp = (source[0].copy(), source[1].copy(), source[2].copy())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...