2014-10-21 1 views
1

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

Это хороший результат (до и после):

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

чем ниже порог, тем больше гр een появляется на коже.

Мне было интересно, был ли альтернативный метод тому, что я сейчас делаю, чтобы изменить красные пиксели?

int lcount = 0; 
for(int y=0;y<lcroppedEye.rows;y++) 
{ 
    for(int x=0;x<lcroppedEye.cols;x++) 
    { 
     double b = lcroppedEye.at<cv::Vec3b>(y, x)[0]; 
     double g = lcroppedEye.at<cv::Vec3b>(y, x)[1]; 
     double r = lcroppedEye.at<cv::Vec3b>(y, x)[2]; 

     double redIntensity = r/((g + b)/2); 

     //currently causes issues with non-red-eye images 
     if (redIntensity >= 1.8) 
     { 
      double newRedValue = (g + b)/2; 
      cv::Vec3b pixelColor(newRedValue,g,b); 
      lroi.at<cv::Vec3b>(cv::Point(x,y)) = pixelColor; 
      lcount++; 
     } 
    } 
} 

EDIT: я могу возможно добавить в проверку, чтобы убедиться, что новые значения RGB являются достаточно низкими, и поэтому R, G, значения B подобны/близкие значения, так черные/серые пиксели выписаны только ... или иметь диапазон значений RGB (зеленоватый), которые не допускаются ... это сработает?

+1

Ах, стена картин! Они напугали меня всерьез;) Пожалуйста, подумайте о следующем вопросе, обрезая их в нужные части. – sschrass

+0

Извините @SatelliteSD. :/ – LKB

+0

opencv имеет встроенный детектор глаз. вы можете замаскировать изображение и работать только в областях глаз. – baci

ответ

3

Регулировка цвета в пространстве RGB имеет оговорки, подобные этим зеленоватым областям, с которыми вы столкнулись. Преобразуйте значения R, G, B в лучшее цветовое пространство, например, HSV или LUV.

Предлагаю вам перейти на HSV для обнаружения и изменения цветов красных глаз. R/(G + B) не является хорошим способом вычисления интенсивности красного. Это означает, что вы вызываете (R = 10, G = 1, B = 0) очень красный цвет, но он смертельно черный. Посмотрите на ниже сравнения:

colors

Таким образом, вы бы лучше проверить, насыщенность и значение имеют высокие значения, которые в случае с цветом красных глаз. Если вы столкнулись с другими цветами высокой интенсивности, вы можете проверить, что оттенок находится в диапазоне примерно от [0-20] и [340-359]. Но без этого вы по-прежнему в безопасности против самого белого, так как он имеет очень низкую насыщенность, и вы все равно не будете выбирать белые области.

Это было для выбора, для изменения цвета, снова лучше не использовать RGB, поскольку изменение в этом пространстве не является линейным, поскольку мы воспринимаем цвета. Глядя на изображение выше, вы можете видеть, что снижение насыщенности и значения будет хорошим началом. Но вы можете поэкспериментировать с ним и посмотреть, что выглядит лучше. Может быть, вы будете в порядке с темно-серым всегда, это означало бы, что Saturation будет равна нулю, и немного уменьшите значение. Вы можете подумать, что темный коричневый цвет будет лучше, пойдите для низкой насыщенности и значения, но настройте Хью примерно на 30 градусов.

Ссылки, которые могут вам помочь:

  1. Converting color values in OpenCV
  2. An online tool to experiment with RGB and HSV colors
3

Это может быть лучше, чтобы изменить

double redIntensity = r/((g + b)/2); 

в

double redIntensity = r/((g+b+1)/2); 

потому, что г + Ь может быть равен 0, и вы получите NAN.

Также возьмите alook в cv :: floodfill method.

+1

Хороший улов за нулевой разрыв. – Surt

1
  • Подготовьте маску того же размера, что и изображение lcroppedEye, которое изначально было черным (я буду называть это изображение maskImage здесь и далее).
  • Для каждого пикселя в lcroppedEye (строка, col), которые передают ваше условие (redIntensity> = 1.8), установите для параметра maskImage (row, col) белый.
  • Когда вы закончите со всеми пикселями в lcroppedEye, maskImage будет иметь все похожие на redeye пиксели в белом цвете.
  • Если вы выполняете анализ подключенных компонентов на этой маске, вы должны иметь возможность отфильтровывать другие регионы, рассматривая круг или дискообразные функции и т. Д.
  • Теперь вы можете использовать эту маску в качестве маски для применения цвета Переход к ROI исходного изображения

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

1

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

новыйRedValue = (g + b)/2; newGreenValue = newRedValue; newBlueValue = newRedValue;

Даже если вы обнаружите неправильную красную область, ее обесцвечивание даст лучший результат, чем зеленоватая область. Вы также можете использовать morphological closing operations (используя элемент структурирования кругов), чтобы избежать пробелов в маске красной области. Таким образом, вам нужно выполнить 3 этапа: 1. найти красные области и создать маску для этого. 2. выполнить морфологические операции закрытия маски красной области. 3. обесцветить изображение с помощью этой маски.

И да, не используйте «r/((g + b)/2), так как это может привести к делению нулевой ошибкой.

1

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

// first pass, getting the highest red value 
int highRed = 0; 
cv::Point redPos = cv::Point(0,0); 

int lcount = 0; 
for(int y=0;y<lcroppedEye.rows;y++) 
{ 
    for(int x=0;x<lcroppedEye.cols;x++) 
    { 
     double r = lcroppedEye.at<cv::Vec3b>(y, x)[2]; 

     if (redIntensity > highRed) 
     { 
      highRed = redIntensity ; 
      redPos = cv::Point(x,y); 
     } 
    } 
} 

// decide if its red enough, need to find a good minRed value. 
if (highRed < minRed) 
    return; 

Оригинальный код здесь со следующими изменениями.

// avoid division by zero, code from @AndreySmorodov 
    double redIntensity = r/((g+b+1)/2); 

    // add check for actual red colour. 
    if (redIntensity >= 1.8 && r > highRed*0.75) 
    // potential add check for low absolute r/b values. 
    { 
     double newRedValue = (g + b)/2; 
     cv::Vec3b pixelColor(newRedValue,g,b); 
     lroi.at<cv::Vec3b>(cv::Point(x,y)) = pixelColor; 
     lcount++; 
    } 
}