Fractal image compression

Fractal image compression é uma aplicação emocionante da teoria fractal, particularmente na compressão de imagem

Descrição

Com esta aplicação, você pode:

  • Comprimir imagens com este método fractal
  • Descomprimir imagens previamente compactadas em um formato diferente

Faça uso das bibliotecas da plataforma, que incluem os seguintes recursos:

  • Multi-língua
  • Zoom multi-resolução configurável
  • Opção de modo escuro
  • Notificação de nova versão


Prós:

  • Quando programado corretamente, funciona independentemente da resolução da imagem
  • É um método de compressão distinto
  • Permite que você aprenda como você vai


Contras:

  • O processo de compressão é extremamente lento
  • Você não consegue taxas de compressão muito altas (pelo menos com os parâmetros que usei)

Descrição do código

É uma implementação destefractal image compression algoritmopublicado no IEEE durante os meus dias de faculdade

O aplicativo utiliza a biblioteca de triangulação incremental Delaunay, que também é usada naAplicação morphing


Algoritmo de alto nível:

  • Compressão:
    • A compressão fractal concentra-se no armazenamento de relações entre regiões de imagem, em vez dos valores reais de pixels, especificamente entre triângulos, neste caso.
    • A imagem é dividida em uma grade triangular composta por múltiplos triângulos, formando um domínio triangulado.
    • A imagem é subdividida em um novo conjunto de triangulações com triângulos maiores designados para o livro de códigos.
    • As triangulações são dinâmicas, e o algoritmo de divisão e fusão é aplicado com base na variância dos pixels do triângulo.
    • Uma vez determinada a triangulação do livro de códigos, os triângulos 2n mais representativos são selecionados para formar o livro de códigos. O valor de n afeta significativamente o tempo de compressão, tendo um efeito menor na taxa de compressão e na qualidade alcançada.
    • Para cada triângulo de domínio, o mapeamento ideal com um triângulo do livro de códigos é procurado usando um critério mínimo de erro quadrado médio (MSE).
    • O mapeamento ideal entre triângulos é encontrado fazendo combinações de:
      • Permutações dos vértices (6 possibilidades)
      • Determinar um deslocamento para a média
      • Encontrar um fator de escala entre 0 e 1, que é aplicado ao desvio da média. Este fator de escala deve permanecer entre 0 e 1 para evitar divergências durante o processo de descompressão iterativa
      Além disso, esses parâmetros devem ser quantizados usando um número limitado de bits para garantir que tanto o tempo de compressão quanto a relação sejam razoáveis e de acordo com a qualidade desejada.
  • As informações armazenadas no arquivo compactado para cada canal:
    • A informação para reproduzir as duas triangulações:
      • Triângulos que se dividem em cada iteração
      • vértices que foram removidos como resultado da fusão (após completar as iterações divididas)
    • A seleção dos triângulos 2n do livro de códigos
    • O mapeamento ideal de cada triângulo de domínio:
      • Qual triângulo de livro de código ele usa para mapear (n bits)
      • A permutação de vértice ideal (6 combinações, 3 bits)
      • Offset (os autores indicam que o deslocamento é efetivamente representado com 6 bits)
      • Escala (os autores indicam que a escala é efetivamente representada com 6 bits)
  • Descompressão (para cada canal):
    • Os triângulos das duas triangulações são obtidos.
    • Os triângulos do livro de códigos são obtidos.
    • Este processo é repetido até que a convergência seja alcançada:
      • O mapeamento de todos os triângulos de domínio para suas correspondências ideais com os triângulos do livro de código


Depois de ganhar um mestrado em Inteligência Artificial, eu imagino inovar como derivar os triângulos mais significativos para o livro de código aplicando K-medoids.

Não tenho certeza se a inovação vai melhorar ou dificultar o algoritmo, mas isso me salva da necessidade de programá-lo eu mesmo, o que inicialmente parecia complicado.


O processamento de imagem é dividido em canais, tipicamente RGB.

Ele utiliza multiprocessamento, com um fio dedicado a cada canal.


Com a versão v1.1, um leitor compatível com o padrão ImageIO foi adicionado.

Portanto, você pode abrir uma imagem compactada (.dfc) com o aplicativo simplesmente fazendo:

BufferedImage image = ImageIO.read("image.dfc");

Windows

Fractal image compression v1.0 (2022-2024)

Assista vídeo
Download

Fractal image compression v1.1 (2026)

Download

Versões

image

O aplicativo implementa um algoritmo fractal image compression descrito em um artigo IEEE dos meus dias universitários. É baseado na triangulação Delaunay e codificação de blocos.

Colaborei com um colega universitário para desenvolver a versão inicial deste algoritmo durante um estágio para o último curso da Teleco Television (plano 64 de Barcelona).

A internet ainda estava em seus estágios iniciais, e qualquer progresso dependia quase inteiramente de esforços individuais e documentos físicos.

Lembro-me que desenvolvemos uma triangulação Delaunay bastante boa e implementamos com sucesso a abordagem de divisão e fusão. Isso envolveu calcular os triângulos mais representativos e encontrar os mapeamentos ideais durante o processo de codificação. No entanto, apesar de três meses de desenvolvimento intensivo, nunca concluímos o aplicativo.

Agora, 25 anos depois, apresento-lhe esta nova implementação do algoritmo, totalmente desenvolvido e concluído em um tempo recorde de duas semanas.

Obviamente, algo será melhorado 25 anos depois. Além disso, desta vez com suporte de função adicional para lidar com triângulos, que eu já tinha programado para a aplicação do efeito Morphing.

Desta vez usando uma biblioteca de triangulação Delaunay programada por profissionais.

É evidente que quando você não tem que fazer os tijolos você mesmo, mais rápido você pode construir as paredes...


Vídeo de demonstração

image

O novo recurso na versão v1.1 é a adição de um leitor de imagem comprimido por fractal dentro do aplicativo que é compatível com ImageIO.

Portanto, você pode ler uma imagem compactada (.dfc) com o aplicativo da seguinte forma:


BufferedImage image = ImageIO.read("image.dfc");


Comparando a imagem no formato.jpg e no formato.dfc do aplicativo, você pode ver que a qualidade é um pouco pior do que em.jpg e que ocupa um arquivo um pouco maior (como esperado).

Mas o resultado não é nada mau.

No entanto, dado o longo tempo de processamento necessário para a compressão, esse tipo de compressão e sua implementação na aplicação são apenas de interesse acadêmico.


04/05/2026 - 04/12/2026 . Depois de ter recuperado a evolução desta aplicação, proponho fazer testes com imagens reais, e eu tento com um dos "4000 x 3000" pixels.

Eu encontro muitos problemas:

  • O processo leva para sempre nas iterações divididas (devido às extensas triangulações de até 400.000 triângulos, e que a verificação da condição dividida foi repetida para todos os triângulos em cada iteração)
  • A memória acaba depois de atingir o limite de 23 GB que eu tinha no meu sistema. Porque:
    • O resultado das iterações de divisão e fusão foram armazenados em uma lista booleana (cerca de 16 iterações x 2 tipos de triangulação x 3 canais x 400.000 elementos!!!!). Isso faz um total de cerca de 40.000.000 elementos, que ainda é aceitável)
    • Além disso, a seleção do livro dos triângulos mais representativos (definido como 256) foi realizada com um K-medoides (mais de 400.000 elementos) (a memória usada por esse algoritmo é O(n2)). Agora está ficando fora de controle...)
    • E, para mais INRI, esses cálculos foram realizados em paralelo para os três canais (rgb)!!
  • Uma vez que esses problemas são resolvidos, consigo comprimir a imagem (4000 x 3000), mas vejo que leva entre 6 e 8 horas para concluir o trabalho.

E proponho resolvê-los:

  • Para a eternização de divisões. Solução:
    • Eu aumento o tamanho mínimo dos triângulos para dividir, de forma proporcional ao número de pixels na imagem. Resultando em uma redução no número de triângulos nas triangulações. Na imagem usada de (4000 x 3000) o número de triângulos é dividido por mais de 4 (passamos de cerca de 400.000 triângulos para cerca de 100.000 triângulos).
    • Além disso, eu crio um conjunto com os triângulos que não atendem ao critério de divisão (em relação à variância dos valores de seus pixels), para não repeti-los em cada iteração. Agora voe!!
  • O sistema está ficando sem memória. Solução:
    • Resultado de divisões e fusões salvas em listas booleanas. Solução:
      • medida que as iterações de divisão progridem, o número de triângulos que se dividem é radicalmente menor, a memória usada é salva armazenando os índices dos triângulos que se dividem em um conjunto.
    • Memória de K-medoides (presumivelmente O(n2)). Solução:
      • Como dividimos o número de triângulos por 4..., a memória necessária para esse algoritmo, essa redução de triângulos envolve dividir a memória usada por um fator de cerca de 16.
      • Três K-medoides em paralelo (um para cada canal). Solução:
        • Sequenciamos os cálculos das triangulações e a seleção dos triângulos mais representativos para o livro de códigos (com K-medóides).
      • Dividimos a memória necessária para os K-medóides de 48!!
  • O tempo de processamento com imagens "reais" leva para sempre (a compressão da imagem de exemplo leva entre 6 e 8 horas) com 3 threads, um para cada canal.
    • (Ao configurá-lo para 23 threads (meu sistema tem 24 núcleos), o tempo de processamento é reduzido para três horas e meia).
  • Efeitos da solução:
    • O efeito de dividir o número de triângulos por 4 obviamente resulta em uma perda notável da qualidade da imagem compactada. Mas com tanta resolução, não é tão importante.
    • Ao dividir o número de triângulos por 4, também faz com que o tamanho do arquivo comprimido seja dividido, supostamente também da ordem de 4.

Também pretendo tentar minimizar o tamanho do arquivo compactado, reorganizando as informações a serem armazenadas.

A ideia é indicar acima de tudo na codificação das listas de índices dos triângulos que se dividem em cada uma das iterações, cuja codificação trivial original era usar um bit por triângulo, indicando se se dividia ou não.

Eu desenvolvo um algoritmo para tentar minimizar o tamanho necessário para armazenar cada um desses conjuntos de índices.

Eu acho que não é desperdiçado... se você está curioso neste site eu digo os pontos-chave em que eu confiei.

Embora talvez valesse mais a pena procurar um compressor geral sem perdas como zip ou 7z e aplicá-lo à globalidade do arquivo compactado... Talvez pela próxima vez.


Na última versão da entrega, um aplicativo de interface de comando está incluído, o que traduz um arquivo criado com versões menos otimizadas do codificador, para a versão mais recente do codificador, que presumivelmente ocupa menos espaço.

Usando esta pequena nova aplicação em um par de arquivos com a codificação original (um de 143x143 e outro de 4000x3000), é que o tamanho do arquivo compactado é reduzido em cerca de 4% neles.

Vídeos

Downloads