我需要为我正在处理的应用程序实施红眼减少。
谷歌搜索主要提供商业最终用户产品的链接。
你知道一个好的红眼减少算法,可以在GPL应用程序中使用吗?
答案 0 :(得分: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));
}
我非常喜欢这样的结果,因为它们保持了颜色强度,这意味着眼睛的光反射不会减少。 (这意味着眼睛保持“活着”的样子。)
答案 1 :(得分:7)
答案 2 :(得分:6)
首先你需要找到眼睛! 标准方法是运行边缘检测器,然后运行霍夫变换,找到两个相同大小的圆,但可能更容易找到红色像素簇的算法。
然后您需要决定要替换它们的内容,假设图像中有足够的绿/蓝数据,您可以忽略红色通道。
OpenCV是一个非常好的图像处理免费库,它可能对你想要的东西有点过分 - 但是有很多例子和一个非常活跃的社区。 您还可以搜索对象跟踪算法,跟踪场景中的彩色对象是一个非常相似的常见问题。
答案 3 :(得分:4)
如果没有其他人提供更直接的答案,您可以随时下载the source code for GIMP,看看他们是如何做到的。
答案 4 :(得分:3)
最简单的算法,仍然是一个非常有效的算法,就是将感兴趣区域的RGB三元组的R归零。
红色消失,但其他颜色保留。
该算法的进一步扩展可能涉及将红色为主色的三元组的R值归零(R> G且R> B)。
答案 5 :(得分:3)
您可以尝试使用imagemagick - 此页面上有关如何操作的一些提示
http://www.cit.gu.edu.au/~anthony/info/graphics/imagemagick.hints
在页面上搜索红眼
答案 6 :(得分:3)
开源项目Paint.NET在C#中有一个实现。
答案 7 :(得分: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);
答案 8 :(得分: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;
}
答案 9 :(得分:0)
阅读此博客,关于红眼的检测和矫正有一个很好的解释。 Red eye correction with OpenCV and python