Às vezes, preciso escrever mais documentação do que apenas comentários no código. E, às vezes, essas explicações precisam de capturas de tela. Às vezes, as condições para obter uma captura de tela são tão estranhas que peço a um desenvolvedor que faça uma captura de tela para mim. Às vezes, a captura de tela não se encaixa nas minhas especificações e eu tenho que redimensioná-la para que fique bem.
Como você pode ver, as circunstâncias para uma necessidade do mágico "Lossless Screenshot Resizer" são muito improváveis. Enfim, para mim parece que eu preciso todos os dias. Mas ainda não existe.
Eu já vi você aqui no PCG resolver quebra-cabeças gráficos impressionantes antes, então acho que este é um pouco chato para você ...
Especificação
- O programa tira uma captura de tela de uma única janela como entrada
- A captura de tela não utiliza efeitos de vidro ou similares (portanto, você não precisa lidar com nenhum material de fundo que brilhe)
- O formato do arquivo de entrada é PNG (ou qualquer outro formato sem perdas, para que você não precise lidar com artefatos de compactação)
- O formato do arquivo de saída é o mesmo que o formato do arquivo de entrada
- O programa cria uma captura de tela de tamanho diferente como saída. O requisito mínimo está diminuindo de tamanho.
- O usuário deve especificar o tamanho de saída esperado. Se você pode dar dicas sobre o tamanho mínimo que seu programa pode produzir a partir da entrada fornecida, isso é útil.
- A captura de tela de saída não deve ter menos informações se interpretada por um ser humano. Você não deve remover o conteúdo de texto ou imagem, mas deve remover áreas apenas com segundo plano. Veja exemplos abaixo.
- Se não for possível obter o tamanho esperado, o programa deve indicar isso e não simplesmente travar ou remover informações sem aviso prévio.
- Se o programa indicar as áreas que serão removidas por motivos de verificação, isso deve aumentar sua popularidade.
- O programa pode precisar de alguma outra entrada do usuário, por exemplo, para identificar o ponto de partida para otimização.
Regras
Este é um concurso de popularidade. A resposta com mais votos em 08/03/2015 é aceita.
Exemplos
Captura de tela do Windows XP. Tamanho original: 1003x685 pixels.
Áreas de exemplo (vermelho: vertical, amarelo: horizontal) que podem ser removidas sem perder nenhuma informação (texto ou imagens). Observe que a barra vermelha não é contígua. Este exemplo não indica todos os pixels possíveis que poderiam ser removidos.
Redimensionado sem perdas: 783x424 pixels.
Captura de tela do Windows 10. Tamanho original: 999x593 pixels.
Áreas de exemplo que podem ser removidas.
Captura de tela redimensionada sem perdas: 689x320 pixels.
Observe que não há problema em que o texto do título ("Downloads") e "Esta pasta esteja vazia" não estejam mais centralizados. Obviamente, seria melhor se estiver centrado e, se sua solução fornecer isso, ela se tornará mais popular.
fonte
Respostas:
Pitão
a função
delrows
exclui todas as linhas, exceto uma duplicada, e retorna a imagem transposta, aplicando-a duas vezes também exclui as colunas e as transpõe de volta.threshold
Controla adicionalmente quantos pixels podem diferir para que duas linhas ainda sejam consideradas iguaisVirar o comparador
mask
de>
para<=
produzirá as áreas removidas, que são principalmente espaços em branco.golfed (porque porque não)
Em vez de comparar cada pixel, ele olha apenas para a soma; como efeito colateral, isso também converte a captura de tela em escala de cinza e tem problemas com permutações de preservação de soma, como a seta para baixo na barra de endereço do Win8. captura de tela
fonte
Java: Tente sem perdas e fallback para reconhecimento de conteúdo
(Melhor resultado sem perdas até agora!)
Quando olhei pela primeira vez para essa pergunta, pensei que não era um quebra-cabeça ou um desafio, apenas alguém que precisava desesperadamente de um programa e seu código;) Mas é da minha natureza resolver problemas de visão, para que eu não possa parar de tentar esse desafio. !
Eu vim com a seguinte abordagem e combinação de algoritmos.
No pseudo-código, fica assim:
Técnicas utilizadas:
O programa
O programa pode cortar capturas de tela sem perda, mas tem uma opção de recorrer ao corte com reconhecimento de conteúdo, que não é 100% sem perda. Os argumentos do programa podem ser ajustados para obter melhores resultados.
Nota: O programa pode ser aprimorado de várias maneiras (não tenho muito tempo livre!)
Argumentos
Código
Resultados
Captura de tela do XP sem perdas sem tamanho desejado (compactação sem perdas máxima)
Argumentos: "image.png" 1 1 5 10 false 0
Resultado: 836 x 323
Captura de tela do XP para 800x600
Argumentos: "image.png" 800 600 6 10 true 60
Resultado: 800 x 600
O algoritmo sem perdas remove cerca de 155 linhas horizontais do que o algoritmo volta à remoção com reconhecimento de conteúdo, pelo que alguns artefatos podem ser vistos.
Captura de tela do Windows 10 para 700x300
Argumentos: "image.png" 700 300 6 10 true 60
Resultado: 700 x 300
O algoritmo sem perdas remove 270 linhas horizontais. O algoritmo volta para a remoção com reconhecimento de conteúdo, que remove outras 29. Na vertical, apenas o algoritmo sem perdas é usado.
Captura de tela do Windows 10 com reconhecimento de conteúdo para 400x200 (teste)
Argumentos: "image.png" 400 200 5 10 true 600
Resultado: 400 x 200
Este foi um teste para ver como a imagem resultante ficaria com o uso severo do recurso de reconhecimento de conteúdo. O resultado está fortemente danificado, mas não irreconhecível.
fonte
C #, algoritmo como eu faria manualmente
Este é o meu primeiro programa de processamento de imagens e demorou um pouco para implementar com tudo isso
LockBits
, etc. Mas eu queria que fosse rápido (usandoParallel.For
) para obter um feedback quase instantâneo.Basicamente, meu algoritmo é baseado em observações sobre como eu removo pixels manualmente de uma captura de tela:
No momento, faço apenas horizontalmente. O resultado vertical pode usar o mesmo algoritmo e operar em uma imagem girada em 90 °, portanto, em teoria, é possível.
Resultados
Esta é uma captura de tela do meu aplicativo com regiões detectadas:
E este é o resultado da captura de tela do Windows 10 e do limite de 48 pixels. A saída tem 681 pixels de largura. Infelizmente, não é perfeito (consulte "Downloads de pesquisa" e algumas das barras verticais das colunas).
E outro com limite de 64 pixels (567 pixels de largura). Isso parece ainda melhor.
Resultado geral da aplicação da rotação para cortar também de toda a parte inferior (567x304 pixels).
Para o Windows XP, eu precisava alterar um pouco o código, pois os pixels não são exatamente iguais. Estou aplicando um limite de similaridade de 8 (diferença no valor RGB). Observe alguns artefatos nas colunas.
Código
Bem, minha primeira tentativa no processamento de imagens. Não parece muito bom, não é? Isso lista apenas o algoritmo principal, não a interface do usuário e nem a rotação de 90 °.
fonte
Haskell, usando a remoção ingênua de linhas sequenciais duplicadas
Infelizmente, este módulo fornece apenas uma função com o tipo muito genérico
Eq a => [[a]] -> [[a]]
, já que não tenho idéia de como editar arquivos de imagem em Haskell, no entanto, tenho certeza de que é possível transformar uma imagem PNG em um[[Color]]
valor e eu imaginoinstance Eq Color
que seja facilmente definível.A função em questão é
resizeL
.Código:
Explicação:
Nota:
a : b
significa elementoa
prefixado para a lista do tipo dea
, resultando em uma lista. Esta é a construção fundamental de listas.[]
denota a lista vazia.Nota:
a :: b
significaa
é do tipob
. Por exemplo, sea :: k
, então(a : []) :: [k]
, onde[x]
denota uma lista contendo itens do tipox
.Isso significa que
(:)
, sem argumentos:: a -> [a] -> [a]
,. O->
denota uma função de algo para algo.O
import Data.List
simplesmente recebe algum trabalho algumas outras pessoas fizeram por nós e nos permite utilizar as suas funções sem reescrevê-los.Primeiro, defina uma função
nubSequential :: Eq a => [a] -> [a]
.Esta função remove os elementos subseqüentes de uma lista que são idênticos.
Então
nubSequential [1, 2, 2, 3] === [1, 2, 3]
,. Vamos agora abreviar esta função comonS
.Se
nS
aplicado a uma lista vazia, nada pode ser feito, e simplesmente retornamos uma lista vazia.Se
nS
for aplicado a uma lista com conteúdo, o processamento real poderá ser feito. Para isso, precisamos de uma segunda função, aqui em umawhere
cláusula -, para usar a recursão, pois o nossonS
não controla um elemento com o qual comparar.Nós chamamos essa função
g
. Ele funciona comparando seu primeiro argumento com o cabeçalho da lista que foi dado e descartando o cabeçalho se eles corresponderem e se chamando de cauda com o antigo primeiro argumento. Caso contrário, ele anexa a cabeça à cauda, passando por ela mesma com a cabeça como o novo primeiro argumento.Para usar
g
, damos a ele a cabeça do argumentonS
e a cauda como seus dois argumentos.nS
agora é do tipoEq a => [a] -> [a]
, pegando uma lista e retornando uma lista. Exige que possamos verificar a igualdade entre os elementos, pois isso é feito na definição da função.Em seguida, compomos as funções
nS
etranspose
usamos o(.)
operador.Compor funções significa o seguinte:
(f . g) x = f (g (x))
.Em nosso exemplo,
transpose
gira uma tabela em 90 °,nS
remove todos os elementos iguais seqüenciais da lista; nesse caso, outras listas (é o que é uma tabela),transpose
gira-a para trás enS
remove novamente os elementos iguais sequenciais. Isso basicamente remove as colunas e linhas duplicadas subsequentes.Isso é possível porque, se é possível
a
verificar a igualdade (instance Eq a
), também[a]
é.Em resumo:
instance Eq a => Eq [a]
fonte