algoritmo de redução de olhos vermelhos
-
02-07-2019 - |
Pergunta
Eu preciso implementar redução de olhos vermelhos para uma aplicação que estou trabalhando.
pesquisando principalmente fornece links para produtos para o usuário final comercial.
Você conhece um algoritmo de redução de olho vermelho bom, que poderia ser usado em um aplicativo de GPL?
Solução
Estou muito atrasado para a festa aqui, mas para os futuros pesquisadores Eu usei o seguinte algoritmo para uma aplicação pessoal que eu escrevi.
Em primeiro lugar, a região a reduzir é seleccionado pelo utilizador e transmitida para o olho vermelho reduzindo método como um centro e um raio. O método percorre cada pixel dentro do raio e faz o seguinte cálculo:
//Value of red divided by average of blue and green:
Pixel pixel = image.getPixel(x,y);
float redIntensity = ((float)pixel.R / ((pixel.G + pixel.B) / 2));
if (redIntensity > 1.5f) // 1.5 because it gives the best results
{
// reduce red to the average of blue and green
bm.SetPixel(i, j, Color.FromArgb((pixel.G + pixel.B) / 2, pixel.G, pixel.B));
}
Eu realmente gosto os resultados desta porque eles mantêm a intensidade da cor, o que significa a reflexão da luz do olho não seja reduzido. (Isto significa olhos manter seu olhar "vivo".)
Outras dicas
uma grande biblioteca para encontrar olhos é openCV . é muito rica, com funções de processamento de imagem. ver também este papel com o título de "detecção de olhos vermelhos automática" de Ilia V. Safonov.
Primeiro você precisa encontrar os olhos! A forma padrão seria executar um detector de borda e, em seguida, a transformada de Hough para encontrar dois círculos do mesmo tamanho, mas pode haver algoritmos mais fácil para simplesmente encontrar aglomerados de pixels vermelhos.
Em seguida, você precisa decidir o que para substituí-los com, assumindo que não é bastante verde / dados azuis na imagem que você poderia simplesmente ignorar o canal vermelho.
OpenCV é uma boa biblioteca livre para processamento de imagem, pode ser um exagero para o que você quer - mas tem um monte de exemplos e uma comunidade muito ativa. Você também pode procurar algoritmos objeto de monitoramento, o acompanhamento de um objeto colorido em uma cena é um problema muito similair e comum.
Se ninguém mais vem com uma resposta mais direta, você pode sempre baixar o código fonte para GIMP e ver como eles fazem isso.
O algoritmo mais simples, e ainda um que é muito eficaz seria a zero o R do RGB triplo para a região de interesse.
Os desaparece vermelha, mas as outras cores são preservadas.
Uma nova prorrogação desse algoritmo pode envolver zerar o valor R apenas para os triplos, onde o vermelho é a cor dominante (R> G e R> B).
Você pode tentar imagemagick - algumas dicas nesta página para saber como fazer isso
http://www.cit.gu. edu.au/~anthony/info/graphics/imagemagick.hints
procurar olhos vermelhos na página
O projeto de código aberto Paint.NET tem uma implementação em C #.
Aqui está a solução aplicação java
public void corrigirRedEye(int posStartX, int maxX, int posStartY, int maxY, BufferedImage image) {
for(int x = posStartX; x < maxX; x++) {
for(int y = posStartY; y < maxY; y++) {
int c = image.getRGB(x,y);
int red = (c & 0x00ff0000) >> 16;
int green = (c & 0x0000ff00) >> 8;
int blue = c & 0x000000ff;
float redIntensity = ((float)red / ((green + blue) / 2));
if (redIntensity > 2.2) {
Color newColor = new Color(90, green, blue);
image.setRGB(x, y, newColor.getRGB());
}
}
}
}
Sendo os parâmetros obtidos a partir de dois rectângulos detectados por uma aplicação como cv aberto (isto deve ser um rectângulo envolvendo a posição do olho)
int posStartY = (int) leftEye.getY();
int maxX = (int) (leftEye.getX() + leftEye.getWidth());
int maxY = (int) (leftEye.getY() + leftEye.getHeight());
this.corrigirRedEye(posStartX, maxX, posStartY, maxY, image);
// right eye
posStartX = (int) rightEye.getX();
posStartY = (int) rightEye.getY();
maxX = (int) (rightEye.getX() + rightEye.getWidth());
maxY = (int) (rightEye.getY() + rightEye.getHeight());
this.corrigirRedEye(posStartX, maxX, posStartY, maxY, image);
Esta é uma implementação mais completa da resposta dada pelo Benry:
using SD = System.Drawing;
public static SD.Image ReduceRedEye(SD.Image img, SD.Rectangle eyesRect)
{
if ( (eyesRect.Height > 0)
&& (eyesRect.Width > 0)) {
SD.Bitmap bmpImage = new SD.Bitmap(img);
for (int x=eyesRect.X;x<(eyesRect.X+eyesRect.Width);x++) {
for (int y=eyesRect.Y;y<(eyesRect.Y+eyesRect.Height);y++) {
//Value of red divided by average of blue and green:
SD.Color pixel = bmpImage.GetPixel(x,y);
float redIntensity = ((float)pixel.R / ((pixel.G + pixel.B) / 2));
if (redIntensity > 2.2f)
{
// reduce red to the average of blue and green
bmpImage.SetPixel(x, y, SD.Color.FromArgb((pixel.G + pixel.B) / 2, pixel.G, pixel.B));
pixel = bmpImage.GetPixel(x,y); // for debug
}
}
}
return (SD.Image)(bmpImage);
}
return null;
}
Leia este blog, há uma boa explicação sobre a detecção e correção de olhos vermelhos. correção de olho vermelho com OpenCV e python