opencv 如何检测图像是否像素化

huus2vyu  于 2023-08-06  发布在  其他
关注(0)|答案(3)|浏览(137)

之前有一个问题是这样问的:Detecting a pixelated image in pythonquora
我想知道用户上传的图像是否可以被检测为“像素化”。像素化的意思是图像like these:在我的情况下,我没有访问原始(非像素化)版本。

我的做法

不知道这种方法有多有效,但如果我能得到图像中每个像素的RGB,然后将其与相邻像素进行比较,看看它们是否相似,那么我就可以检测到图像是像素化的?我可以得到像素的RGB,但不知道如何将它们与相邻像素进行比较。
现在有算法可以做这样的事情吗?有没有其他方法我可以采取?我不受任何特定语言的约束。

du7egjpx

du7egjpx1#

这里有一个相当简单的方法,可以工作:
1.从x和y方向均平移1个像素的副本中减去图像。
1.按列和行对像素求和(我只在下面显示列)。
1.计算峰位置的频率和标准偏差。
1.如果标准偏差低于某个阈值,则图像被像素化。
步骤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


这里请注意,“平均差距”是没有意义的,因为标准差要高得多。
希望这足以说明这种方法可以很好地工作。

axr492tv

axr492tv2#

一些办法:
1)执行canny或其他边缘检测并改变边缘阈值以查看结果是否是网格。可以通过将霍夫线检测器应用于所得到的边缘图像来检测网格。见下文(2)。
2)(这实际上是在边缘检测之前对图像进行阈值化;还建议用中值滤波器或其它噪声去除滤波器来平滑图像)。从左到右扫描,并在每个像素颜色变化时将黑色或白色分配给像素。继续使用黑色/白色,直到颜色发生变化,并从黑色切换到白色或从白色切换到黑色。如果像素化,你最终会得到一个像网格一样的图像。您可以在图像上运行一个标准的线检测(也可以对1执行),并查看结果线的斜率是否垂直和平行,以及这些线是否相当等距。互联网上有采样线检测算法(甚至Java实现)。
这个website参考了线检测和边缘检测算法。
编辑:在回答mmgp的问题(+1的挑战,我喜欢!),这是我对问题中的示例图像所做的:1)边缘检测2)灰度3)高变换(高阈值)通过评估具有水平/垂直斜率的所有线并计算它们之间的距离,可以辨别网格图案。这并不自动意味着图像是像素化的(棋盘将显示为像素化的)。可能会有假阳性。
x1c 0d1x的数据

vktxenjb

vktxenjb3#

这将是有问题的,有很多方法来像素化图像。即使使用单一方法,也可以任意旋转。从理论上讲,这种旋转不会影响像Hough这样的方法,但实际上会影响,因为您不可能以任意Angular 完美地光栅化线条。我的方法是简单的,它不会每次都有效(它可能会在大多数时候失败),但你真的必须更好地定义你想做什么。你会告诉用户:“嘿,你的图像是像素化的,我不想要它”?你想做什么不清楚,范围也不清楚。
这就是方法。将您的图像拆分为颜色通道,您的示例是一个调色板GIF,但可以很容易地看到RGB图像。如果它是一个灰度,那么你最喜欢有一个通道,这是罚款。如果你的图像有一个Alpha通道,混合它或忽略它。使用这种分离的颜色通道,在每个通道中应用形态梯度,通过大津对每个通道进行二值化(因为它是自动的,相对较好,易于获得),并通过将它们相加将n个二值通道合并成一个。形态学梯度将对强边缘(包括噪声)给予高响应,并且二值化步骤将保留它们。现在,您将删除太小的组件,并进行细化以获得一个像素宽的边缘。以下是我们在这些步骤之后获得的示例图像:

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 &]]

字符串
现在,我们继续检测该细化的二进制图像中的线。我们的期望是,当图像像素化时,它会形成许多矩形区域,但不能保证我们实际上可以形成这些矩形区域。假设我们可以,将这些区域中的每一个视为一个连通的组件。然后,如果我们执行简单的分量分析:如果其船体的面积和其边界框的面积之间的比率大于某个值,则该面积是矩形面积。如果我们最终有许多矩形区域,那么你说你的图像是像素化的(但实际上没有信心说这样的事情)。接下来,我们看到原始图像与检测到的线重叠,在右侧,我们看到在考虑使用> 95%的比率所提到的分析之后保留的连接分量(不是黑色的点)。在这种情况下,总共有542个连接的组件,减少到483个。这意味着近90%的组件是矩形的。您也可以考虑剩余组件的面积,或者将此分析与其他分析结合起来,但这里不做这些。

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. *)


这是你的“像素化”的指示。
以下是考虑到其他图像的其他结果。这始终是一系列三个图像的顺序:原始的,结果如上而不改变任何东西,在改变用于行检测的阈值之后结果如上。
所有检测到的都是矩形。但是这里的行检测阈值0.05太高了,在将其降低到0.01后,我们得到了更好的分量划分。

接下来,我们考虑一个超出我们期望的图像,所以我们最终只有很少的组件。不存在将给予更大量矩形分量的线检测阈值,因此第三图像是空的(或全黑的,因为没有分量剩余)。

最后,一个像素化的方块旋转。生成下面图像的过程可能与示例图像中使用的过程不同,但我不知道,因为我不是作者。右图是将线阈值提高到0.08的结果。这里的问题是,区域相对较大,我不会考虑像素化图像的检测。

相关问题