红眼消除算法

Posted

技术标签:

【中文标题】红眼消除算法【英文标题】:Red eye reduction algorithm 【发布时间】:2010-09-13 02:49:10 【问题描述】:

我需要为我正在开发的应用程序实现红眼消除。

谷歌搜索主要提供商业最终用户产品的链接。

您知道可以在 GPL 应用程序中使用的良好吗?

【问题讨论】:

【参考方案1】:

我在这里参加聚会已经很晚了,但是对于未来的搜索者,我已将以下算法用于我编写的个人应用程序。

首先,要减少的区域由用户选择,并作为中心点和半径传递给红眼减少方法。该方法循环遍历半径内的每个像素并进行以下计算:

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

我真的很喜欢这个结果,因为它们保持了颜色强度,这意味着眼睛的光反射没有减少。 (这意味着眼睛保持“活”的样子。)

【讨论】:

您也可以在用户提供的最大半径的点击点处使用“魔杖”选择工具。【参考方案2】:

寻找眼睛的好图书馆是openCV。 它具有非常丰富的图像处理功能。 另请参阅 Ilia V. Safonov 题为“自动红眼检测”的 this 论文。

【讨论】:

【参考方案3】:

首先你需要找到眼睛! 标准方法是运行边缘检测器,然后运行 ​​Hough 变换来找到两个相同大小的圆,但可能有更简单的算法可以简单地找到红色像素的集群。

然后您需要决定用什么替换它们,假设图像中有足够的绿色/蓝色数据,您可以简单地忽略红色通道。

OpenCV 是一个非常好的免费图像处理库,它可能对你想要的东西来说有点过头了——但它有很多例子和一个非常活跃的社区。 您还可以搜索对象跟踪算法,跟踪场景中的彩色对象是一个非常相似且常见的问题。

【讨论】:

【参考方案4】:

如果没有其他人提供更直接的答案,您可以随时下载the source code for GIMP 看看他们是如何做到的。

【讨论】:

【参考方案5】:

最简单且仍然非常有效的算法是将感兴趣区域的 RGB 三元组的 R 归零。

红色消失,但保留其他颜色。

此算法的进一步扩展可能涉及仅将红色为主色(R > G 和 R > B)的三元组的 R 值归零。

【讨论】:

【参考方案6】:

您可以尝试使用 imagemagick——此页面上的一些提示,说明如何做到这一点

http://www.cit.gu.edu.au/~anthony/info/graphics/imagemagick.hints

在页面上搜索红眼

【讨论】:

【参考方案7】:

开源项目Paint.NET 有一个 C# 实现。

【讨论】:

我不认为来源是可得的了。【参考方案8】:

这里是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());
            


        
    

是从open 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);

【讨论】:

【参考方案9】:

这是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;
  

【讨论】:

【参考方案10】:

阅读此博客,关于红眼的检测和校正有一个很好的解释。 Red eye correction with OpenCV and python

【讨论】:

以上是关于红眼消除算法的主要内容,如果未能解决你的问题,请参考以下文章

技术分享| anyRTC回声消除算法进化

爱消除游戏中的消除算法

爱消除游戏中的消除算法

消除光流算法中的噪声?

MATLAB教程案例30基于MATLAB的图像阴影检测和消除算法的实现

回声消除(Acoustic Echo Cancellation)中遇到的几个常见问题思考