Quais fatores causam ou impedem a "perda geracional" quando os JPEGs são recomprimidos várias vezes?

29

Durante anos, acreditei que recomprimir arquivos JPEG várias vezes degradaria gradualmente sua qualidade até que se tornassem uma bagunça irreconhecível, como faz fotocópias de fotocópias. Intuitivamente, isso faz sentido porque o JPEG é um formato com perdas. Também existem outras perguntas e respostas que afirmam que é assim:

No entanto, também li que recomprimir JPEGs no mesmo nível de qualidade não prejudicará a qualidade da imagem. Isso contraria a degradação gradual descrita em outro lugar.

O que tecnicamente acontece quando um JPEG é recomprimido?  O que está sendo perdido e como? A imagem realmente se transformará na bagunça nevada que costumava aparecer na televisão? E os vídeos que mostram imagens que desmoronam após serem recomprimidas várias vezes?

(Por favor, não apenas acenar com a mão e apelar para o conceito geral de perda.)

(Esta pergunta, e as respostas que ela atraiu até agora, concentram-se nos fatores técnicos (configurações específicas e manipulações de imagem) que causam ou impedem a degradação da imagem quando um arquivo JPEG é recomprimido várias vezes.)

xiota
fonte
Relevante .
Mehrdad 28/06
2
@MonkeyZeus Alguma (pequena) quantidade de dados de imagem é perdida pelo erro de arredondamento na qualidade 100. A recompressão na mesma configuração (como 80) não resulta em perda progressiva de dados. Esse é o "conhecimento comum" que esta sessão de perguntas e respostas pretende abordar.
Xiota
1
@MonkeyZeus Os valores como "100" e "80" (ou "10, 11, 12" no Photoshop) são arbitrários - 100% não apresenta perdas.
mattdm

Respostas:

32

Quase todas as perdas na qualidade da imagem ocorrem na primeira vez que uma imagem é compactada como JPEG. Independentemente de quantas vezes um JPEG é recomprimido com as mesmas configurações , as perdas geracionais são limitadas ao erro de arredondamento.

  • Os limites do MCU permanecem intactos (8x8 blocos).

  • A subamostragem de croma está desativada.

  • DQT constante (mesma configuração de qualidade).

No entanto, os erros de arredondamento podem ser grandes para cada iteração em que os critérios acima não são atendidos e é prudente manter backups de todos os arquivos originais.


O algoritmo de compactação JPEG

  1. Converter espaço de cores. Se desejar, reduza a informação da cor (subamostra de croma) (Perda) . Se não for reduzida, a perda de informações é o resultado de um erro de arredondamento .

  2. Segmentação. Divida cada canal em blocos 8x8 (MCU = Unidade de codificação mínima). (Sem perdas)

    Nota: Se a subamostragem de croma estiver ativada, as MCUs poderão ser efetivamente 16x8, 8x16 ou 16x16, em termos da imagem original. No entanto, os MCUs ainda são todos os blocos 8x8.

  3. Transformação discreta de cosseno (DCT) em cada MCU. A perda de informações é o resultado de um erro de arredondamento .

  4. Quantização.  O valor em cada célula do MCU é dividido por um número especificado em uma tabela de quantização (DQT). Os valores são arredondados para baixo, muitos dos quais se tornarão zero. Essa é a parte com perdas primária do algoritmo.

  5. Digitalização em zigue-zague. Reorganize os valores em cada MCU em uma sequência de números seguindo um padrão em zigue-zague. Os zeros que ocorreram durante a quantização serão agrupados. (Sem perdas)

  6. DPCM = Modulação por código de pulso diferencial. Converta as seqüências numéricas em um formato mais fácil de compactar. (Sem perdas)

  7. RLE = Execução de codificação de comprimento. Zeros consecutivos são compactados. (Sem perdas)

  8. Codificação de Entropia / Huffman. (Sem perdas)

Recomprimindo JPEGs

Observe que a redução da amostragem dos canais de cores e a quantização são as únicas etapas intencionalmente com perdas . Deixando de lado o erro de arredondamento por enquanto, todas as outras etapas são sem perdas. Depois que a quantização ocorre, a reversão e a repetição da etapa fornecem resultados idênticos. Em outras palavras, a re-quantização (com o mesmo DQT) é sem perdas .

Em princípio, é possível criar um algoritmo de reamostragem sem perdas após a primeira passagem. No entanto, com a implementação no ImageMagick, as cores podem mudar drasticamente antes que o estado estacionário seja atingido, como visto na imagem desta.

Dadas as condições ideais, recomprimir um JPEG com as mesmas configurações de qualidade resultaria exatamente no mesmo JPEG. Em outras palavras, recomprimir JPEGs é potencialmente sem perdas . Na prática, recomprimir JPEGs não é sem perdas, mas está sujeito a, e limitado por, erro de arredondamento. Embora os erros de arredondamento geralmente acabem convergindo para zero , para que a mesma imagem seja recriada, a subamostragem de croma pode resultar em alterações significativas de cor.

Demonstração (mesma configuração de qualidade)

Eu escrevi o seguinte bashscript, que usa o ImageMagick para recomprimir repetidamente um arquivo JPEG em uma determinada configuração de qualidade:

#!/usr/bin/env bash
n=10001; q1=90
convert original.png -sampling-factor 4:4:4 -quality ${q1} ${n}.jpg

while true ; do
   q2=${q1}            # for variants, such as adding randomness
   convert ${n}.jpg -quality ${q2} $((n+1)).jpg
   #\rm $((n-5)).jpg   # uncomment to avoid running out of space
   n=$((n+1))

   echo -n "$q2  "
   md5sum ${n}.jpg
done

Depois de deixá-lo rodar por algumas centenas de iterações, executei md5sumos resultados:

d9c0d55ee5c8b5408f7e50f8ebc1010e  original.jpg

880db8f146db87d293def674c6845007  10316.jpg
880db8f146db87d293def674c6845007  10317.jpg
880db8f146db87d293def674c6845007  10318.jpg
880db8f146db87d293def674c6845007  10319.jpg
880db8f146db87d293def674c6845007  10320.jpg

Podemos ver que, de fato, o erro de arredondamento convergiu para zero e a mesma imagem exata está sendo reproduzida repetidamente .

Repeti isso várias vezes com diferentes imagens e configurações de qualidade. Normalmente, o estado estacionário é atingido, ea exata mesma imagem é reproduzida repetidamente.

E os resultados da @ mattdm ?

Eu tentei replicar os resultados do mattdm usando o Imagemagick no Ubuntu 18.04. O original foi uma conversão bruta para TIFF em Rawtherapee, mas parece não estar mais disponível. Em seu lugar, peguei a versão ampliada e a reduzi ao tamanho original (256x256). Então recompactei repetidamente aos 75 anos até obter convergência. Aqui está o resultado (original, 1, n, diferença):

tentativa de replicar o mattdm

Meus resultados são diferentes. Sem o original verdadeiro, a razão da diferença é impossível de determinar.

E a montagem de @ ths ?

Recompactei a imagem do canto superior esquerdo da montagem até a convergência em 90. Este é o resultado (original, 1, n, diferença):

tentar replicar ths-montagem

Depois de ativar a subamostragem de croma, as cores mudam quando o estado estacionário é atingido.

ths-color-shift

Alterando entre um pequeno número de configurações

Modificando a variável q2, a configuração de qualidade pode ser limitada a um conjunto de valores distribuídos uniformemente.

q2=$(( (RANDOM % 3)*5  + 70 ))

Para um pequeno número de opções de configuração, o equilíbrio pode eventualmente ser alcançado , o que é visto quando os valores de md5 começam a se repetir. Parece que quanto maior o conjunto, mais tempo demora e pior a imagem se torna, antes que o equilíbrio possa ser alcançado.

O que parece acontecer em equilíbrio é que o coeficiente de DCT antes da quantização deve ser divisível para todos (ou a maioria) dos valores quânticos. Por exemplo, se alternar entre dois DQTs em que o coeficiente DCT é dividido alternadamente por 3 e 5, o equilíbrio será alcançado quando o coeficiente DCT for divisível por 15. Isso explica por que a queda na qualidade é muito maior que a diferença entre as configurações originais.

Alterando entre um número maior de configurações

O Bisonho não fica feliz quando q2muda assim:

q2=$(( (RANDOM % 9)  + 90 ))

Para fazer um vídeo, use ffmpeg:

rename 's@1@@' 1*.jpg
ffmpeg -r 30 -i %04d.jpg -c:v libx264 -crf 1 -vf fps=25 -pix_fmt yuv420p output.mp4

Observar as primeiras 9999 iterações é quase como assistir a água ferver. Pode querer dobrar a velocidade de reprodução. Aqui está o Eeyore após 11999 iterações:

11999 iterações, DQT aleatório

E se os limites do MCU mudarem?

Se as alterações ocorrerem um número limitado de vezes, é provável que a recompressão repetida atinja o estado estacionário. Se ocorrerem alterações a cada iteração, a imagem provavelmente será degradada de maneira semelhante a quando o DQT for alterado.

E a edição?

O efeito de recomprimir após a edição depende da edição específica realizada. Por exemplo, salvar na mesma configuração de qualidade após reduzir os artefatos JPEG reintroduziria os mesmos artefatos. No entanto, a aplicação de uma alteração localizada, como um pincel de recuperação, não afetaria áreas que não foram tocadas.

A maior queda na qualidade da imagem ocorre na primeira vez que o arquivo é compactado em uma determinada configuração de qualidade. A recompressão subsequente com a mesma configuração não deve introduzir nenhuma alteração maior que o erro de arredondamento. Portanto, eu esperaria que os ciclos de edição e salvamento em uma determinada configuração de qualidade parecessem com qualquer outra imagem salva com a mesma configuração de qualidade (desde que os limites do MCU permaneçam intactos e a subamostragem de croma esteja desativada ).

E esses vídeos?

Posso sobrescrever meus originais com JPEGs recomprimidos?

É prudente manter backups de todos os arquivos originais, mas se você substituir acidentalmente um, o dano provavelmente será limitado. Também seria bom trabalhar em JPEG com a subamostragem de croma desativada.

O JPEG não pode ser usado para imagens que usam mais de 8 bits por cor.

xiota
fonte
5
a imagem é bem diferente com os loops load- edit- save, no entanto. neste caso, a quantização repetida causará degradação.
ths 27/06
2
Acabei de fazer um teste com o mesmo script da resposta. aqui está uma montagem de cada 20ª imagem até 100: i.stack.imgur.com/xtob6.jpg que é significativa.
ths 27/06
2
ah Encontrei o problema com a minha imagem. se você tiver a subamostragem de croma ativada, isso causará degradação progressiva.
ths 27/06
2
Também achei isso. Assim, ativar a subamostragem de croma altera significativamente a cor da imagem antes que o estado estacionário seja atingido.
xiota
2
Cargas e salvamentos repetidos usando exatamente os mesmos parâmetros provavelmente não introduziriam perda de qualidade ilimitada, já que a maioria dos arquivos de entrada poderia ser carregada e salva novamente sem a introdução de um erro de arredondamento adicional, e os arquivos que seriam afetados por erros de arredondamento provavelmente seriam transformados em arquivos que não. Por outro lado, ciclos repetidos de carregamento / salvamento que alternam entre parâmetros de compressão semelhantes mas não idênticos podem resultar em erros de arredondamento a cada ciclo.
Supercat
20

A perda de recompressão é real, especialmente quando se trabalha com níveis mais altos de compactação JPEG.

Em teoria, se você salvar novamente os arquivos JPEG com exatamente os mesmos parâmetros e alinhar sua colheita a 8 × 8 blocos, a degradação deverá ser mínima. No entanto, se você estiver usando um alto nível de compactação, verá mais perdas, porque os artefatos introduzidos pela compactação inicial são alterações permanentes na imagem e também serão recomprimidos, causando mais artefatos.

Se você salvar novamente com um baixo nível de compactação (alta qualidade, como "100" no Gimp ou 11 ou 12 no Photoshop), será difícil notar qualquer artefato adicionado recentemente. Ele não vai fazer a imagem qualquer melhor , mas não significativamente pior. No entanto, ele vai introduzir mudanças em toda a imagem.

Como um teste rápido, usei o ImageMagick para recomprimir uma imagem JPEG repetidamente a 75%. As amostras abaixo são carregadas como arquivos PNG para evitar recompressão ainda maior e tiveram seu tamanho duplicado quando converti para PNG para tornar o efeito mais óbvio. (Os originais usados ​​no teste não foram duplicados.) Acontece que, após oito reamostragens, o efeito convergiu para um resultado perfeitamente estável, onde a recompressão novamente resulta em um arquivo idêntico bit a bit.

Aqui está o original não compactado:

original, sem compressão JPEG

Aqui está o resultado de 75% de JPEG:

primeiro jpeg

E aqui está o que foi salvo novamente:

segunda passagem

Esse segundo salvamento causa uma grande quantidade de degradação adicional!

E aqui está a imagem convergente final (8ª passagem):

JPEG convergido

Novamente, as cores são definitivamente ainda mais diferentes , incluindo alguns padrões de cores falsas, e os artefatos em blocos saltam mais. O algoritmo converge, mas para uma versão significativamente degradada. Então não faça isso.

Mas aqui está a mesma coisa com um nível de qualidade de 99%, após 9 passes (o ponto em que converge para que outros passes sejam idênticos):

99% 9 vezes

Aqui, a diferença mal se registra. (Quero dizer isso literalmente; compare-os pixel por pixel com a versão não compactada e o desvio é apenas um ruído aleatório muito pequeno.) Então, e se eu voltar para a primeira imagem de 75% e depois salvar novamente em 99%? Bem, isso (depois de apenas uma vez):

75% uma vez e depois 99% uma vez

Salvar com alta qualidade é definitivamente visivelmente melhor do que salvar novamente com os mesmos parâmetros, para minha surpresa. Mas há uma nova degradação óbvia em torno do aparamento rosa e dos olhos. Com a versão reciclada das mesmas configurações, os artefatos JPEG estão sendo exagerados a cada recompressão. Com a baixa resolução e a baixa qualidade que escolhi, isso acaba sendo pior do que recomprimir tudo de maneira diferente.

Nesses vídeos: encontrei este como um dos principais hits do Google. Observe que ele diz na descrição:

É o que acontece se você recodificar uma imagem JPEG várias vezes, em configurações aleatórias de alta qualidade (85 ou superior).

Ênfase adicionada - isso explica por que não há convergência, porque, em vez de salvar com as mesmas configurações ou com qualidade super alta, configurações aleatórias são usadas a cada vez .

O segundo vídeo que encontrei diz:

Uma imagem JPEG foi copiada e girou uma revolução completa para cada imagem. [...] (596 ações "girar no sentido horário")

Então, novamente, algo foi feito para manter os erros acumulados.

De qualquer forma, para a edição prática de fotos , vale a pena mencionar que economizar 75% uma vez é muito pior do que salvar em 99% um milhão de vezes . No meu exemplo de exemplo, os artefatos a 75% são tão óbvios que a degradação adicional é como despejar água no oceano. Se você salvar em um nível alto o suficiente para que esses artefatos não sejam realmente visíveis, salvar novamente com as configurações originais é uma boa estratégia. Obviamente, se você continuar trabalhando sempre com originais não compactados, estará melhor.

Se, por algum motivo, você precisar (ou preferir fortemente) simplesmente trabalhar com JPEG, configure sua câmera para salvar na mais alta qualidade possível , mesmo que você não note a diferença nos arquivos iniciais. Consulte Vale a pena usar a configuração de qualidade JPEG Premium da Pentax? para saber mais sobre isso - não necessariamente específico da Pentax.

mattdm
fonte
(1) Você economiza 75%. Nessa configuração, é esperada a perda da qualidade da imagem. (2) Essa imagem foi selecionada e alterada para exagerar os artefatos de compactação JPEG. (3) A imagem converge após 8 rodadas de recompressão, após o que não haverá mais redução na qualidade da imagem. (4) Um vídeo dessa imagem mostrando "perda de geração" não teria acontecido nada depois dos primeiros 1/4 de segundo.
xiota
5
(1) Sim (2) "Selecionado" como uma foto típica em que alguém pode se importar com esse tipo de coisa. "Alterado" apenas para aumentar o zoom. Observe que isso é apenas para exibição aqui - não dupliquei o tamanho da imagem com a qual estava trabalhando. (3) Sim, mas na prática para edição, são as primeiras rodadas com as quais você pode se importar. (4) Isso é verdade, mas não implica que convergir para o pior caso e permanecer lá seja útil de alguma forma.
mattdm
Para replicar, pegue a primeira imagem e redimensione para 256 × 256 sem nenhuma reamostragem ou interpolação.
mattdm
Não vejo muita diferença entre as imagens que você mostra. Mas se eu pegar a diferença de uma imagem isolada e recomprimida e amplificada para torná-la visível, eu obtenho esse resultado (muito mais convincente): i.stack.imgur.com/57uaY.png (veja meu arquivo excluído responda exatamente o que foi feito) É mais convincente porque as pessoas não precisam ficar olhando a imagem para detectar pequenas diferenças.
precisa
As diferenças são bem pequenas. Se você tiver uma tela LCD grande, os diferentes "gama" resultantes de ângulos de visão ligeiramente diferentes podem fazer com que os artefatos pareçam mais proeminentes.
Xiota 28/06
5

A recompressão tem um efeito mensurável na qualidade da imagem e esse efeito é muito mais pronunciado ao alterar as taxas de compactação.

Como uma rápida verificação aqui, alguns valores do SSIM para operações executadas em uma imagem de teste contendo uma combinação de recursos de linha e recursos contínuos. Selecionei o JPG95, porque foi isso que me ensinaram a usar na escola Ad-photo e o JPG83, porque isso é comum entre os provedores de conteúdo digital.

  • Salvar imagem Tiff como JPG95 - .9989
  • Salvar imagem Tiff como JPG83 - .9929
  • Salve a imagem JPG95 como JPG95 10 vezes - .9998
  • Salve a imagem JPG83 como JPG83 10 vezes - .9993
  • Salve JPG95 como JPG83 e salve como JPG95 - .9929
  • Salve JPG95 como JPG83, depois JP83 para JP92 e JPG92 para JPG86 - .9914

Portanto, a quantidade de semelhança estrutural perdida para salvar novamente na mesma compactação 10 vezes é 1/10 da perda, poupando-a na qualidade da tiff. No entanto, a perda de qualidade ao alterar a compactação JPG mesmo uma vez é a mesma que a qualidade perdida ao salvar a imagem de Tiff para JPG.

Vou executar este teste mais algumas maneiras e atualizar.

Metodologia : No ImageJ:

  1. Converter Tiff RGB em escala de cinza de 8 bits
  2. Salvar JPG95 e JPG83 do Tiff Original
  3. Realizar operações de salvamento adicional, conforme especificado
  4. Carregue imagens de comparação e use o SSIM Index Plugin

NOTA: muitas pessoas que olham os valores do SSIM pela primeira vez os leem como porcentagens e assumem que a diferença é pequena. Isto não é necessariamente verdade. Os valores do SSIM devem ser comparados entre si e não considerados uma variação de 1.

PhotoScientist
fonte
@xiota, estou usando um plug-in SSIM para o ImageJ. É uma das poucas implementações de SSIM que permite o ajuste de parâmetros (eu defino a largura do filtro como 8 para que seja mais provável detectar alterações nos blocos JPEG de 16px.) Prefiro o SSIM porque é mais sensível às diferenças de energia redistribuição. Uma imagem de diferença pode ser enganosa se as diferenças forem canceladas ou as diferenças estiverem concentradas em uma área pequena.
PhotoScientist
E para sua segunda pergunta, diz que a diferença entre JPG95 e JPG83 para JPG95 é a mesma que entre Tiff e JPG83. Se você quiser Tiff-JPG95-JPG83-JPG95, ou seja, .9923 #
PhotoScientist
Foi adicionada uma tentativa com quatro compressões diferentes. A perda é ainda maior, mas é claro que a "convergência" vista por várias gerações da mesma compressão também está presente ao tentar várias compressões diferentes. Ainda gostaria de tentar isso em um fluxo de trabalho centrado no aplicativo, mas isso exige um pouco mais de trabalho.
PhotoScientist
Outra questão é que não existe um mapeamento padrão das configurações de "qualidade" para os limites do SSIM, nem há como determinar qual configuração de qualidade seria necessária para evitar perda significativa de informações. Se alguém carregar um JPEG e salvá-lo em uma configuração alta o suficiente, poderá ser evitada perda adicional de qualidade, mas o arquivo provavelmente ficará maior. Se alguém não souber qual configuração foi usada quando um arquivo foi produzido, pode ser difícil determinar qual configuração usar ao salvá-lo novamente.
Supercat
4

Nada como alguma experimentação. O seguinte script bash (escrito no Linux, pode funcionar no OSX se você tiver o ImageMagick ):

  • começando com uma primeira imagem (nomeada step000.jpg)
  • pega um arquivo JPEG, adiciona um ponto branco (para provar que é uma nova imagem) e salva como um (PNG sem perdas)
  • pega o PNG e o comprime novamente como JPEG (para que nunca comprimamos JPEG-para-JPEG, e não podemos supor que o software apenas copia blocos codificados)
  • cria uma imagem que mostra os diferentes pixels entre os dois JPEGs
  • enxágüe e repita, usando o JPG de saída da etapa anterior

O resultado é que:

  1. não há muita perda nas altas qualidades de JPG
  2. os erros de arredondamento acabam se resolvendo; depois de um pequeno número de gerações, as coisas não se degradam mais.

Obviamente, tudo isso pressupõe que o JPEG seja salvo pelo mesmo software com os mesmos parâmetros de cada vez.

#! /bin/bash
# Runs successive JPEG saves on an image to evaluate JPEG losses

# convert & compare command from imagemagick
# if you use a recent version of IM, set these variables to:
# compare="magick compare"
# convert="magick convert"
convert=convert
compare=compare

dotradius=2
defaultsteps=10
defaultquality=90 # default quality for "convert"

function usage {
        echo "Usage: $0 [quality [steps]]"
        echo ""
        echo "Where:"
        echo "       - 'quality' is the quality factor of the JPEG compression "
        echo "          (1-100, 100 is best, default is $defaultquality)"
        echo "       - 'steps' is the number of successive steps to perform"
        echo "         (default is $defaultsteps)"
        echo ""
        echo "Produces:"
        echo "   - successive saves of a JPEG image to test JPEG-induced losses."
        echo "   - compare images with the original file and the 1st JPEG save."
        echo ""
        echo "Starts from a 'step000.jpg' file in the current directory."
        exit 1
}

[[ -n "$3" ]] && { usage ; exit 1 ; }
steps=${1:-$defaultsteps}
quality=${2:-$defaultquality}    
dotcolor="white" # change this if the top of the image is too clear

echo "Running with $steps steps with quality $quality"

for step in $(seq $steps)
do 
    echo "Step $step of $steps"
    src=$(printf step%03d $(( $step - 1 )) ) 
    dst=$(printf step%03d $(( $step )) )
    dif=$(printf diff%03d $(( $step )) )
    # dot coordinates
    let cxc="2 * $dotradius * $step"
    let cxr="$cxc + $dotradius"
    let cyc="$dotradius * 2"
    let cyr="$dotsradius * 2"

    $convert $src.jpg -fill white -draw "circle $cxc,$cyc,$cxr,$cyr" $dst.png
    $convert $dst.png -quality $quality $dst.jpg
    rm $dst.png
    $compare $src.jpg $dst.jpg $dif.jpg
done

Por enquanto, não mostrarei os resultados, prefiro permitir que você experimente suas próprias imagens. Com comentários suficientes, vou adicionar uma amostra.

xenoid
fonte
1
Eu estava curioso sobre a coisa diferente do software. Tentei salvar 7x de 7 softwares diferentes. A diferença era bastante grande, então eu a dividi para ver se cada aplicativo tinha a mesma perda. Um dos aplicativos foi responsável por toda a variação. Uma vez eu removi o arenque vermelho, 6x salva de 6x programas era o mesmo que 6x salva de ImageJ
PhotoScientist
É provável que haja algum software mal codificado. Também é possível que a mistura de algoritmos de vários aplicativos também impeça a resolução dos erros de arredondamento.
Xenóide
@xiota, era um pequeno programa chamado FLEMinimizer. Eu nem me lembro por que eu tive isso em primeiro lugar. Os outros eram ImageJ, Matlab, Photoshop, FastStone Image Viewer, Ifranview e CameraRaw. Quase não houve variação em nenhuma etapa entre os seis.
PhotoScientist