我有一组消除锯齿的灰度PNG图像 . 我需要知道如何以编程方式恢复抗锯齿效果并再次获得锐利边缘 .
我正在使用GDI,但我对代码不太感兴趣 . 如果可以构建这样的矩阵,我需要一个算法,可能是卷积滤波器 .
灰度图像(应该)仅包含6种颜色(或不同的灰色阴影) . 这样我以后可以使用Color-Lookup过滤器重新着色它们 . 但是,当图像保存时,Photoshop会自动应用抗锯齿功能,使边缘模糊(因为启用了双立方插补模式) . 我需要恢复这种效果 .
这是一个例子:
这是Photoshop的截图
有人建议我应该使用Sharpen过滤器,所以我在photoshop上尝试过 . 以下是它的外观:
即使外边缘很细,2种不同颜色相遇的边缘也会显示出瑕疵 .
编辑:
这就是我最终做到的方式 . 这是非常即兴的,可能会做得更好,更快,但我找不到更好的解决方案 .
我们的想法是迭代每个像素,得到它的直接邻居并将它的颜色与它们的颜色进行比较 . 如果它由相同颜色的至少2个像素支持,则它检查相邻像素是否也被支持 . 如果没有,它用自己的邻居像素替换 .
码:
private static void Resample(Bitmap bmp)
{
// First we look for the most prominent colors
// i.e. They make up at least 1% of the image
Hashtable stats = new Hashtable();
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
Color px = bmp.GetPixel(x, y);
if (px.A == 0)
continue;
Color pxS = Color.FromArgb(255, px);
if (stats.ContainsKey(pxS.ToArgb()))
stats[pxS.ToArgb()] = (int)stats[pxS.ToArgb()] + 1;
else
stats.Add(pxS.ToArgb(), 1);
}
}
float totalSize = bmp.Width*bmp.Height;
float minAccepted = 0.01f;
List<int> selectedColors = new List<int>();
// Make up a list with the selected colors
foreach (int key in stats.Keys)
{
int total = (int)stats[key];
if (((float)total / totalSize) > minAccepted)
selectedColors.Add(key);
}
// Keep growing the zones with the selected colors to cover the invalid colors created by the anti-aliasing
while (GrowSelected(bmp, selectedColors));
}
private static bool GrowSelected(Bitmap bmp, List<int> selectedColors)
{
bool flag = false;
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
Color px = bmp.GetPixel(x, y);
if (px.A == 0)
continue;
Color pxS = Color.FromArgb(255, px);
if (selectedColors.Contains(pxS.ToArgb()))
{
if (!isBackedByNeighbors(bmp, x, y))
continue;
List<Point> neighbors = GetNeighbors(bmp, x, y);
foreach(Point p in neighbors)
{
Color n = bmp.GetPixel(p.X, p.Y);
if (!isBackedByNeighbors(bmp, p.X, p.Y))
bmp.SetPixel(p.X, p.Y, Color.FromArgb(n.A, pxS));
}
}
else
{
flag = true;
}
}
}
return flag;
}
private static List<Point> GetNeighbors(Bitmap bmp, int x, int y)
{
List<Point> neighbors = new List<Point>();
for (int i = x - 1; i > 0 && i <= x + 1 && i < bmp.Width; i++)
for (int j = y - 1; j > 0 && j <= y + 1 && j < bmp.Height; j++)
neighbors.Add(new Point(i, j));
return neighbors;
}
private static bool isBackedByNeighbors(Bitmap bmp, int x, int y)
{
List<Point> neighbors = GetNeighbors(bmp, x, y);
Color px = bmp.GetPixel(x, y);
int similar = 0;
foreach (Point p in neighbors)
{
Color n = bmp.GetPixel(p.X, p.Y);
if (Color.FromArgb(255, px).ToArgb() == Color.FromArgb(255, n).ToArgb())
similar++;
}
return (similar > 2);
}
结果:原始图片:http://i.imgur.com/8foQwFe.png
消除锯齿的结果:http://i.imgur.com/w6gELWJ.png
2 回答
过滤器的反转过程称为反卷积(这是一般反问题的特定情况) .
解卷积有两种类型:
非盲解卷积 - 图像上的操作已知(例如,已应用低通滤波器的系数) .
盲解卷积 - 如果应用的滤波器具体未知,则仅假设有关它的一些假设(例如是LPF或空间不变等等) .
那些通常(其中任何一个)复杂的算法花费时间(除非使用天真的“维纳滤波器”方法) .
假设过滤器是某种LPF穷人的解决方案将是某种高通滤波器(HPF) . 其中任何一个都可以看到“更清晰的图像”和“增强的边缘” . 这种类型的已知过滤器是Unsharp Mask:
在图像上应用LPF(通常使用具有给定STD的高斯模糊) . 我们称之为lpfImage .
计算差异图像:diffImage = originalImage - lpfImage .
"Unsharp Mask Image"由下式给出:usmImage = originalImage(alpha * diffImage)
其中
alpha
是"Sharpening"级别的预定义缩放因子 .请享用...
我会试试Color Quantization .
您需要构建某种类型的颜色直方图,并从图像中获取最常用的颜色 . 在平滑之前,它可能是你的初始颜色 .
创建前6种颜色的调色板 .
将栅格PNG转换为索引PNG .
我不确定GDI可以创建索引的PNG,但是有很多SDK可以处理它 .