11

我正在尝试用在服务器上完成的自动化过程替换在 PhotoShop 中完成的手动过程。目前在 PhotoShop 中,“颜色范围”工具用于使用“模糊度”因素选择一系列颜色,并根据处理的部分从黑色或白色开始。

我最初的方法包括在 L*a*b 颜色空间中使用发光阈值以及在候选颜色和黑/白之间使用 DE94。在这两种情况下,我都选择了不应该选择的颜色和/或没有选择应该选择的颜色。

我的直觉是我应该使用圆锥体而不是球体来进行选择。

任何人都可以深入了解 PhotoShop 正在做什么以及我是否朝着正确的方向前进?另外,如果有一个库可以做到这一点,那将是很棒的,我目前正在用 C 语言编写它。

4

3 回答 3

5

从我在 Photoshop 中看到的情况来看,该算法可能类似于以下内容:

  1. 定义一个计算两种颜色接近度的函数:例如,在色彩空间中使用欧几里得距离——即使用欧几里得距离公式计算RGB空间中两个像素的颜色之间的距离。
  2. 接下来,通过使用 fallof 函数(例如Gaussian 函数)来调整每个像素的强度。您可能需要调整一些参数。澄清一下:您计算 RGB 空间中两个像素的距离(而不是 2D 像素坐标中的距离),然后将其输入衰减函数,该函数将提供 0.0 到 1.0 之间的结果。将当前像素的所有颜色分量与其衰减函数的结果相乘。对图像的每个像素执行此操作。
  3. 如果要添加效果的范围参数,只需再次对每个像素使用相同的衰减函数,但这次将所选像素与像素的 2D 空间中当前像素之间的欧几里得距离(像素之间的距离图像上的坐标)。

如果您只想选择某些像素,那么您可以将衰减值存储在double0.0 到 1.0 范围内的 s 矩阵中,而不是直接在图像中的像素上应用效果。然后,选择一个阈值,高于该阈值您将选择给定像素。

例如,如果步骤 2. 对于坐标 (x, y) 处的像素产生 0.8,步骤 3. 产生 0.5,则坐标 x 和 y 的矩阵元素的值应该是0.8*0.5=0.4。如果您选择低于 0.4 的选择阈值,您将选择像素 (x, y),否则您不会。

于 2013-11-19T14:56:39.553 回答
3

我不知道 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()

这是来自 gimp 源的 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;
    }
}
于 2013-11-14T20:46:53.327 回答
2

我有根据的猜测是它使用的是 HSL 颜色空间,而模糊度是一个参数,它在亮度窗口中选择具有特定色调和饱和度的所有颜色(基于this)。

现在选择可能只是在进行阈值计算,以查找该窗口内的所有内容(这将是色彩空间中的一个非常小的区域)。但是,它也可能在进行统计距离计算。如果颜色样本实际上对颜色周围的窗口进行小采样,则可以计算颜色方差并使用诸如马氏距离计算和阈值之类的东西。

同样,这只是猜测,但也许它会帮助你的思考过程。

最后,虽然这个库没有直接实现类似的东西,但OpenCV有许多图像处理工具可以使实现更容易。

于 2013-11-14T19:56:15.450 回答