Bom dia!
Então, eu precisava fazer um algoritmo de detecção de bordas e outro que lê a imagem e retorna a % de pixels R, G, B da imagem, porém não consegui encontrar algo na internet com os métodos que eu uso, Buffered, Writable, Raster… Só tem usando funções.
Alguém tem alguma ideia de algoritmo de como começar? Ou tem alguma base?
Não entendi bem sua dúvida. BufferedImage, Writable, Raster e etc. são, de forma simplificada, meios para armazenar os dados da imagem. Eles, por si só, não fornecem algoritmos para essas operações, mas podem ser usadas nesses algoritmos.
Por exemplo, BufferedImage permite percorrer os pixels da imagem usando getRGB(), então você pode verificar os percentuais de cada canal (Red, Green, Blue) em cada pixel. Com isso, também, fica mais fácil implementar qualquer algoritmo que opere sobre a imagem.
Abraço.
Sim, eu sei que eles não fornecem o algoritmo kkk.
Eu digo isso porque a maioria de algoritmos de processamento de imagens que eu vejo, são usando métodos/funções diferentes, daí fica mais difícil pra mim entender, por isso eu perguntei se alguém tem alguma base com eles.
Dê um exemplo desses algoritmos (um link ou similar), pois não estou entendendo qual a sua dificuldade em específico.
Também não está claro se você tem muita experiência com Java, o que pode afetar sua compreensão dos algoritmos. Boa parte deles não é complexa, mas também não são triviais, requerendo um pouco de familiaridade com algoritmos.
Abraço.
Um exemplo de algoritmo que já fiz, foi o de transformar uma imagem em preto e branco.
Algoritmo:
public static void main(String[] args) throws IOException {
int w, h;
BufferedImage original = ImageIO.read(new File(“cidade.jpg”));
w = original.getWidth(); h = original.getHeight();
BufferedImage processada = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
int[] pixels = new int[h * w * 3];
WritableRaster raster = processada.getRaster();
original.getRaster().getPixels(0, 0, w, h, pixels);
int limiar = 100;
int ml = 0;
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int [] p = new int[3];
ml = (p[0] + p[1] + p[2])/3;
if (ml < limiar)
{
p[0] = 0;
p[1] = 0;
p[2] = 0;
}
else
{
p[0] = 255;
p[1] = 255;
p[2] = 255;
}
}
raster.setPixels(0, 0, w, h, pixels);
ImageIO.write(processada, "jpg", new File("pretobranco.jpg"));
}
}
}
Eu recomendo você organizar seu código em métodos e classes distintos, assim fica mais fácil de estrutura e entender o código. Por exemplo ao invés de fazer tudo no main, crie um método para gerar a imagem em preto e branco e passe a imagem que quer processar como parâmetro. Assim, você terá uma classe mais reusável e fácil de entender.
Esses métodos podem retornar a imagem processada (um BufferedImage ou um WritableRaster, que você pode fazer o que quiser depois. Isso te permite, por exemplo, aplicar diversos filtros sobre uma imagem em sequência.
public class ProcessadorDeImagens{
// o retorno pode ser um WritableRaster, mas eu geralmente prefiro BufferedImage
public BufferedImage gerarImagemPretoEBranco(BufferedImage imagemOriginal){
BufferedImage resultado;
// aqui se faz o processamento sobre a imagemOriginal com seus código atual, guardando o que foi feito na variável resultado
return resultado;
}
public static void main(String args[]) throws IOException{
ProcessadorDeImagens processador = new ProcessadorDeImagens();
BufferedImage original = ImageIO.read(new File(“cidade.jpg”));
BufferedImage imagemEmPretoEBranco = processador.gerarImagemPretoEBranco(original);
WritableRaster raster = imagemEmPretoEBranco.getRaster();
}
}
A partir daí, você cria outros métodos para outros processamentos. Por exemplo, para detecção de bordas, pode criar um método como:
public BufferedImage deteccaoDeBordas(BufferedImage imagemOriginal){
// aqui você implementa o algoritmo. Note que método "acessórios" podem ser necessários
}
Para o algoritmo em específico, você pode procurar por algo como Java edge detection. Exemplos:
- https://www.codemiles.com/java-examples/edge-detection-in-java-t10945.html
- https://stackoverflow.com/questions/41468661/sobel-edge-detecting-program-in-java
Abraço.
Agradeço muito por me ajudar, mas é complicado pra mim entender isso tudo kkkk…
Mas vou tentar adaptar o código do link pro meu código.
O link que você me passou funcionou, porém, é bem além do que estou aprendendo.
Mas mesmo assim, te agradeço dms!
Você pode detectar bordas pelos algoritmos de Prewitt, Laplace ou Sobel. Todos eles se baseiam na observação de que valores diferentes, quando subtraídos, dão um resultado maior que zero. Como os pixels na área de bordas costumam a ser diferentes, a idéia é então subtrair as vizinhanças de um pixel para ver se tem algo lá.
Eu fiz uma implementação de alguns filtros de bordas usando Java. O código é bem simples e direto, já que é para meus alunos entenderem, e usa praticamente só o getRGB. Você pode ver nesse repositório:
Outra forma de detectar Bordas é por morfologia matemática. Basta realizar um processo de dilação ou erosão e subtrair as duas imagens. Isso é demonstrado aqui:
Sobre contar o percentual de pixels pretos e brancos… ora, seu código quase já faz isso. Basta usar um contador para somar a quantidade de pixels que estiver no limiar e depois dividir pelo total:
public double whitePercent(BufferedImage img, int threshold) {
double white = 0;
for (int y = 0; i < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
Color c = new Color(img.getRGB(x,y));
if (c.getRed() > threshold) {
white+=1;
}
}
}
return white / (img.getWidth() * img.getHeight());
}
O percentual de pretos vai ser 1 - whitePercent.
PS: Nesse repositório há também uma série de outros algoritmos comuns em processamento de imagens implementados de forma bem simples:
E aqui os mesmos algoritmos utilizando recursos mais avançados do Java, como lambdas:
Talvez você queira estuda-los.