反向(去除)抗锯齿滤波器

7
我有一组抗锯齿灰度 PNG 图像。我需要知道如何通过编程取消反锯齿效果并再次获得清晰的边缘。
我正在使用 GDI+,但我对代码不太感兴趣。我需要算法。
这些灰度图像(应该)仅包含 6 种颜色(或不同的灰度阴影)。这样,以后我可以使用 Color-Lookup 滤镜重新着色它们。但是,当图像保存时,Photoshop 自动应用了抗锯齿处理,因此边缘变模糊了(因为启用了 Bicubic Interpolation 模式)。我需要恢复那个效果。
这里是一个示例: enter image description here 这是 Photoshop 的截图。
有人建议我应该应用 Sharpen 滤镜,所以我在 Photoshop 上尝试了一下。这是它的效果: enter image description here 即使外部边缘很好,两种不同颜色相遇的边缘也会显示伪像。
编辑:
这就是我最终的做法。这非常实用,可能可以做得更好更快,但我找不到更好的解决方案。
思路是迭代每个像素,获取其直接邻居并将其颜色与其相比较。如果它由至少 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


您需要提供一些您已尝试过的示例,或者说明您卡在了哪里。您不能请求他人为您完成任务。 - astorije
你可以通过扫描相同颜色像素的3x3块来获取用于输出的颜色目录。 - Mark Ransom
3个回答

3
一个滤波器的反转过程被称为退卷积(这是一般逆问题的一个特定案例)。
有两种类型的退卷积:
  1. 非盲目退卷积-其中图像上的操作是已知的(例如已知应用的低通滤波器的系数)。
  2. 盲目退卷积-应用的滤波器未知,只假设了一些关于它的假设(例如是LPF或空间不变的等)。

这些通常都是复杂算法(任何一种),需要时间(除非使用天真的"维纳滤波器"方法)。

假设滤波器是某种LPF,那么简单的解决方案是一些高通滤波器(HPF)。 任何一种都会给出"更清晰的图像"和"增强的边缘"的外观。 这种类型的已知滤波器是不锐化掩蔽:

  1. 在图像上应用LPF(通常使用具有给定STD的高斯模糊)。让我们称之为lpfImage。
  2. 计算差异图像:diffImage = originalImage - lpfImage。
  3. "不锐化掩蔽图像"由以下公式给出:usmImage = originalImage + (alpha * diffImage)
    其中alpha是"锐化"级别的预定义缩放因子。

享受...


1
我如何找出Photoshop抗锯齿卷积矩阵是什么?这是否与双三次插值设置有关?您能否举个例子,展示我们如何反卷积抗锯齿滤镜?此外,它是模糊还是低通滤镜? - Francois Zard

2

我会尝试 颜色量化

您需要构建某种类型的颜色直方图,并从您的图像中获取最常用的颜色。可能是您平滑前的初始颜色。

创建一个带有前6个颜色的调色板。

将光栅PNG转换为索引PNG。

我不确定GDI +是否能够创建索引PNG,但有很多SDK可以处理它。


0

Photoshop中的Facet过滤器可能会有所帮助。它会搞乱颜色通道,但使用灰度图像是最好的选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接