反向(去除)抗混叠滤波器 [英] Reverse (remove) anti-aliasing filter

查看:138
本文介绍了反向(去除)抗混叠滤波器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组抗锯齿的灰度PNG图像.我需要知道如何以编程方式还原抗锯齿效果并再次获得清晰的边缘.

I have a set of anti-aliased greyscale PNG images. I need to know how to programatically revert the anti-aliasing effect and get sharp edges again.

我正在使用GDI +,但对代码的兴趣不大.如果可以建立这样的矩阵,我需要一个算法,也许是一个卷积滤波器.

I'm using GDI+ but I am less interested in code. I need an algorithm, maybe a convolution filter, if such a matrix can be built.

(应该)灰度图像仅包含6种颜色(或不同的灰色阴影).这样一来,以后我就可以使用颜色查找"滤镜为它们重新着色.但是,在保存图像时,Photoshop会自动应用抗锯齿功能,以使边缘模糊(因为启用了Bicubic Interpolation模式).我需要恢复这种效果.

The greyscale images (should) contain only 6 colors (or different shades of grey). This is so that later on I can re-color them using a Color-Lookup filter. However, when the images where saved, Photoshop automatically applied anti-aliasing so the edges were blurred (because the Bicubic Interpolation mode was enabled). I need to revert that effect.

这里是一个例子:

这是Photoshop的屏幕截图

This is a screenshot from Photoshop

有人建议我应用锐化"滤镜,因此我在photoshop上尝试了该滤镜.这是它的外观:

Someone suggested that I should apply a Sharpen filter, so I tried it on photoshop. Here is how it looks:

即使外部边缘很好,但两种不同颜色相遇的边缘仍显示出伪像.

Even though the outer edges are fine, the edges where 2 different colors meet show artifacts.

这就是我最终这样做的方式.它是非常即兴的,可能可以做得更好,更快,但是我找不到更好的解决方案.

This is how I ended up doing it. It is very much improvised and can probably be done better and faster, but I couldn't find any better solution.

想法是遍历每个像素,获取其直接邻居,并将其颜色与其像素进行比较.如果至少有2个相同颜色的像素作为后盾,它将检查是否也支持相邻像素.如果没有,它将用自己的像素替换相邻像素.

The idea is to iterate over each pixel, get its direct neighbors and compare its color to theirs. If it's backed by at least 2 pixels of same color, it checks if the neighbor pixel is backed as well. If not, it replaces the neighbor pixel with its own.

代码:

    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

Result: Original Image: http://i.imgur.com/8foQwFe.png

消除锯齿的结果: http://i.imgur.com/w6gELWJ.png

推荐答案

过滤器的反向过程称为反卷积(这是一般逆问题的一种特殊情况).
反卷积有两种类型:

The reversing procedure of a filter is called Deconvolution (Which is a specific case of the General Inverse Problem).
There are two types of Deconvolution:

  1. 非盲反卷积-已知图像操作(例如,已知所应用的低通滤波器的系数).
  2. 盲反卷积-在具体应用的滤波器未知的情况下,仅假设有关它的一些假设(例如LPF或空间不变等).

这些算法(通常都是复杂算法)需要时间(除非使用朴素的维纳过滤器"方法).

Those are usually (Any of them) complex algorithms which take time (Unless using the naive "Wiener Filter" approach).

假设滤波器是某种LPF穷人的解决方案将是某种高通滤波器(HPF). 这些中的任何一个都会给出更清晰的图像"和增强的边缘"的外观. 这种类型的已知过滤器是锐化蒙版":

Assuming the filter is some kind of LPF poor's man solution would be some kind High Pass Filter (HPF). Any of those would give a look of "Sharper Image" and "Enhanced Edges". Known filter of this type is the Unsharp Mask:

  1. 在图像上应用LPF(通常使用具有给定STD的高斯模糊).我们称之为lpfImage.
  2. 计算差异图像:diffImage = originalImage-lpfImage.
  3. 锐化蒙版图像"的给出方式为:usmImage = originalImage +(alpha * diffImage)
    其中alpha是锐化"级别的预定义缩放比例.
  1. Apply LPF on the image (Usually using Gaussian Blur with a given STD). Let's call it lpfImage.
  2. Calculate the difference image: diffImage = originalImage - lpfImage.
  3. The "Unsharp Mask Image" is given by: usmImage = originalImage + (alpha * diffImage)
    Where alpha is a predefined scaling factor of the "Sharpening" level.

享受...

这篇关于反向(去除)抗混叠滤波器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆