2013-11-14 3 views
10

Я пытаюсь заменить ручной процесс, выполняемый в PhotoShop, автоматическим процессом, выполняемым на сервере. В настоящее время в PhotoShop инструмент «Цветовой диапазон» используется для выбора диапазона цветов с использованием фактора «Fuzziness» и начиная с черного или белого цвета в зависимости от части процесса.Эмуляция алгоритма «Цветовой диапазон» PhotoShop

Мои первоначальные подходы, включающие как пороговые значения для люминесценции в цветовом пространстве L * a * b, так и DE94 между цветом кандидата и черным/белым. В обоих случаях я выбрал цвета, которые не следует выбирать и/или не выбирать цвета, которые должны быть.

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

Может ли кто-нибудь дать представление о том, что делает PhotoShop, и если я направляюсь в правильном направлении? Кроме того, если есть библиотека, чтобы сделать это, это было бы потрясающе. Я сейчас пишу это в C.

+0

Что касается языка выбора, я настоятельно рекомендую Matlab по крайней мере для прототипирования. В C++ есть некоторые библиотеки STL, которые также могут помочь. – ElKamina

+1

Я бы попытался обработать компонент r, g, b как вектор 3d. Затем вы можете найти расстояние между целевым и исходным цветами, вычислив длину вектора между этими двумя точками. Gimp имеет аналогичную функциональность для Photoshop. Вы всегда можете понюхать его источник для проверенного подхода. – enhzflep

ответ

2

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

Теперь выбор может просто сделать расчет порога, находя все, что находится внутри этого окна (которое было бы очень маленькой областью в цветовом пространстве). Однако он также может выполнять статистический расчет расстояния. Если образец цвета на самом деле маленький, образец отображает окно вокруг цвета, вы можете рассчитать дисперсию цвета и использовать что-то вроде вычисления расстояния и порога от Mahalanobis.

Опять же, это всего лишь гипотеза, но, возможно, это поможет вашему процессу мышления.

Наконец, в то время как эта библиотека не имеет чего-то подобного непосредственно, OpenCV имеет множество инструментов обработки изображений, которые облегчили бы реализацию.

2

Я не знаю, как Photoshop делает это под капотом, но это просто RGB в XYZ 3d вектор подход:

rDelta = pixel.r - color.r 
gDelta = pixel.g - color.g 
bDelta = pixel.b - color.b 
fuzziness = 0.1 // anything 0 to 1.0 
maxDistance = fuzziness * 441 // max distance, black -> white 

distance = Math.sqrt(rDelta * rDelta + gDelta * gDelta + bDelta * bDelta) 

if (distance < maxDistance) includePixel() 
else dontIncludePixel() 

Это функция pixel_difference от источника вкладной:

https://github.com/GNOME/gimp/blob/125cf2a2a3e1e85172af25871a2cda3638292fdb/app/core/gimpimage-contiguous-region.c#L290

static gfloat 
pixel_difference (const gfloat  *col1, 
        const gfloat  *col2, 
        gboolean    antialias, 
        gfloat    threshold, 
        gint     n_components, 
        gboolean    has_alpha, 
        gboolean    select_transparent, 
        GimpSelectCriterion select_criterion) 
{ 
    gfloat max = 0.0; 

    /* if there is an alpha channel, never select transparent regions */ 
    if (! select_transparent && has_alpha && col2[n_components - 1] == 0.0) 
    return 0.0; 

    if (select_transparent && has_alpha) 
    { 
     max = fabs (col1[n_components - 1] - col2[n_components - 1]); 
    } 
    else 
    { 
     gfloat diff; 
     gint b; 

     if (has_alpha) 
     n_components--; 

     switch (select_criterion) 
     { 
     case GIMP_SELECT_CRITERION_COMPOSITE: 
      for (b = 0; b < n_components; b++) 
      { 
       diff = fabs (col1[b] - col2[b]); 
       if (diff > max) 
       max = diff; 
      } 
      break; 

     case GIMP_SELECT_CRITERION_R: 
      max = fabs (col1[0] - col2[0]); 
      break; 

     case GIMP_SELECT_CRITERION_G: 
      max = fabs (col1[1] - col2[1]); 
      break; 

     case GIMP_SELECT_CRITERION_B: 
      max = fabs (col1[2] - col2[2]); 
      break; 

     case GIMP_SELECT_CRITERION_H: 
      { 
      /* wrap around candidates for the actual distance */ 
      gfloat dist1 = fabs (col1[0] - col2[0]); 
      gfloat dist2 = fabs (col1[0] - 1.0 - col2[0]); 
      gfloat dist3 = fabs (col1[0] - col2[0] + 1.0); 

      max = MIN (dist1, dist2); 
      if (max > dist3) 
       max = dist3; 
      } 
      break; 

     case GIMP_SELECT_CRITERION_S: 
      max = fabs (col1[1] - col2[1]); 
      break; 

     case GIMP_SELECT_CRITERION_V: 
      max = fabs (col1[2] - col2[2]); 
      break; 
     } 
    } 

    if (antialias && threshold > 0.0) 
    { 
     gfloat aa = 1.5 - (max/threshold); 

     if (aa <= 0.0) 
     return 0.0; 
     else if (aa < 0.5) 
     return aa * 2.0; 
     else 
     return 1.0; 
    } 
    else 
    { 
     if (max > threshold) 
     return 0.0; 
     else 
     return 1.0; 
    } 
} 
+0

Это звучит как алгоритм, указанный в вопросе, используя RGB вместо цветового пространства LAB - LAB, вероятно, лучше для этого приложения. Я также предлагаю возведение в квадрат 'maxDistance' и сброс вызова' sqrt' для скорости. –

+0

Согласен, использование двух квадратов будет быстрее. Я хотел бы сохранить код как есть, но для ясности. – hunterloftis

5

Из того, что я видел в Photoshop, алгоритм может, вероятно, будет похож на следующее:

  1. Определите функцию, которая вычисляет близость двух цветов: например, используйте эвклидово расстояние в цветовом пространстве, то есть вычислите расстояние между цветами двух пикселей в пространстве RGB, используя Euclidean distance formula.
  2. Затем отрегулируйте интенсивность каждого пикселя, используя функцию fallof, , такую ​​как Gaussian function. Вероятно, вам нужно будет настроить параметры . Чтобы уточнить: вы вычисляете расстояние до двух пикселей в пространстве RGB (а не на расстоянии в 2D пиксельных координатах) и , затем подайте это на функцию falloff, которая даст результат между 0.0 и 1.0. Умножьте все цветовые компоненты текущего пикселя с результатом функции falloff для него. Сделайте это для каждого пикселя изображения.
  3. Если вы хотите добавить параметр диапазона эффекта, просто использовать же функцию Falloff для каждого пикселя, но в этот раз кормить его евклидово расстояние между выбранным пикселем и текущим пикселя в 2D пространстве пикселей (расстояние между пикселями координаты на изображении).

Если вы хотите выбрать только определенные пиксели, то вместо применения эффекта непосредственно на пиксели в изображении вы можете хранить значения Falloff в матрице double с в диапазоне от 0,0 до 1,0. Затем выберите пороговое значение, выше которого вы выберете данный пиксель.

Например, если шаг 2. для пикселя в координате (x, y) дал 0,8, а шаг 3 дал 0,5, то значение матричного элемента с координатами x и y должно быть 0.8*0.5=0.4. Если вы выбрали порог выбора ниже 0,4, вы должны выбрать пиксель (x, y), иначе вы бы этого не сделали.

+0

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

+0

Я отредактировал свой ответ, чтобы включить это. –

Смежные вопросы