我正在尝试用服务器上完成的自动化过程替换在PhotoShop中完成的手动过程。目前在PhotoShop中,"颜色范围"工具用于使用"模糊度"因子选择一系列颜色,并根据过程的一部分从黑色或白色开始。
我最初的方法包括在L*a*b色彩空间中使用发光阈值,以及在候选颜色和黑/白之间使用DE94。在这两种情况下,我都选择了不应该选择的颜色和/或没有选择应该选择的颜色。
我的预感是,我应该使用圆锥体而不是球体进行选择。
谁能深入了解PhotoShop正在做什么,以及我是否朝着正确的方向前进?另外,如果有一个库可以做到这一点,那将是很棒的,我目前正在用 C 编写这个。
从我在Photoshop中看到的,该算法可能类似于以下内容:
- 定义一个计算两种颜色接近度的函数:例如,在色彩空间中使用欧几里得距离 - 即使用欧几里得距离公式计算 RGB 空间中两个像素的颜色之间的距离。
- 接下来,使用fallof函数调整每个像素的强度,比如高斯函数。您可能需要进行调整一些参数。澄清一下:你计算两个的距离RGB 空间中的像素(不是 2D 像素坐标中的距离),以及然后将其输入衰减函数,这将提供结果介于 0.0 和 1.0 之间。将当前的所有颜色分量相乘像素及其衰减函数的结果。这样做是为了图像的每个像素。
- 如果要添加效果的范围参数,只需使用每个像素再次具有相同的衰减函数,但这次喂它所选像素与当前像素之间的欧氏距离像素的 2D 空间中的像素(像素之间的距离图像上的坐标)。
如果只想选择某些像素,则无需直接将效果应用于图像中的像素,则可以将衰减值存储在 0.0 到 1.0 范围内的 double
s 矩阵中。然后,选择一个阈值,高于该阈值,您将选择给定的像素。
例如,如果坐标 (x, y) 处的步骤 2. 对于像素产生 0.8,步骤3. 产生 0.5,则坐标为 x 和 y 的矩阵元素的值应0.8*0.5=0.4
。如果选择低于 0.4 的选择阈值,则选择像素 (x, y),否则不会。
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;
}
}
我有根据的猜测是它使用的是 HSL 色彩空间,模糊度是一个参数,用于在亮度窗口中选择具有特定色调和饱和度的所有颜色(基于此)。
现在,选择可能只是进行阈值计算,以查找该窗口内的所有内容(这将是色彩空间中非常小的区域)。但是,它也可能在进行统计距离计算。如果颜色样本实际上在颜色周围取了一个窗口,则可以计算颜色方差并使用类似马氏距离计算和阈值的东西。
同样,这只是猜测,但也许它会帮助你的思考过程。
最后,虽然这个库没有直接实现这样的东西,但OpenCV有许多图像处理工具可以使实现更容易。