Gimp 的“Color to Alpha”背后的算法是什么?特征?
对于那些还不熟悉 Gimp 的“Color to Alpha”功能的人,这里是 Gimp 文档中的页面:颜色到 Alpha。它做得非常好,我很想知道 Gimp 在颜色处理方面到底是如何做到的,无论颜色可能处于哪个颜色空间。非常感谢您的任何提示。
编辑1:根据像素与关键颜色(您在“颜色到Alpha”对话框中选择的颜色)的相似性生成像素的透明度信息,就像某些人在出于某种原因删除答案之前所建议的那样,听起来像是一个很好的见解,但我认为它比这更复杂。假设我们在 0.0 到 1.0 的单位范围内估计颜色相似度,并且我们有一个像素,其颜色例如为 0.4,类似于白色(就像您在“颜色到”中选择白色一样) Alpha”对话框),因此像素的 alpha 值为 0.6,那么当生成的像素在白色背景上显示时,如何改变像素的实际颜色来补偿亮度/光度/饱和度的松散阿尔法为 0.6?
编辑2:实际上是一个更新:与第一次编辑相关的子问题已在 如何在不改变结果颜色的情况下改变像素的 alpha? 但这可能不是完整的故事,因为接下来会发生什么于Gimp 的“Color to Alpha”功能的来源并不那么简单,似乎是基于特定的算法而不是公式。
For those who aren't familiar with the Gimp's "Color to Alpha" feature yet, here is the page on it from the Gimp's documentation: Color to Alpha. It does a really good job, and I wonder much how exactly Gimp does it in terms of color manipulation, whichever color space the colors might be in. Thanks a bunch for any hints.
EDIT 1: Generating transparency information for a pixel based on its similarity to the key color (the one you select in the "Color to Alpha" dialog), like some folk suggested before removing his answer for some reason, would sound like a good insight, but I suppose it's more intricate than that. Let's assume we estimate color similarity in the unit range from 0.0 to 1.0 and we've got a pixel whose color is, for example, 0.4 similar to, say, the color of white (like you would have selected white in the "Color to Alpha" dialog) and therefore the pixel gets an alpha value of 0.6, then how would you alter the pixel's actual color to compensate the loose of brightness/luminosity/saturation when the resulting pixel is displayed against a white background with the alpha of 0.6?
EDIT 2: Actually an update: The sub-question related to the first edit has been answered in How to change the alpha of a pixel without changing the resulting color? but it's probably not the full story because what is going on in the Gimp's source for the "Color to Alpha" feature is not that simple and seems to be based on a specific algorithm rather than a formula.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我看了一下源代码,它的核心是 colortoalpha 函数。参数*a1到*a4分别是输入/输出红、绿、蓝和alpha,c1到c3是制作alpha的颜色。
当您将两种颜色 c1 和 c2 与特定的 alpha a (0 ≤ a ≤ 1) 组合时,结果是
这里我们正在执行相反的操作: 我们知道最终结果 y 和背景颜色 c2,并且想要算出c1和a。由于这是一个未指定的方程,因此有无限多个解。然而,范围 0 ≤ c1 ≤ 255 和 0 ≤ a ≤ 1 增加了解的范围。
Gimp 插件的工作方式是,对于每个像素,它最小化 alpha 值(即最大化透明度)。相反,这意味着对于每个不完全透明的结果像素(即不完全是背景颜色),RGB 分量之一是 0 或 255。
这会生成一个图像,当覆盖在指定颜色之上时,该图像将生成原始图像(没有舍入误差)并且每个像素具有最大透明度。
值得注意的是,整个过程是在 RGB 颜色空间中完成的,但也可以在其他颜色空间中执行,只要组合操作是在相同的颜色空间中完成即可。
I took a look at the source code, and the meat of it is the colortoalpha function. The parameters *a1 to *a4 are the input/output red, green, blue and alpha, respectively, and c1 to c3 is the color to make alpha.
When you're combining two colors c1 and c2 with a specific alpha a (0 ≤ a ≤ 1), the result is
Here we're doing the reverse operation: We know the end result y and the background color c2, and want to figure out c1 and a. Since this is an under-specified equation, there's an infinite amount of solutions. However, the ranges 0 ≤ c1 ≤ 255 and 0 ≤ a ≤ 1 adds bounds to the solution.
The way the Gimp plugin works is that for each pixel it minimizes the alpha value (i.e. maximizes transparency). Conversely, this means that for each resulting pixel that isn't completely transparent (i.e. was not exactly the background color), one of the RGB components is either 0 or 255.
This produces an image that when overlayed on top of the specified color will produce the original image (in absence of rounding errors) and has maximum transparency for each pixel.
It's worth noting that the whole process is done in the RGB color space, but could be performed in others as well, as long as the combining operation is done in the same color space.
我在编辑器 www.Photopea.com 的 Filter - Other - Color to Alpha 下实现了这个过滤器。结果与 GIMP 100% 相同。该算法极其简单。
想法:使用透明度值 A 将背景色 B 与前景色 F 组合,得到新颜色 N:
您知道 N(图像中的实际颜色)和 B(滤镜的参数),并且您想要恢复前景色 F 及其透明度 A。
这样做:
现在,您知道了 N、B、A。只需使用上面的公式来计算 F。
I implemented this filter into my editor www.Photopea.com under Filter - Other - Color to Alpha. The results are 100% identical to GIMP. The algorithm is extremely simple.
The idea: a background color B was combined with a foreground color F using the transparency value A, to get a new color N:
You know N (the actual color in the image) and B (the parameter of the filter), and you want to recover the foreground color F and its transparency A.
Do it like this:
Now, you know N, B, A. Just use the formula above to compute the F.
所以我研究了 GIMP 源代码...呃!我让它变得通用且可读。
不过还是相当快。
有关数学解释,请参阅Sampo 的答案。
下面是 C# 实现(可以轻松转换为 C / C++):
GIMP 的实现 (此处) 使用 RGB 颜色空间,使用 alpha 值作为 0 到 1 范围内的
float
,以及 R、G、B 作为从 0 到 255 的float
。当图像具有 JPEG 伪影时,RGB 实现会严重失败,因为它们意味着可感知的颜色偏差不显着,但绝对 R、G、B 偏差却相当显着。使用 LAB 色彩空间应该可以解决这个问题。
如果您只想从图像中删除纯色背景,颜色到 Alpha 算法并不是最佳选择。使用 LAB 色彩空间计算每个像素的色彩空间距离时,我得到了很好的结果。然后将计算出的距离应用于原始图像的 Alpha 通道。这与 Alpha 颜色之间的主要区别是像素的色调不会改变。背景删除只是将 alpha(不透明度)设置为色彩空间差异。如果前景图像中没有出现背景颜色,则效果很好。如果确实如此,则无法删除背景,或者必须使用 BFS 算法仅遍历外部像素(类似于在 GIMP 中使用魔术棒选择,然后删除选择)。
如果前景图像同时存在孔洞和颜色与背景颜色相似的像素,则无法删除背景。此类图像需要一些手动处理。
So I looked into GIMP source code... ew! I made it generic and readable.
Still quite fast though.
For math explanation see Sampo's answer.
Here's C# implementation (easy convertible to C / C++):
GIMP's implementation (here) uses RGB color space, uses alpha value as
float
with 0 to 1 range, and R, G, B asfloat
from 0 to 255.RGB implementation fails spectacularly when image has JPEG artifacts, because they mean insignificant perceivable color deviations, but quite significant absolute R, G, B deviations. Using LAB colorspace should do the trick for the case.
If you're looking just to remove solid background from the image, color to alpha algorithm is not an optimal option. I got nice results when calculated colorspace distance for each pixel using LAB colorspace. The calculated distance was then applied to alpha channel of the original image. Main difference between this and color to alpha is the hue of the pixels would not be changed. Background remove just sets alpha (opacity) to colorspace difference. It works well if background color does not occur in foreground image. If it does either the background cannot be removed, or BFS algorithm must be used to walk the outer pixels only (something like using magic wand selection in GIMP, then removing the selection).
Background cannot be removed if the foreground image has both holes and pixels in color similar to background color. Such images require some manual processing.
您需要想出一种比较颜色相似度的机制。您可以在多种颜色空间中执行此操作。 RGB 通常不是此类事物的最佳选择。但您可以使用 HSV、YCbCr 或其他一些亮度/色度空间。通常,这些空间之一中的距离会给您比 RGB 中的欧几里得距离更好的答案。获得距离后,您可以将其除以最大距离以获得百分比。作为一种可能性,该百分比将是您想要使用的 alpha 的倒数。
如果你想知道 GIMP 是如何做到的,你可以查看源码。例如,这是最近的一项代码更改< /a> 到该插件。
You need to come up with a mechanism for comparing the similarity of colors. There are a variety of color spaces in which you can do this. RGB is often not the best for this sort of thing. But you could use HSV, YCbCr, or some other luma/chroma space. Often a distance in one of those spaces will give you a better answer than a Euclidean distance in RGB. Once you have a distance, you could divide that by the maximum distance to get a percentage. That percentage would be the inverse of the alpha you want to use, as one possibility.
If you want to know how the GIMP does it, you can look at the source. For example, here's one recent code change to that plug-in.
我尽我所能将 colortoalpha 方法从 gimp 翻译成 C#。问题是 RGBA 值在 ImageSharp 等库中被视为每个通道的字节。有些转换在转换过程中会丢失数据,但我尽力保留尽可能多的数据。这使用 ImageSharp 进行图像突变。 ImageSharp 是完全托管的,因此它可以跨平台工作。它也很快。整个方法的运行时间约为 10 毫秒(不到 10 毫秒)。
以下是C#实现的代码:
I translated the colortoalpha method from gimp to C# the best I could. The problem is RGBA values are taken as bytes for each channel in a library like ImageSharp. Some of the conversions are losing data during conversion but I tried my best to retain as much as I could. This uses ImageSharp for image mutation. ImageSharp is fully managed so it will work across platforms. Its also fast. This entire methods runs in around ~10ms (less than 10ms).
Here is the code for C# implementation:
我遇到了同样的问题,并在 Python 中实现了 colortoalpha ,这样我就可以轻松地编写批处理操作的脚本。它似乎与 GIMP 输出完美匹配!
您可以在这里找到完整的源代码: https://github.com/unicilindro /color2alpha/blob/main/color2alpha.py
I faced the same problem and implemented the
colortoalpha
in Python, so that I can easily script batch operations. It seems to match GIMP output perfectly!You can find the full source code here: https://github.com/unicilindro/color2alpha/blob/main/color2alpha.py
我最近尝试弄清楚 Gimp 的颜色擦除混合模式背后的数学原理(基本上与颜色到 Alpha 过滤器相同),这就是我最终得到的结果:
[C++ 代码]
工作原理。]
[详细说明其 其要点是:
由于底层完全不透明,法线混合只是线性插值。由于两个图层都完全不透明,“颜色擦除”是“法线混合”的逆操作。
在您选择的颜色空间中,追踪一条穿过顶部颜色和底部颜色的线。从底部开始,沿着远离顶部的线走,直到遇到单位立方体的边界(即色域的限制)。那一点就是你得到的颜色。其不透明度是顶部到底部的距离与顶部到结果的距离的比例。
I recently tried figuring out the math behind Gimp's Colour Erase blend mode (basically the same as the Colour to Alpha filter), and this is what I ended up with:
[C++ Code]
[Detailled explanations of how it works.]
The gist of it is:
With a fully opaque bottom layer, Normal Blend is just a linear interpolation. With both layers fully opaque, Colour Erase is the inverse operation of that Normal Blend.
In your colour space of choice, trace a line that passes through both the Top and Bottom colours. Starting from Bottom, walk that line away from Top until it you meet the border of the unit cube (i.e, the limit your colour gamut). That point is your resulting colour. Its opacity is the proportion of the distance top-bottom, compared to the distance top-result.