9

之前在 SO 上问过这样一个问题:Detecting a pixelated image in python and also on quora

我正在尝试找出是否可以将用户上传的图像检测为“像素化”。像素化是指像这样的图像:在我的情况下,我无法访问原始(非像素化)版本。

我的方法

不确定这种方法有多有效,但如果我可以获取图像中每个像素的 RGB,然后将其与相邻像素进行比较,看看它们是否相似,那么我可以检测到图像是否像素化?我可以获得像素的 RGB,但不知道如何将它们与邻居进行比较。

是否已经有用于执行此类操作的算法?我可以采取其他一些方法吗?我不受任何特定语言的约束。

4

3 回答 3

10

这是一个相当简单的方法,可以工作:

  1. 从 x 和 y 中平移 1 个像素的副本中减去图像。
  2. 对列和行中的像素求和(我只在下面显示列)。
  3. 找出峰值位置的频率和标准偏差。
  4. 如果标准偏差低于某个阈值,则图像被像素化。

第 1 步后的图像:

在此处输入图像描述

呈现出清晰的网格图案。现在,如果我们按列对像素求和,我们得到:

在此处输入图像描述 现在如果我们能弄清楚峰值列间距的规律,并将其用作阈值来确定图像是否像素化。

这是一些快速而粗略的 python 代码,以提供一种方法的想法:

import numpy as np
import Image, ImageChops

im = Image.open('fireworks-pixelate-02.gif')    
im2 = im.transform(im.size, Image.AFFINE, (1,0,1,0,1,1))
im3 = ImageChops.subtract(im, im2)
im3 = np.asarray(im3)
im3 = np.sum(im3,axis=0)[:-1]
mean = np.mean(im3)
peak_spacing = np.diff([i for i,v in enumerate(im3) if v > mean*2])
mean_spacing = np.mean(peak_spacing)
std_spacing = np.std(peak_spacing)
print 'mean gap:', mean_spacing, 'std', std_spacing

输出:

mean gap: 14.6944444444 std: 3.23882218342

低标准 = 像素化图像

这个未像素化的图像: 在此处输入图像描述

有一个像这样的相应图表:

在此处输入图像描述 产生更高的标准:

mean gap: 16.1666666667 std: 26.8416136293

请注意,“平均差距”是没有意义的,因为 std 要高得多。

希望这足以说明这种方法可以很好地工作。

于 2013-01-19T23:36:10.897 回答
7

一些方法:

1)实现canny或其他边缘检测并改变边缘阈值以查看结果是否为网格。可以通过将霍夫线检测器应用于生成的边缘图像来检测网格。见下文 (2)。

2)(这实际上是在边缘检测之前对图像进行阈值处理;也建议使用中值滤波器或其他去噪滤波器对图像进行平滑处理)。从左到右扫描,并在每个像素颜色变化时为像素分配黑色或白色。继续使用黑色/白色,直到颜色发生变化,然后从黑色切换到白色或从白色切换到黑色。如果像素化,你最终会得到一个像网格一样的图像。您可以在 iamge 上运行标准线检测(您也可以对1执行此操作)并查看生成的线的斜率是否垂直和平行,以及线是否相当等距。互联网上有示例行检测算法(甚至是 Java 实现)。

网站参考了线检测和边缘检测算法。

编辑:针对 mmgp 的问题(挑战 +1,我喜欢这样!),这就是我对问题中的示例图像所做的:1)边缘检测 2)灰度 3)休变换(高阈值)附加的是休变换输出。通过评估所有具有水平/垂直斜率的线并计算它们之间的距离,可以识别网格图案。这并不自动意味着图像是像素化的(棋盘会显示为像素化)。可能存在误报。

在此处输入图像描述

于 2013-01-19T21:25:35.643 回答
2

This is going to be problematic, there are many ways to pixelate images. Even using a single method, you can have it arbitrarily rotated. In theory this rotation shouldn't affect methods like Hough, but in practice it does because you cannot have perfectly rasterized lines at arbitrary angles. My approach is simplistic, it is not going to work every time (it will probably fail most of time), but you really have to better define what you want to do. Are you going to tell the user: "hey, your image is pixelated, I don't want it" ? What you want to do is not clear, the scope is not clear too.

So here is the approach. Split your image into its color channels, your example one is a palleted GIF but that can be easily seen as a RGB image. If it is a grayscale then you mostly like have one channel, that is fine. If your image have an alpha channel, either blend it or ignore it. With this separated color channels, apply a morphological gradient in each one, binarize each one by Otsu (since it is automatic, relatively good, easily available), and combine the n binary channels into one by adding them. The morphological gradient will give a high response for strong edges (including noise), and the binarization step will keep them. Now you remove components that are too small and do a thinning to get one-pixel-wide edges. Here is what we get with your example image after these steps:

enter image description here enter image description here

f = Import["http://www.caughtinthefire.com/wp-content/uploads/2009/03/\
     fireworks-pixelate-02.gif"]
split = Binarize[ImageSubtract[Dilation[#, 1], Erosion[#, 1]]] & /@ 
  ColorSeparate[f, "RGB"]
thin = Thinning[SelectComponents[Fold[ImageAdd, split[[1]], split[[2 ;;]]], 
  "Count", # > 10 &]]

Now we proceed to detect the lines in this thinned binary image. The expectation is that it will form many rectangular areas when the image is pixelated, but there is no guarantee that we can actually form these rectangular areas. Supposing we can, consider each of these areas as a connected component. Then if we perform a simply component analysis as: if the ratio between the area of its convex hull and the area of its bounding box is greater than some value, then this area is a rectangular area. If we end up with many rectangular areas, then you say your image is pixelated (but actually there is no confidence on saying such thing). Next we see the original image with the detected lines overlaid, at right we see the connected components (points that are not black) that remain after considering the analysis mentioned using a ratio > 95%. In this case, there were 542 connected components in total, which were reduced to 483. This means nearly 90% of the components are rectangular. You could also take into consideration the area of the remaining components, or combine this analysis with other ones, but I'm not doing this here.

enter image description here enter image description here

lines = ImageLines[thin, 0.05, Method -> "RANSAC"];
Show[f, Graphics[{Thick, Blue, Line /@ lines}]] (* The left image above. *)
blank = Image[ConstantArray[255, Reverse@ImageDimensions[thin]]];
blankcc = ImagePad[Binarize[Image[Show[blank, 
  Graphics[{Thick, Black, Line /@ lines}]]]], 1, Black]
ccrect = SelectComponents[MorphologicalComponents[blankcc], {"BoundingBoxArea", 
  "ConvexArea"}, #2/#1 > 0.95 &];
Colorize[ccrect, ColorFunction -> "DarkRainbow"] (* The right image above. *)

This is your indication of "pixelated".

Here are other results considering other images. This is always a sequence of three images in this order: original, result as above without changing anything, result as above after changing the threshold for line detection.

Everything detected as rectangular. But a threshold of 0.05 for line detection is too high here, after reducing it to 0.01 we get a better division of the components.

enter image description here enter image description here enter image description here

Next we consider an image which is outside of what we expect, so we end up with very few components. There is no threshold for line detection that will give a greater amount of rectangular components, so the third image is empty (or fully black, since no component remains).

enter image description here enter image description here

Lastly, a pixelation where the squares are rotated. The process for generating the following image might have been different than the one used in the example image, but I have no idea since I'm not the author. The right image is the result of raising the line threshold to 0.08. The problem here is that the regions are relatively large, which I wouldn't consider for detection of pixelated images.

enter image description here enter image description here enter image description here

于 2013-01-20T15:07:33.127 回答