Рекурсивно выполнять уменьшение эффекта «красных глаз» на изображении в C#
Пример исследует пиксели в выбранном прямоугольнике и преобразует любой пиксель, который является более красным, чем зеленый или синий, в оттенки серого. Это устраняет эффект «красных глаз» в области, но также преобразует любые другие красные пиксели в оттенки серого. На картинке лица в этом примере много розоватой кожи. Розовый в основном светлый оттенок красного, поэтому программа преобразует розовую кожу в оттенки серого, если она находится в выбранном прямоугольнике.
В этой программе используется другой подход к выбору пикселей для преобразования. Когда вы нажимаете на пиксель, выполняется следующий код.
// Выполнение эффекта «красных глаз», начиная с щелчка.
private void picImage_MouseClick(object sender, MouseEventArgs e)
{
Bitmap bm = (Bitmap)picImage.Image;
RemoveRedEyeAtPoint(1, bm, e.X, e.Y);
picImage.Image = bm;
}
Этот код в основном просто вызывает следующий рекурсивный метод RemoveRedEyeAtPoint, передавая ему точку, которую вы нажали.
// Удаление красных глаз в прямоугольнике.
private void RemoveRedEyeAtPoint(int depth, Bitmap bm, int x, int y)
{
// Не повторяйте слишком глубоко.
if (depth > 100) return;
// Не делайте ничего, если этот пиксель не в основном красный.
Color clr = bm.GetPixel(x, y);
if ((clr.R <= clr.G + 10) || (clr.R <= clr.B + 10)) return;
// Удалите красные глаза в этот момент.
byte new_clr = (byte)((clr.R + clr.G + clr.B) / 3);
bm.SetPixel(x, y, Color.FromArgb(new_clr, new_clr, new_clr));
// Проверяем соседние пиксели.
int min_x = Math.Max(x - 1, 0);
int max_x = Math.Min(x + 1, bm.Width - 1);
int min_y = Math.Max(y - 1, 0);
int max_y = Math.Min(y + 1, bm.Height - 1);
for (int new_x = min_x; new_x <= max_x; new_x++)
{
for (int new_y = min_y; new_y <= max_y; new_y++)
{
if ((new_x != 0) || (new_y != 0))
RemoveRedEyeAtPoint(depth + 1, bm, new_x, new_y);
}
}
}
Этот метод вызывает себя рекурсивно, поэтому он сначала проверяет, что его глубина рекурсии не слишком глубока. Если он этого не сделал, и вы нажали на большую красную область на изображении, метод будет называть себя рекурсивно, пока не заполнит стек программы и не разбился. Этот тест просто устанавливает верхнюю границу того, сколько раз метод будет рекурсивно. (Если вам действительно нужно преобразовать огромную красную область в оттенки серого, просто щелкните по ней несколько раз.)
Далее код получает цвет своего целевого пикселя. Если этот цвет не является главным образом красным, метод возвращается. В этой версии я добавил небольшое смещение, поэтому красный компонент должен быть как минимум на 10 больше, чем зеленые компоненты синего цвета. Это не позволяет методу преобразовать пиксели, которые в основном серые, но имеют бесконечно красное, чем зеленое или синее.
Если код делает это так далеко, он преобразует целевой пиксель в оттенки серого.
Затем программа перебирает соседние пиксели и рекурсивно вызывает себя, чтобы проверить их на красные пиксели.
