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?

Foi útil?

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top