我一直在尝试弄清楚如何执行从源图像到另一图像的颜色转移。
我想创建的过滤器需要 2 张完全相同大小的图像(ImageA 和 ImageB)。滤镜生成的输出图像将颜色的所有像素从 imageA 更改为 imageB 相同像素位置的颜色。
检查图像。我需要使用 ImageA 作为源并将 ImageB 作为一种颜色 mask ,将蓝色像素更改为绿色和紫色像素。正如您所看到的,只有与绿色和紫色区域重叠的蓝色区域发生了变化(将灰色视为透明...)
我的问题是: 1)这是可行的吗? 2)我应该使用通用内核吗?根据我的理解,颜色内核也应该可以工作,但我不确定我是否可以将 2 个图像传递给颜色内核。
您能否提供内核代码示例?
在每个像素上执行的非常简单的非优化伪代码可能是这样的:
color func (source imageA, source imageB, color colorToChange) {
if imageA.currentpixel.color == colorToChange{
if imageB.getPixel(imageA.currentPixel).color not transparent{
return imageB.getPixel(imageA.currentPixel).color
}
}
return imageA.currentPixel.color
}
这是我正在使用的当前过滤器(虽然我得到了奇怪的结果)
kernel vec4 coreImageKernel(sampler image, sampler msk, __color color)
{
vec4 a = sample(image, samplerCoord(image));
if (length(a - color) == 0.0){
return sample(msk, samplerCoord(msk));
}else{
return a;
}
}
最佳答案
使用 CIKernel
是可能的,但我不相信使用简单的 CIColorKernel
,因为您需要使用两个 CIImages
。
它仍然是非常简单的代码。您需要三个输入,在您的示例中,“IMAGE A”、“IMAGE B”和要忽略的图像 B 像素颜色。由于 CoreImage 是逐像素工作的,因此您只需要处理两个图像中的当前像素即可。
基本代码是这样的:
kernel vec4 createResult(sampler imageA, sampler imageB, vec4 backgroundColor) {
vec4 pixelA = sample(imageA, samplerCoord(imageA));
vec4 pixelB = sample(imageB, samplerCoord(imageB));
if (pixelA == backgroundColor) {
return pixelA;
} else if (pixelB == backgroundColor) {
return pixelA;
} else {
return pixelB;
}
}
这是未经测试的内核代码,因此可能存在语法错误。但这是逻辑:
- 从两个图像中传入一个像素以及背景颜色
- 如果 pixelA 是背景色,则它不是“点”,所以不要更改它
- 如果 pixelB 是背景色,则它不是一行您满意的点,所以不要更改它
- 如果pixelB不是背景色,输出它
请注意,只有当两个像素都不是背景色时,才能到达项目符号 #4。
最后一点 - Apple 决定弃用 OpenGL。在 WWDC '18 之后,我花了一周时间将我的内核代码更改为 Metal 2 代码,但(还)没有成功。颜色内核?简单的。但是同时具有扭曲和一般内核的东西......与获取周围像素相关的东西仍然让我望而却步。我认为这与我编写 samplerTransform
的方式有关,但没有时间研究它。
您应该将其用作“基于金属的”内核,因为我确实复制了一个简单的传递作为 CIKernel。请注意!
关于ios - 使用 Core Image 自定义滤镜在两个图像之间实现颜色传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51594333/