thoga31 Posted June 21, 2012 at 05:04 PM Report Share #464664 Posted June 21, 2012 at 05:04 PM (edited) Olá, pessoal. Estou a fazer umas brincadeiras com Bitmaps e surgiu-me um problema. Tenho um OpenFileDialog para abrir uma imagem a meu gosto, e carrego-a numa PictureBox denominada pb_Image. Numa outra PictureBox, pb_Comparacao, tenho uma imagem feita por mim que mais não é uma série de pixéis coloridos. Esta é uma imagem 101x3. A minha intenção é comparar cada pixel da pb_Imagem.Image com todos os pixéis de pb_Comparacao.Image e determinar qual é a cor desta última mais próxima da original. Determinada a cor mais próxima, atribuo-lhe um valor, determinado pela coordenada do pixel onde se localiza essa cor: X+Y*100. Até aqui, tudo bem. O problema é que os valores determinados quase nunca são os mais próximos! Por exemplo, em vez de ter branco (que é o que se assemelha a branco, logicamente), aparece-me vermelho... Estou a utilizar o seguinte método para a comparação - uso dos métodos GetPixel e ToArgb: Private Sub Comparar() 'Imagem original e mapa de cores a comparar Dim Imagem As New Bitmap(Me.pb_Image.Image) Dim Comparacao As New Bitmap(Me.pb_compare.Image) 'Variáveis necessárias Dim ImgPixel As Integer Dim CmpPixel(101, 3) As Integer Dim Dif As UInteger Dim FinalX, FinalY As Integer 'Cria um array dos valores ARGB de cada pixel do mapa de comparação For x = 0 To Comparacao.Width - 1 For y = 0 To Comparacao.Height - 1 CmpPixel(x, y) = Comparacao.GetPixel(x, y).ToArgb Next Next 'Compara imagem com mapa For y = 0 To Imagem.Height - 1 For x = 0 To Imagem.Width - 1 'Pixel a comparar ImgPixel = Imagem.GetPixel(x, y).ToArgb 'Inicializa diferença de ARGB Dif = UInteger.MaxValue 'Compara com todos os pixéis do mapa de comparação For j = 0 To Comparacao.Height - 1 For i = 0 To Comparacao.Width - 1 'Se a diferença ARGB é menor, então é mais semelhante If Math.Abs(CmpPixel(i, j) - ImgPixel) < Dif Then Dif = Math.Abs(CmpPixel(i, j) - ImgPixel) FinalX = i FinalY = j End If Next Next 'Regista valor RichTextBox1.Text += NumberTo3Digits((FinalX + FinalY * 100)) '& ";" Next RichTextBox1.Text += vbNewLine Next End Sub Existe algum método que eu desconheça para determinar qual é a cor mais próxima? Cumprimentos, thoga31 Edited June 21, 2012 at 06:38 PM by thoga31 Knowledge is free! Link to comment Share on other sites More sharing options...
ribeiro55 Posted June 21, 2012 at 05:27 PM Report Share #464674 Posted June 21, 2012 at 05:27 PM (edited) Para o tipo de comparação que estás a fazer, tens usar o produto de todos os canais, não o valor 32-bit da cor. Compara longs provenientes da multiplicação de todos os canais. 128 x 128 x 128 x 128 = 268435456 é uma cor semelhante, de 130 x 130 x 130 x 130 = 285610000 Distam em 17174544 tons. Só tens de estipular offsets. Ficaste já a saber que a diferença de 2 valores em cada canal pode produzir 17174544 cores diferentes. Com estes valores, estamos a falar de dois cinzentos muito próximos. Na verdade são muito menos "cores", porque estamos a usar o canal alpha na equação, o que replica as 16777216 cores por cada um dos 256 níveis de alpha, totalizando 4294967296 possibilidades. Edited June 21, 2012 at 05:30 PM by ribeiro55 Sérgio Ribeiro "Great coders aren't born. They're compiled and released""Expert coders do not need a keyboard. They just throw magnets at the RAM chips" Link to comment Share on other sites More sharing options...
thoga31 Posted June 21, 2012 at 05:54 PM Author Report Share #464683 Posted June 21, 2012 at 05:54 PM Obrigado, @ribeiro55, de facto foi parvo da minha parte não ter pensado dessa forma. Para evitar erros de Overflow, e tendo em conta que não pretendo utilizar o Alpha, utilizei o tipo Int64 (ou Long), igualmente para facilitar o uso do método Abs da classe Math. Cumprimentos 😉 Knowledge is free! Link to comment Share on other sites More sharing options...
thoga31 Posted June 21, 2012 at 06:37 PM Author Report Share #464707 Posted June 21, 2012 at 06:37 PM Não estava à espera que o resultado fosse este... não estou a entender muito bem como é possível, sendo a escala P&B a menos passível de erros... :/ Do lado esquerdo está a imagem original, e do lado direito está o produto da comparação. Poderá estar a haver alguma falha da minha parte no que diz respeito ao cálculo da diferença de tonalidades? Knowledge is free! Link to comment Share on other sites More sharing options...
KTachyon Posted June 21, 2012 at 07:45 PM Report Share #464728 Posted June 21, 2012 at 07:45 PM Penso que há cores que têm mais peso que outras no RGB. Existe uma propriedade chamada luminância (se não me engano), que dá maior peso para determinadas cores. Penso que será essa a propriedade que te está a afectar as comparações. Os pesos são os seguintes: R: 29.9% G: 58.7% B: 11.4% Experimenta utilizar estes pesos e vê que resultados consegues obter. “There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.” -- Tony Hoare Link to comment Share on other sites More sharing options...
thoga31 Posted June 21, 2012 at 08:08 PM Author Report Share #464734 Posted June 21, 2012 at 08:08 PM Penso que há cores que têm mais peso que outras no RGB. Existe uma propriedade chamada luminância (se não me engano), que dá maior peso para determinadas cores. Penso que será essa a propriedade que te está a afectar as comparações. Os pesos são os seguintes: R: 29.9% G: 58.7% B: 11.4% Experimenta utilizar estes pesos e vê que resultados consegues obter. Utilizar directamente estes factores na multiplicação de nada vão servir. Assim de repente não estou a ver onde aplicar estes factores, apesar de suspeitar que seja estupidamente fácil :S Knowledge is free! Link to comment Share on other sites More sharing options...
KTachyon Posted June 21, 2012 at 09:11 PM Report Share #464743 Posted June 21, 2012 at 09:11 PM Tens que separar as componentes e aplicar os pesos a cada uma para achares a diferença: diff = 0.299 * abs(c1.red - c2.red) + 0.587 * abs(c1.green - c2.green) + 0.114 * abs(c1.blue - c2.blue) “There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.” -- Tony Hoare Link to comment Share on other sites More sharing options...
ribeiro55 Posted June 21, 2012 at 09:19 PM Report Share #464746 Posted June 21, 2012 at 09:19 PM (edited) Sim, existem pesos por canal quando queres determinar a luminosidade (penso que luminosidade seja o mais correcto, e foi também o nome que dei na minha imago), e estes afectam a forma como uma cor se relaciona com outra, vá, o como dizes que determinada cor é de facto mais escura do que outra. Não os sei de cor, nem conssigo confirmar esses do KTachyon, mas posso espreitar a source da minha lib. Na altura fiz umas deep researches. Como deves usar os pesos, depende um pouco do que queres fazer. Eu uso muitas vezes o cálculo de luminosidade para detectar quando devo usar letras brancas ou pretas, dependendo da luminosidade da cor de fundo. Dei-te a solução straightforward porque não percebi sinceramente que filtro estás a tentar aplicar. Consegues explicar de outra forma qual seria o resultado que esperas? Estas a tentar implementar algum filtro em particular? EDIT: se puderes explica-me à mesma melhor o que estás a tentar aplicar, agora que o KTachyon te deu uma fórmula de pesos na diferença. Edited June 21, 2012 at 09:21 PM by ribeiro55 Sérgio Ribeiro "Great coders aren't born. They're compiled and released""Expert coders do not need a keyboard. They just throw magnets at the RAM chips" Link to comment Share on other sites More sharing options...
thoga31 Posted June 21, 2012 at 09:49 PM Author Report Share #464761 Posted June 21, 2012 at 09:49 PM Estou a fazer uma pequena aplicação que transforma uma imagem num TXT onde cada píxel é definido com um número de 3 dígitos. Criei uma imagem 101x3 com as cores-padrão, uma em cada pixel. Isto para quê? Não consigo desencantar nenhum método que mostre uma imagem em Pascal, pelo que estou a tentar fazer um método que o faça. Tenho a função em pascal a funcionar: lê o TXT, e converte cada número num pixel de cor correspondente que ele suporta. Ora, tenho de ter uma forma de converter as imagens nos TXTs, e visto que VB.NET tem estas funções de uso simples e rápido, decidi fazer o conversor em VB.NET. Mas os problemas vieram com a comparação da cor de cada pixel da imagem original com as 256 cores do "mapa de comparação" (a tal imagem 101x3). Ele cria correctamente o TXT segundo o formato padrão que defini, mas não está a comparar as cores correctamente. Não sei se estão a entender bem o meu objectivo. O produto que mostrei na imagem é produzido pelo meu programa em Pascal, e não, nesse não há erros que eu já fiz a experiência a fundo. Cumprimentos, e obrigado por tudo até agora 😉 Knowledge is free! Link to comment Share on other sites More sharing options...
ribeiro55 Posted June 21, 2012 at 10:05 PM Report Share #464770 Posted June 21, 2012 at 10:05 PM 'Cha cá ver se percebi. O objectivo é recriar uma imagem onde as cores têm de ser o mais aproximadas possível das disponíveis na tal palete 101x3. É isto? Ora manda-nos lá a palete... Sérgio Ribeiro "Great coders aren't born. They're compiled and released""Expert coders do not need a keyboard. They just throw magnets at the RAM chips" Link to comment Share on other sites More sharing options...
thoga31 Posted June 21, 2012 at 10:24 PM Author Report Share #464784 Posted June 21, 2012 at 10:24 PM (edited) Palete original: Download para uso: https://dl.dropbox.com/u/30172141/P%40P/T%C3%B3picos/cores.png Palete aumentada: Código das cores: Como podem reparar, só vai até à 247 - o resto é inexistente (aka preto aka '000') Edited June 21, 2012 at 10:25 PM by thoga31 Knowledge is free! Link to comment Share on other sites More sharing options...
ribeiro55 Posted June 21, 2012 at 11:10 PM Report Share #464810 Posted June 21, 2012 at 11:10 PM Pedi-te a palete porque achei o desafio interessante. Agora não posso, mas amanhã vou deslindar uma implementação e depois discutimos os resultados 😉 Percebi bem, certo? O objectivo é aplicar a palete em determinada imagem? Sérgio Ribeiro "Great coders aren't born. They're compiled and released""Expert coders do not need a keyboard. They just throw magnets at the RAM chips" Link to comment Share on other sites More sharing options...
thoga31 Posted June 21, 2012 at 11:20 PM Author Report Share #464814 Posted June 21, 2012 at 11:20 PM Exactamente. O objectivo é, por pontos: 1) Determinar qual das 247 cores da palete é a mais semelhante à cor de cada pixel de uma imagem; 2) Determinada essa cor, dar-lhe o devido número segundo o código que forneci; 3) Gravar o resultado num TXT, que será simplesmente o conjunto de números de 3 dígitos. Ter em atenção o padrão do TXT: 1) Cada linha corresponde a uma linha de píxeis; 2) Cada linha termina com um CRLF feito pelo vbNewLine - é mandatório ser assim, caso contrário a aplicação em Pascal não suporta o TXT 3) Cada píxel deve ter os 3 dígitos - a cor 5 será 005. Também vou dormir agora, não consegui evoluir muito mais, estive a limar as arestas numa unit. E obrigado pelo interesse! 😉 Cumprimentos, thoga31 Knowledge is free! Link to comment Share on other sites More sharing options...
ribeiro55 Posted June 22, 2012 at 04:55 PM Report Share #464992 Posted June 22, 2012 at 04:55 PM Com muito, muito pouco tempo, escrevi um algoritmozito para apanhar a cor mais próxima. Com essa palette indexada, obténs isso que obténs, com esta técnica de aproximação, que é a directa. Existem outros métodos de aproximação que analisam pixeis vizinhos e determinam a melhor aproximação. Tentei aproximações de luminosidade, e combinação de canais com luminosidade, sendo esta última, a mais aproximada. Tens pano para mangas 😉 Lembrei-me também de uma forma de perceberes se o teu método de comparação directo está a trabalhar bem. Usa como palette, a mesma imagem a converter. Se o output ficar exactamente igual, à partida estás a fazer comparações directas correctamente. Sérgio Ribeiro "Great coders aren't born. They're compiled and released""Expert coders do not need a keyboard. They just throw magnets at the RAM chips" Link to comment Share on other sites More sharing options...
thoga31 Posted June 22, 2012 at 05:10 PM Author Report Share #464993 Posted June 22, 2012 at 05:10 PM (edited) Olá, @ribeiro55. Não vou conseguir fazer exactamente essa experiência a não ser que crie um "script" em VB para analisar o output. O Pascal não suporta mais do que aquelas 248 cores, pelo que o meu Tester não funcemina. 😛 Fazendo contas rápidas de cabeça, o método a que chegámos da multiplicação vai dar o mesmo output, não haveria hipóteses de falhas, acho. Acho que é melhor tentar experimentar outros métodos para aquilo que pretendo... Mas se o mais próximo a que chegaste foi aquela imagem a que eu cheguei, digo-te já que é mesmo a melhor imagem a que consigui chegar... 😛 Obrigado por tudo. 😉 thoga31 Edited June 22, 2012 at 05:11 PM by thoga31 Knowledge is free! Link to comment Share on other sites More sharing options...
ribeiro55 Posted June 22, 2012 at 05:16 PM Report Share #464995 Posted June 22, 2012 at 05:16 PM Não. Cheguei a uma melhor determinando a menor diferença de canal AND a menor diferença de luminosidade. Mas não tão melhor que valha a pena. Sérgio Ribeiro "Great coders aren't born. They're compiled and released""Expert coders do not need a keyboard. They just throw magnets at the RAM chips" Link to comment Share on other sites More sharing options...
thoga31 Posted June 22, 2012 at 05:19 PM Author Report Share #464997 Posted June 22, 2012 at 05:19 PM (edited) Sinceramente não vale a pena tanto trabalho, não queimes mais neurónios com isto, era só uma experiência breve para ver se adaptava uma unit do Pascal. Depois investigo melhor o caso, de momento tenho outras coisas prioritárias com que me preocupar. 😛 Obrigado 😉 Edited June 22, 2012 at 05:19 PM by thoga31 Knowledge is free! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now