如何实现带颜色的自适应阈值滤波器
How to achieve adaptive threshold filter with color
我正在寻找一种类似于自适应阈值化但可以保持颜色的算法。我正在尝试拍摄这样的图像:
让它看起来像这样:
如果重要的话,我在 ios 工作。
阈值处理总是会产生二进制掩码,即低于(局部自适应)阈值的像素和高于阈值的像素。如果你有那个蒙版,你当然可以保留原始图像的颜色信息。
因此,一种简单的方法将导致以下工作流程:
- 具有红色、绿色、蓝色值的图像
- 通过添加红+绿+蓝生成灰度图像
- 通过灰度图像上的局部自适应阈值创建灰度图像掩码
- 对具有红色、绿色、蓝色值的原始图像应用蒙版
或者:
- 具有红色、绿色、蓝色值的图像
- 为只有红色(或分别为绿色或蓝色)值的图像创建三个蒙版
- 组合所有三个掩码(逻辑与)以获得单个掩码
- 对具有红色、绿色、蓝色值的原始图像应用蒙版
这两种方式可能并不理想,但可能已经适用于大量情况,包括问题中的示例。
这是一个在您的示例图像上运行良好的 CIKernel
kernel vec4 coreImageKernel (sampler i)
{
vec2 dc = destCoord();
// center pixel color
vec4 c = unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,0.0))));
// for a whiteboard, the max of a neighborhood is likely to be the color
// of the whiteboard
vec4 cmax = c;
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(10.0,0.0)))), cmax);
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(-10.0,0.0)))), cmax);
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,10.0)))), cmax);
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,-10.0)))), cmax);
// normalize the center color according to the whiteboard color
vec4 r = c / cmax;
return premultiply(r);
}
那么这是如何工作的呢?那么内核的第一部分,即计算 cmax 的部分,就是计算白板的局部颜色。这是棘手的部分。基本上它确定(大约)白板在没有标记的情况下的颜色。为此,内核做出三个关键假设:
- 白板颜色局部差异不大
- 标记从白板颜色中减去
- 对于每个像素,它或附近的像素(10 个像素 N、S、E 或 W)没有任何标记。实际上,内核假设标记线比 10 像素更细,尽管可以调整该常量)
cmax 的输出如下所示:
一旦局部白板颜色近似,只需将当前像素除以局部背景即可。这类似于从图像中移除偏色的方式。
此算法类似于 WWDC13 Core Image 演示文稿中的 Haze Removal 示例。在该示例中,减去局部最小值以生成更黑的黑色。在这种情况下,局部最大值被划分为更白的白色。
:
我正在寻找一种类似于自适应阈值化但可以保持颜色的算法。我正在尝试拍摄这样的图像:
让它看起来像这样:
如果重要的话,我在 ios 工作。
阈值处理总是会产生二进制掩码,即低于(局部自适应)阈值的像素和高于阈值的像素。如果你有那个蒙版,你当然可以保留原始图像的颜色信息。
因此,一种简单的方法将导致以下工作流程:
- 具有红色、绿色、蓝色值的图像
- 通过添加红+绿+蓝生成灰度图像
- 通过灰度图像上的局部自适应阈值创建灰度图像掩码
- 对具有红色、绿色、蓝色值的原始图像应用蒙版
或者:
- 具有红色、绿色、蓝色值的图像
- 为只有红色(或分别为绿色或蓝色)值的图像创建三个蒙版
- 组合所有三个掩码(逻辑与)以获得单个掩码
- 对具有红色、绿色、蓝色值的原始图像应用蒙版
这两种方式可能并不理想,但可能已经适用于大量情况,包括问题中的示例。
这是一个在您的示例图像上运行良好的 CIKernel
kernel vec4 coreImageKernel (sampler i)
{
vec2 dc = destCoord();
// center pixel color
vec4 c = unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,0.0))));
// for a whiteboard, the max of a neighborhood is likely to be the color
// of the whiteboard
vec4 cmax = c;
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(10.0,0.0)))), cmax);
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(-10.0,0.0)))), cmax);
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,10.0)))), cmax);
cmax = max(unpremultiply(sample(i, samplerTransform(i,dc+vec2(0.0,-10.0)))), cmax);
// normalize the center color according to the whiteboard color
vec4 r = c / cmax;
return premultiply(r);
}
那么这是如何工作的呢?那么内核的第一部分,即计算 cmax 的部分,就是计算白板的局部颜色。这是棘手的部分。基本上它确定(大约)白板在没有标记的情况下的颜色。为此,内核做出三个关键假设:
- 白板颜色局部差异不大
- 标记从白板颜色中减去
- 对于每个像素,它或附近的像素(10 个像素 N、S、E 或 W)没有任何标记。实际上,内核假设标记线比 10 像素更细,尽管可以调整该常量)
cmax 的输出如下所示:
一旦局部白板颜色近似,只需将当前像素除以局部背景即可。这类似于从图像中移除偏色的方式。
此算法类似于 WWDC13 Core Image 演示文稿中的 Haze Removal 示例。在该示例中,减去局部最小值以生成更黑的黑色。在这种情况下,局部最大值被划分为更白的白色。