Estou tentando combinar horizontalmente algumas imagens JPEG em Python.
Problema
Eu tenho 3 imagens - cada uma tem 148 x 95 - consulte o anexo. Acabei de fazer 3 cópias da mesma imagem - é por isso que são iguais.
Minha tentativa
Estou tentando uni-los horizontalmente usando o seguinte código:
import sys
from PIL import Image
list_im = ['Test1.jpg','Test2.jpg','Test3.jpg']
new_im = Image.new('RGB', (444,95)) #creates a new empty image, RGB mode, and size 444 by 95
for elem in list_im:
for i in xrange(0,444,95):
im=Image.open(elem)
new_im.paste(im, (i,0))
new_im.save('test.jpg')
No entanto, isso está produzindo a saída anexada como test.jpg
.
Questão
Existe uma maneira de concatenar horizontalmente essas imagens de modo que as subimagens em test.jpg não tenham uma imagem parcial extra aparecendo?
informação adicional
Estou procurando uma maneira de concatenar n imagens horizontalmente. Eu gostaria de usar este código de maneira geral, então prefiro:
- não codificar as dimensões da imagem, se possível
- especifique as dimensões em uma linha para que possam ser facilmente alteradas
for i in xrange(...)
em seu código? Não deveriapaste
cuidar dos três arquivos de imagem que você especifica?Respostas:
Você pode fazer algo assim:
Test1.jpg
Test2.jpg
Test3.jpg
test.jpg
O aninhado para
for i in xrange(0,444,95):
é colar cada imagem 5 vezes, com intervalos de 95 pixels separados. Cada iteração do loop externo é colada sobre a anterior.fonte
x_offset = 0
- este é o escalonamento entre os centros de imagem? 2. Para uma concatenação vertical, como sua abordagem muda?x_offset
comoleft
. Para concat vertical, acompanhe oy-offset
, outop
. Em vez desum(widths)
emax(height)
, façasum(heights)
emax(widths)
e use o segundo argumento da caixa de 2 tuplas. incrementary_offset
emim.size[1]
.map
em python3.6Eu tentaria isso:
Deve funcionar desde que todas as imagens sejam da mesma variedade (todas RGB, RGBA ou em tons de cinza). Não deve ser difícil garantir que este seja o caso com mais algumas linhas de código. Aqui estão minhas imagens de exemplo e o resultado:
Test1.jpg
Test2.jpg
Test3.jpg
Trifecta.jpg:
Trifecta_vertical.jpg
fonte
min_shape =....
eimgs_comb....
mudaria para uma concatenação vertical? Você poderia postar isso aqui como um comentário ou em sua resposta?hstack
paravstack
.Image.resize
do PIL.min_shape
é uma tupla de (min_width, min_height) e então(np.asarray( i.resize(min_shape) ) for i in imgs )
encolherá todas as imagens para esse tamanho. Na verdade,min_shape
pode ser o que(width,height)
você desejar, mas lembre-se de que ampliar imagens em baixa resolução as tornará desfocadas!Edit: A resposta do DTing é mais aplicável à sua pergunta, uma vez que usa PIL, mas deixarei isso no caso de você querer saber como fazê-lo em numpy.
Aqui está uma solução numpy / matplotlib que deve funcionar para N imagens (apenas imagens coloridas) de qualquer tamanho / forma.
Aqui está um exemplo de uso:
fonte
output = concat_images(output, ...
é o que eu procurava quando comecei a procurar uma maneira de fazer isso. Obrigado.Com base na resposta da DTing, criei uma função que é mais fácil de usar:
Permite escolher a cor de fundo e o alinhamento da imagem. Também é fácil fazer recursão:
fonte
Aqui está uma função generalizando abordagens anteriores, criando uma grade de imagens em PIL:
Isso reduzirá cada linha e coluna da grade ao mínimo. Você pode ter apenas uma linha usando pil_grid (imagens), ou apenas uma coluna usando pil_grid (imagens, 1).
Um benefício de usar PIL em vez de soluções baseadas em numpy array é que você pode lidar com imagens estruturadas de forma diferente (como escala de cinza ou imagens baseadas em paleta).
Saídas de exemplo
pil_grid(dummy_images)
:pil_grid(dummy_images, 3)
:pil_grid(dummy_images, 1)
:fonte
h_sizes, v_sizes = [0] * n_horiz, [0] * (n_images // n_horiz)
deve ser:h_sizes, v_sizes = [0] * n_horiz, [0] * ((n_images // n_horiz) + (1 if n_images % n_horiz > 0 else 0))
Razão: Se a largura horizontal não divide o número de imagens em inteiros, você precisa acomodar para a linha adicional, se incompleta.Se todas as alturas da imagem forem iguais,
talvez você possa redimensionar as imagens antes da concatenação como esta,
fonte
Esta é minha solução:
Para essas imagens:
Os resultados serão semelhantes a:
fonte
fonte
Resultado
fonte
Apenas adicionando as soluções já sugeridas. Assume a mesma altura, sem redimensionamento.
fonte
minha solução seria:
fonte