Sobre o blog

sexta-feira, 9 de maio de 2025

Noções de programação: exemplos com manipulação de imagens digitais

    Vamos aprender conceitos básicos de programação usando imagens.

    ATENÇÃO: Vão ter códigos em JavaScript abaixo, mas o professor do curso falou que isso não é JavaScript de verdade, e sim uma versão simplificada que eles usaram no curso pra facilitar o entendimento. Eu não sei se é verdade ou não, não sei muito de JavaScript. Mas acredito na palavra dele.

Manipulação de dados

    Começamos manipulando pixels únicos numa imagem 10 x 10. Fizemos ela dar zoom e pintamos um de seus pixels usando:

img = new SimpleImage("img/circulo.bmp"); // Põe a imagem na memória do programa, atribuindo ela a variável img
img.setZoom(20); // Dá um zoom na imagem.
pixel = img.getPixel(4,4); // Atribui especificamente o pixel nas coordenadas 4,4 na grade de pixels a variavel pixel
pixel.setRed(255); // Faz esse pixel atribuído virar da cor vermelha
print(img); // Mostra a imagem alterada na tela

    Pra pintar mais, só fazer tipo:

pixel1 = img.getPixel(4,4);
pixel1.setRed(255); 
pixel1.setBlue(255); 
pixel1.setGreen(0); 

    Desse jeito, o 4,4 vai ficar magenta, pois juntamos ele com vermelho e azul no máximo 255 e tiramos o verde colocando ele no 0. Mas isso é muito ruim, porque se eu quisesse editar OUTRO pixel eu teria que fazer as mesmas 4 linhas de código pra ele. Pra uma imagem grande, teria que fazer milhões de linhas. Se usar uma estrutura de repetição fica mais fácil.

Estruturas de repetição

    Estruturas de repetição são importantes pra quem programa. Faz o PC manipular vários dados em poucas linhas repetindo instruções automaticamente. Focaremos na estrutura de repetição for (ou loop for).

img = new SimpleImage("img/circulo.bmp");
for(pixel:img){ // Ele tá dizendo: "Para cada pixel da imagem, faça as 3 instruções abaixo. Nesse caso, tirar todas as cores."
    pixel.setRed(0); 
    pixel.setBlue(0); 
    pixel.setGreen(0); 
} // Quando ele chega aqui, ele volta pro começo até acabar com a imagem toda.
print(img);

    Com isso, ele vai pintar a foto TODA de uma cor (nesse caso, preta, mas pode ser alterada). A imagem usada tinha 292 mil pixels e o computador arrumou ela em 1 segundo só com 5 linhas.

Segunda prática


    Nessa eu me confundi e falhei por falta de atenção. Peguemos o código novamente mas mudemos ele um pouco.

img = new SimpleImage("img/circulo.bmp");
for(pixel:img){
    pixel.setRed(0); 
    pixel.setBlue(0); 
    pixel.setGreen(0); 
}
print(img);

    Aqui está como eu coloquei: "se removermos ou comentarmos (colocar // na frente) uma das instruções abaixo, as outras vão ser feitas e a marcada vai ser ignorada."

    Eu me confundi por causa disso e errei as questões, o que acontece na realidade é que a instrução é pra tirar todas essas 3 cores e colocar elas todas no 0. Se removermos uma, por exemplo, a vermelha, o computador NÃO vai colocar ela no 0. Ela vai continuar com seus tons avermelhados direitinho. Então seria: "se removermos ou comentarmos (colocar // na frente) uma das instruções abaixo, a cor dela vai ser mantida e as outras cores vão ser tiradas da imagem"

    Na primeira pratica, com todas no 0, a imagem ficar toda preta. Mas se fizermos ISSO:

img = new SimpleImage("img/circulo.bmp");
for(pixel:img){
//    pixel.setRed(0); 
    pixel.setBlue(0); 
    pixel.setGreen(0); 
}
print(img);

        Os tons avermelhados vão ser mantidos na imagem pois estamos zerando o verde e o azul e mantendo o vermelho. Do mesmo jeito, se fizéssemos isso com a verde ou com a azul, ficariam com seus respectivos tons.

Expressões

    Expressões são instruções onde você é capaz de realizar operações aritméticas como soma, multiplicar, subtrair, etc. Expressões são importantes. Deixam o código mais flexível. Em vez de só usar valores fixos (tipo 10, 255), dá pra combinar números e calcular coisas dinamicamente.

    Por exemplo print(51); faz o PC imprimir "51" na tela, mas podemos usar uma expressão print(40+11); Em vez de um número fixo, podemos usar uma expressão aritmética, o PC vai calcular a expressão automaticamente e imprimir "51".

    Como estamos usando IMAGENS de exemplo, vamos usar as funções de manipulação de pixel. Fiquei um pouco confuso nessa parte, então vou tentar explicar o melhor que eu conseguir, mas é basicamente:

pixel.getRed()
pixel.getGreen()
pixel.getBlue()

    Essas expressões obtêm/leem o valor atual de vermelho, verde ou azul. Tipo, se tiver um pixel amarelo e a gente usar pixel.getRed() nele, vai dar 255, pois amarelo é 255, 255, 0. Se pedisse azul, saia 0.

    Se quisermos duplicar o valor do vermelho, por exemplo, só colocar:

exemplo = pixel.getRed();
pixel.setRed(exemplo*2);

    E o vermelho vai ser dobrado. Mas o "exemplo" ali foi só pra ficar mais fácil de entender como funciona. Dá pra afzer isso tudo em 1 só linha, usando:

pixel.setRed(pixel.getRed()*2);

    Se a gente quisesse reduzir pela metade o valor, só trocar o "*" por um "/" o multiplicar o pixel atual por 0,5 ou 0,7 (reduz pra 50% e 70% respectivamente).

Transformar imagem em escala de cinzas

    Pra fazer uma imagem cinza é só fazer todos os RGB ter o mesmo valor. Como no exemplo abaixo:

soma=(pixel.getRed()+pixel.getGreen()+pixel.getBlue()); // Pra descobrir a média dos valores, primeiro mandamos o PC somar todos.
media= soma/3; // Depois mandamos o PC dividir a soma por 3.
pixel.setRed( media ); // Colocamos aqui as 3 cores com o mesmo valor. E vai ficar cinza. Eu coloquei "media" aqui porque com "media" a imagem fica com todas suas texturas intactas. Se colocar só o mesmo valor, a imagem vai ficar cinza, mas um cinza que é só um bloco cinza.
pixel.setGreen( media );
pixel.setBlue( media );

    Mudando qualquer um dos valores vai alterar a imagem de formas diferentes. Por exemplo, se colocar os // de comentário na frente do pixel.setRed, a imagem vai ficar com um tom meio rosa.

If

Estrutura condicional: classe de instruções de códigos que nos permite mandar o PC tomar uma decisão baseada em valores variados. Normalmente se um valor é verdadeiro ou falso. Todas as linguagens de programação tem estruturas condicionais,  vamos ver sobre o IF.

if(pixel.getRed() > 160){ // Ele basicamente diz: Se a intensidade do vermelho for maior que 160, execute as instruções abaixo.
pixel.setRed(0);
pixel.setGreen(0);
pixel.setBlue(0);
}

    Ou seja, se for menor ou igual, não vai ser feito nada. Só é feito se for verdadeiro.

    Normalmente temos declarações IF dentro de estruturas FOR, combinando seus poderes. Exemplo: Temos a imagem dos 3 círculos RGB e queremos mudar o vermelho pra CINZA, vamos mudar usando IF.




    Temos que ter em mente que vermelho é 255, 0, 0. Pra transformar em cinza, todos tem que estar iguais. O que fazemos é, mandamos o PC ver quais pixels vermelhos estão em 255, e se tiver, ele muda cada um desses pixels pra cinza! 120, 120, 120. Usamos esse código:

for(pixel:img){
if(pixel.getRed() == 255){
pixel..setRed(120);
pixel..setGreen(120);
pixel..setBlue(120);
}
}

    Desse jeito, tudo que for vermelho, amarelo, branco ou magenta vai virar cinza, pois todos tem 255 de vermelho. Agora, como fazemos SÓ o vermelho mudar e não os outros? Fazemos a instrução mais detalhada, mandando ele checar 3 coisas.

if(pixel.getRed() == 255 && pixel.getGreen() == 0 && pixel.getBlue() == 0) {

    Dessa forma, ele checa se é exatamente 255, 0, 0. E só muda o pixel se as TRÊS condições forem verdadeiras. Agora, a tal imagem dos círculos RGB foi um exemplo simples, pois ela mostra todas as cores em seus tons máximos, ou é 255 ou não é. Numa imagem com mais tons, checar só o 255, 0, 0 é meio difícil de fazer direitinho. Vamos colocar um exemplo de imagem com mais tons, por exemplo, a imagem de uma calçada com meio fio amarelo.

    Uma coisa que podemos fazer é novamente calcular a MÉDIA e testar se o verde e o vermelho (cores que fazem o amarelo) estão acima ou abaixo dela. Pra cada pixel, calculamos a média, somando 3 valores e dividindo por 3, assim, vemos se ele está acima ou abaixo da média. Talvez no amarelo fique: R:97 + G:97 + B:84 / 3 = 92.6 nesse caso, vermelho e verde estão acima da média, azul está abaixo.

    Novamente, colocamos o mesmo código de lá de cima, mas com o IF dessa vez:

media=(pixel.getRed()+pixel.getGreen()+pixel.getBlue()) / 3;
if(pixel.getRed() > media && pixel.getGreen() > media) { // Se o vermelho e o verde forem acima de média (desconsiderando o azul, pois queremos focar no amarelo) faça as cores ficarem cinzas (valores iguais abaixo)
pixel.setRed( media );
pixel.setGreen( media );
pixel.setBlue( media );
}

    É um código simples que faz muita coisa.

Tudo isso e pensamento computacional

    Pensamento computacional é importante, eu preciso aplicar mais técnicas como decompor e abstrair. Eu faço muita coisa na pressa e não paro pra usar as técnicas. Pensamento computacional é uma competência fundamental e imprescindível no mercado de trabalho.

    Vamos ver o que as coisas que aprendemos se conectam com pensamento computacional. 

    Compreendemos que o PC representa qualquer conceito por meio de números. Em imagens os números indicam a posição do pixel e sua cor.

    Usamos a abstração pra ver o que realmente importa na representação, no exemplo de imagem: Quantos pixels tem na imagem e qual a cor de cada pixel.

    Usamos a automação para escrever códigos pro PC automaticamente manipular os números, e assim, a imagem junto. Automação é outra habilidade do pensamento computacional. É escrever instruções pra fazer o PC fazer tudo automaticamente.

    Parar, analisar e avaliar como melhorar o código pra melhorar os resultados é muito útil e bom, se chama análise/avaliação.

    Decomposição é decompor um problema em problemas menores e fáceis de resolver, é ir passo a passo. Isso é muito útil e eu tenho que fazer mais disso, listar cada coisa que é pra fazer uma por uma.

Nenhum comentário:

Postar um comentário

Sobre o blog

    Essa vai ser uma postagem que vou tentar deixar fixada, talvez no cabeçalho, pra todo mundo ver. Só pra explicar direitinho esse blog, c...