Вопрос

Мне нужно реализовать уменьшение эффекта красных глаз для приложения, над которым я работаю.

Поиск в Google в основном предоставляет ссылки на коммерческие продукты для конечного пользователя.

Знаете ли вы хороший алгоритм уменьшения эффекта красных глаз, который можно было бы использовать в приложении GPL?

Это было полезно?

Решение

Я сильно опаздываю на вечеринку, но для будущих поисковиков я использовал следующий алгоритм для личного приложения, которое я написал.

Прежде всего, область для уменьшения выбирается пользователем и передается методу уменьшения эффекта красных глаз в качестве центральной точки и радиуса.Метод перебирает каждый пиксель в пределах радиуса и выполняет следующие вычисления:

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

Мне очень нравятся результаты этого, потому что они сохраняют интенсивность цвета, а это значит, что отражение света глазом не уменьшается.(Это означает, что глаза сохраняют свой "живой" вид.)

Другие советы

отличная библиотека для поиска глазами - это OpenCV.он очень богат функциями обработки изображений.смотрите также это статья с названием "Автоматическое обнаружение эффекта красных глаз" от Ильи В.Сафонов .

Сначала вам нужно найти глаза!Стандартным способом было бы запустить детектор границ, а затем преобразование Хафа, чтобы найти две окружности одинакового размера, но могут быть более простые алгоритмы для простого поиска скоплений красных пикселей.

Затем вам нужно решить, чем их заменить, предполагая, что на изображении достаточно зеленых / синих данных, вы могли бы просто проигнорировать красный канал.

OpenCV - очень хорошая бесплатная библиотека для обработки изображений, возможно, она излишня для того, что вы хотите, но в ней много примеров и очень активное сообщество.Вы также можете поискать алгоритмы отслеживания объектов, отслеживание цветного объекта в сцене - очень похожая и распространенная проблема.

Если никто другой не найдет более прямого ответа, вы всегда можете скачать исходный код для GIMP и посмотрите, как они это делают.

Самый простой алгоритм, но при этом очень эффективный, заключался бы в обнулении R тройки RGB для интересующей области.

Красный цвет исчезает, но другие цвета сохраняются.

Дальнейшее расширение этого алгоритма может включать обнуление значения R только для тех троек, где красный является доминирующим цветом (R > G и R > B).

Вы можете попробовать imagemagick - несколько советов на этой странице о том, как это сделать

http://www.cit.gu.edu.au /~энтони/информация/графика/imagemagick.подсказки

найдите "эффект красных глаз" на странице

Проект с открытым исходным кодом Paint.NET имеет реализацию на C#.

Вот решение для реализации 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);

Это более полная реализация ответа, предоставленного 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;
  }

Прочтите этот блог, там есть хорошее объяснение относительно обнаружения и коррекции эффекта красных глаз.Коррекция эффекта красных глаз с помощью OpenCV и python

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top