2008-09-25 74 views
40

我需要爲我正在處理的應用程序實施紅眼消除。紅眼消除算法

谷歌搜索主要提供商業終端用戶產品的鏈接。

你知道一個好的紅眼減少算法,可以在GPL應用程序中使用嗎?

回答

43

我對這裏的派對遲到了,但對於未來的搜索者,我使用了以下算法來編寫我寫的個人應用程序。

首先,要縮小的區域由用戶選擇,並作爲中心點和半徑傳遞給紅眼減少方法。該方法循環通過該半徑範圍內的每個像素,並執行以下計算:

//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)); 
} 

我很喜歡的這個結果,因爲它們保持顏色強度,這意味着眼睛的光反射不會降低。 (這意味着眼睛保持「活力」的樣子。)

+0

您也可以在點擊點使用用戶提供的最大半徑的「魔棒」選擇工具。 – rafaelcastrocouto 2017-02-19 13:19:54

3

最簡單的算法,仍然非常有效的一種方法是將感興趣區域的RGB三元素的R值歸零。

紅色消失,但其他顏色保留。

該算法的進一步擴展可能涉及將R值僅歸零,其中紅色是主色(R> G和R> B)。

4

如果沒有人提供更直接的答案,您可以隨時下載the source code for GIMP並查看他們是如何做到的。

6

首先你需要找到眼睛! 標準的方法是運行邊緣檢測器,然後進行Hough變換以找到兩個相同大小的圓,但是可能有更簡單的算法來簡單地查找紅色像素的簇。

然後,您需要決定如何替換它們,假設圖像中有足夠的綠色/藍色數據,您可以忽略紅色通道。

OpenCV是一個非常好的圖像處理免費庫,它可能是你想要的矯枉過正 - 但有很多的例子和一個非常活躍的社區。 您也可以搜索對象跟蹤算法,跟蹤場景中的彩色對象是一個非常相似和常見的問題。

3

開源項目Paint.NET在C#中有一個實現。

+0

我不認爲源是可以達到更多。 – 2009-04-05 09:37:04

7

一個偉大的圖書館找到眼睛openCV。 它具有豐富的圖像處理功能。 另請參閱this來自Ilia V. Safonov的標題爲「自動紅眼檢測」的論文。

2

這裏是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()); 
      } 


     } 
    } 
} 

是由通過類似開放CV的應用程序檢測到的兩個矩形檢索到的參數(這應該是涉及眼睛位置的矩形)

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); 
1

這是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; 
    }