如何使用 Python 上的数据帧信息通过循环合并多个图像?
How can I merge several images via loop using the information of a dataframe on Python?
我有以下词典:
the_dictionary_list = {'Fondo': ['Oceano.png'],
'Cuerpo': ['Cuerpo_cangrejo.png'],
'Ojos': ['Antenas.png', 'Pico.png', 'Verticales.png'],
'Color': ['Amarillo.png', 'Blanco.png', 'Rojirosado.png', 'Turquesa.png', 'Verde_oscuro.png', 'Zapote.png'],
'Pinzas': ['None', 'Pinzitas.png', 'Pinzotas.png', 'Pinzota_pinzita.png'],
'Puas': ['None', 'Arena.png', 'Marron.png', 'Purpura.png', 'Verde.png']}
为了获得每个可能的排列而不按特定顺序重复(即笛卡尔积),我使用以下代码:
import itertools as it
AllKeysNames = ['Fondo', 'Cuerpo', 'Ojos', 'Color', 'Pinzas', 'Puas']
Combinations = list(it.product(*(the_dictionary_list[Name] for Name in AllKeysNames)))
print(f'{Combinations}')
然后,为了将每次迭代保存到数据帧中,它会抛出如下输出:
| Permutations | FilePermutations |
0|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+None+None |
1|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+None+Arena.png |
2|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+None+Marron.png |
3|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+None+Purpura.png |
4|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+None+Verde.png |
5|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+Pinzitas.png+None |
6|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+Pinzitas.png+Arena.png |
7|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+Pinzitas.png+Marron.png |
8|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+Pinzitas.png+Purpura.png |
9|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+Pinzitas.png+Verde.png |
.
.
.
358|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Verticales.png+Zapote.png+Pinzota_pinzita.png+Purpura.png |
359|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Verticales.png+Zapote.png+Pinzota_pinzita.png+Verde.png |
我使用以下代码:
new = ['+'.join(x) for x in
it.product(*(the_dictionary_list[Name] for Name in AllKeysNames))]
df = pd.DataFrame({'Permutations':"+".join(AllKeysNames), 'FilePermutations':new})
现在,假设上述程序位于同一路径(即r"./"
),巧合以下文件夹也位于其中:
这些文件夹只包含文件图像,巧合的是与the_dictionary_list
中的那些值同名。
由于 df
变量存储了正确的顺序,除了文件名和文件夹名之外,还必须合并这些图像,以及排列的总数
这个程序如何从 df
中获取信息并使用以下函数:
Image.open(r"./")
Image.alpha_composite()
resize((350, 350), resample=Image.NEAREST
来自 Python Imaging Library (PIL)
要按照 df
显示的顺序生成新的合并图像?
备注:
The image filenames can be equal to the respective index of df
.
As the None
element doesn't actually exist in the folders, when needed, the program would have to merge the previous images with the next one (i.e. not calling Image.open(r"./")
nor Image.alpha_composite()
when 'None
' appears and continue to do so with the next element)
Only after having merged the file images of a row, it would call resize((350, 350), resample=Image.NEAREST
for then saving the final output using .save(r"./Test/str(Index(i))+".png")
and then repeat the process until it has reached the final index of df
以下解决方案由 @christian 从 Whosebug en español 构建,他的答案翻译如下:
Pandas DataFrames have a method called iterrorws() that returns a
generator and we can iterate through it, this returns the row
itself as a tuple that contains two objects, the first one is the index of
the row and the second one is a Pandas Series that contains the values
of the next columns.
I would not recommend joining the names with a +
, you can simply leave
them in list format since later we will need them as lists again and
you can save that conversion to a list by avoiding using '+'.join(x)
.
for i, per in df.iterrows():
images = per["FilePermutations"].split("+")
files = per["Permutations"].split("+")
With this we are obtaining the value of the respective column and we
convert it back to a list with the help of the split
method. Once we
have this we can move on to create the new image that is the result of
joining all the images specified in the images
list. For this, we must
first know the directory of each image and "coincidentally" the first
element of files
list is the directory where the image of the
first element of the images
list is located, and so on for each of the
images. It happened to use the zip()
function that matches each of
those elements (in case a list has fewer elements, it will only match
up to the smallest list and will not include the others, in case there
is that scenario you can use the zip_longest
function from itertools
module) . With that we would already have the path
of the image, we
would only have to open it, combine it and at the end of all resize it
and save it.
for i, per in df.iterrows():
images = per["FilePermutations"].split("+")
files = per["Permutations"].split("+")
result_image = None #aquí se almacenará la imagen resultante
for direc, img in zip(files, images): #iteramos
if img=="None": continue #si es None omitimos
path = f"{direc}/{img}" #definimos la ruta donde se encuentra la imagen
#en la primera iteración no habrá imagen inicial por lo que no podrá combinarse con otra
# por lo que asignamos la imagen
if result_image == None:
result_image = Image.open(f"./{path}")
else: #combinamos la imagen
img2 = Image.open(f"./{path}")
result_image = Image.alpha_composite(result_image, img2)
# redimensionamos y guardamos
result_image = result_image.resize((350, 350), resample=Image.NEAREST)
result_image.save(f"./Test/image_{i}.png")
This will combine all the specified images in each row and save them
to the specified path. As you have seen there is not much magic in
this, just a couple of for
loops, the first to iterate through the
rows and the second to create the path
and get the images. In each
iteration of the second for
the result of result_image
is overwritten
so that it always contains the result of the combination of the
current image and the previous one, in this way all the images are
mixed, obviously those that do not exist marked as 'None'
are omitted
这非常好地回答了我的问题。
我有以下词典:
the_dictionary_list = {'Fondo': ['Oceano.png'],
'Cuerpo': ['Cuerpo_cangrejo.png'],
'Ojos': ['Antenas.png', 'Pico.png', 'Verticales.png'],
'Color': ['Amarillo.png', 'Blanco.png', 'Rojirosado.png', 'Turquesa.png', 'Verde_oscuro.png', 'Zapote.png'],
'Pinzas': ['None', 'Pinzitas.png', 'Pinzotas.png', 'Pinzota_pinzita.png'],
'Puas': ['None', 'Arena.png', 'Marron.png', 'Purpura.png', 'Verde.png']}
为了获得每个可能的排列而不按特定顺序重复(即笛卡尔积),我使用以下代码:
import itertools as it
AllKeysNames = ['Fondo', 'Cuerpo', 'Ojos', 'Color', 'Pinzas', 'Puas']
Combinations = list(it.product(*(the_dictionary_list[Name] for Name in AllKeysNames)))
print(f'{Combinations}')
然后,为了将每次迭代保存到数据帧中,它会抛出如下输出:
| Permutations | FilePermutations |
0|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+None+None |
1|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+None+Arena.png |
2|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+None+Marron.png |
3|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+None+Purpura.png |
4|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+None+Verde.png |
5|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+Pinzitas.png+None |
6|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+Pinzitas.png+Arena.png |
7|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+Pinzitas.png+Marron.png |
8|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+Pinzitas.png+Purpura.png |
9|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Antenas.png+Amarillo.png+Pinzitas.png+Verde.png |
.
.
.
358|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Verticales.png+Zapote.png+Pinzota_pinzita.png+Purpura.png |
359|Fondo+Cuerpo+Ojos+Color+Pinzas+Puas |Oceano.png+Cuerpo_cangrejo.png+Verticales.png+Zapote.png+Pinzota_pinzita.png+Verde.png |
我使用以下代码:
new = ['+'.join(x) for x in
it.product(*(the_dictionary_list[Name] for Name in AllKeysNames))]
df = pd.DataFrame({'Permutations':"+".join(AllKeysNames), 'FilePermutations':new})
现在,假设上述程序位于同一路径(即r"./"
),巧合以下文件夹也位于其中:
这些文件夹只包含文件图像,巧合的是与the_dictionary_list
中的那些值同名。
由于 df
变量存储了正确的顺序,除了文件名和文件夹名之外,还必须合并这些图像,以及排列的总数
这个程序如何从 df
中获取信息并使用以下函数:
Image.open(r"./")
Image.alpha_composite()
resize((350, 350), resample=Image.NEAREST
来自 Python Imaging Library (PIL)
要按照 df
显示的顺序生成新的合并图像?
备注:
The image filenames can be equal to the respective index of
df
.As the
None
element doesn't actually exist in the folders, when needed, the program would have to merge the previous images with the next one (i.e. not callingImage.open(r"./")
norImage.alpha_composite()
when 'None
' appears and continue to do so with the next element)Only after having merged the file images of a row, it would call
resize((350, 350), resample=Image.NEAREST
for then saving the final output using.save(r"./Test/str(Index(i))+".png")
and then repeat the process until it has reached the final index ofdf
以下解决方案由 @christian 从 Whosebug en español 构建,他的答案翻译如下:
Pandas DataFrames have a method called iterrorws() that returns a generator and we can iterate through it, this returns the row itself as a tuple that contains two objects, the first one is the index of the row and the second one is a Pandas Series that contains the values of the next columns.
I would not recommend joining the names with a
+
, you can simply leave them in list format since later we will need them as lists again and you can save that conversion to a list by avoiding using'+'.join(x)
.
for i, per in df.iterrows():
images = per["FilePermutations"].split("+")
files = per["Permutations"].split("+")
With this we are obtaining the value of the respective column and we convert it back to a list with the help of the
split
method. Once we have this we can move on to create the new image that is the result of joining all the images specified in theimages
list. For this, we must first know the directory of each image and "coincidentally" the first element offiles
list is the directory where the image of the first element of theimages
list is located, and so on for each of the images. It happened to use thezip()
function that matches each of those elements (in case a list has fewer elements, it will only match up to the smallest list and will not include the others, in case there is that scenario you can use thezip_longest
function fromitertools
module) . With that we would already have thepath
of the image, we would only have to open it, combine it and at the end of all resize it and save it.
for i, per in df.iterrows():
images = per["FilePermutations"].split("+")
files = per["Permutations"].split("+")
result_image = None #aquí se almacenará la imagen resultante
for direc, img in zip(files, images): #iteramos
if img=="None": continue #si es None omitimos
path = f"{direc}/{img}" #definimos la ruta donde se encuentra la imagen
#en la primera iteración no habrá imagen inicial por lo que no podrá combinarse con otra
# por lo que asignamos la imagen
if result_image == None:
result_image = Image.open(f"./{path}")
else: #combinamos la imagen
img2 = Image.open(f"./{path}")
result_image = Image.alpha_composite(result_image, img2)
# redimensionamos y guardamos
result_image = result_image.resize((350, 350), resample=Image.NEAREST)
result_image.save(f"./Test/image_{i}.png")
This will combine all the specified images in each row and save them to the specified path. As you have seen there is not much magic in this, just a couple of
for
loops, the first to iterate through the rows and the second to create thepath
and get the images. In each iteration of the secondfor
the result ofresult_image
is overwritten so that it always contains the result of the combination of the current image and the previous one, in this way all the images are mixed, obviously those that do not exist marked as'None'
are omitted
这非常好地回答了我的问题。