4

我有一组反锯齿灰度PNG图像。我需要知道如何以编程方式恢复抗锯齿效果并再次获得锐利的边缘。反转(移除)反锯齿滤镜

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

灰度图像(应该)只包含6种颜色(或不同的灰色阴影)。这是以后,我可以使用颜色查找过滤器对它们重新着色。但是,当保存图像时,Photoshop会自动应用消除锯齿效果,使边缘模糊(因为启用了双三次插值模式)。我需要恢复那个效果。

下面是一个例子:

enter image description here

这是从Photoshop

截图有人建议我应该申请一个锐化滤镜,所以我想它的Photoshop。下面是它的外观:

enter image description here

即使外缘都很好,其中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

+0

你需要提供一些你已经试过的东西,或者你被卡住的地方。你不应该要求别人为你完成你的任务。 – astorije

+0

通过扫描3x3相同颜色的像素块,您可以获得输出中使用的颜色目录。 –

回答

1

滤波器的倒车过程被称为解卷积(这是一般反问题的一个特例)。
有两种类型的反褶积:

  1. 非盲解 - 在图像上的操作是已知的(例如应用了低通滤波器的系数是已知)。
  2. 盲解卷积 - 如果应用的滤波器具体未知,则只假设其中的一些假设(如LPF或空间不变量等)。

那些通常是其中任何一个需要时间的复杂算法(除非使用天真的“维纳滤波器”方法)。

假设滤波器是某种LPF穷人的解决方案将是某种高通滤波器(HPF)。 其中任何一个都可以看到“更锐利的图像”和“增强的边缘”。 已知这种类型的过滤器是柔化:

  1. 应用LPF的图像(通常使用高斯模糊与给定STD)上。我们称之为lpfImage。
  2. 计算差异图像:diffImage = originalImage - lpfImage。
  3. “USM锐化图像”由下式给出:usmImage = originalImage +(alpha * diffImage)
    其中alpha是“锐化”级别的预定义比例因子。

享受...

+1

如何找出photoshop卷积矩阵用于抗锯齿?它是否与双三次插值设置有关?您能举一个例子说明我们如何解卷积抗混叠滤波器吗?此外,它是模糊还是低通滤波器? –

0

我会尝试Color Quantization

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

创建一个顶级6色调色板。

将栅格PNG转换为索引PNG。

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