确定“视觉清晰度”或图像像素化的算法


Algorithm to determine "visual clarity", or pixelation of an image

是否有这样的方法来确定图像可以放大多少,直到它被认为是"失焦"?

一个实际的例子(和我试图解决的问题):

我有一个图像保存在几个不同的大小,比如500 × 500, 250 × 250和120 × 120。我要服务的形象最高效,也最清晰。如果用户请求一个125x125的图像,显然增加120x120的图像来适应不仅是最有效的,而且很可能不会造成任何明显的像素化。

然而,如果用户要请求一张180x180的图像,那么增加120x120的图像可能会更有效,但很可能会呈现一个模糊的图像。在本例中,我想要缩小250x250的图像。

显然,图像的"清晰度"可以是相对的,并且从眼睛到眼睛以及图像到图像都有所不同,但我想知道是否有任何类型的算法或函数来确定各种"像素化指数"……谢谢!

注意:使用PHP &ImageMagick的图像操作,所以在这个领域的任何答案将是伟大的…

澄清:我并不是在寻找一个解决方案我上面的例子。我在寻找原始问题的答案:is there an algorithm that could possibly determine how "pixelated" a blown up image is…上面的问题只是说明这种算法如何有用的一个实际例子。

您可以对图像进行灰度sobel边缘检测过滤器,并对边缘的像素值求和;然后对像素数(SumOfEdges/(width*height))进行求和。这会告诉你图像的"尖锐性"。这只能用于比较图像类型。

这是我的sobel opencl过滤器内核

const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE |
CLK_FILTER_NEAREST;
kernel void
sobel_grayscale(read_only image2d_t src, write_only image2d_t dst)
{
int x = get_global_id(0);
int y = get_global_id(1);
float4 p00 = read_imagef(src, sampler, (int2)(x - 1, y - 1));
float4 p10 = read_imagef(src, sampler, (int2)(x, y - 1));
float4 p20 = read_imagef(src, sampler, (int2)(x + 1, y - 1));
float4 p01 = read_imagef(src, sampler, (int2)(x - 1, y));
float4 p21 = read_imagef(src, sampler, (int2)(x + 1, y));
float4 p02 = read_imagef(src, sampler, (int2)(x - 1, y + 1));
float4 p12 = read_imagef(src, sampler, (int2)(x, y + 1));
float4 p22 = read_imagef(src, sampler, (int2)(x + 1, y + 1));
float4 gx = -p00 + p20 + 2.0f * (p21 - p01)-p02 + p22;
float4 gy = -p00 - p20 +2.0f * (p12 - p10) +p02 + p22;
float gs_x = 0.3333f * (gx.x + gx.y + gx.z);
float gs_y = 0.3333f * (gy.x + gy.y + gy.z);
float g = native_sqrt(gs_x * gs_x + gs_y * gs_y);
write_imagef(dst, (int2)(x, y), (float4)(g,g,g, 1.0f));
}

这并不完全符合您的要求,但我认为它达到了您想要的效果。编写一个算法来量化图像的像素化程度将是非常重要的,它肯定是特定于图像格式的(例如,只有适用于PNG图像),我真的不认为有必要实现你想要的。

因此,为了这个例子,让我们假设所有的图像都是完全方形的(修改它来考虑非方形图像是相当微不足道的):

假设你有一个可以调整大小的源图像列表,以及一个"结果大小"——比如500像素× 500像素。你可以这样做:

$resultSize = 500;
$bestRatio = PHP_INT_MAX;
$bestURL = "";
foreach($sourceImageURLs as $url)
{
    $size = getimagesize($url);
    $size = $size[0];
    $ratio = min($resultSize, $size) / max($resultSize, $size);
    if($ratio < $bestRatio)
    {
        $bestRatio = $ratio;
        $bestURL = $url;
    }
}
/*
 * We've now found the image closest to our desired size. All we need
 * to do is resize the image at the URL in $bestURL to $resultSize, and
 * we're done.
 */

我不认为我会担心"最有效"的图像-将100x100图像缩放到200x200与将300x300图像缩放到200x200将会给你两个非常大小相似的图像(特别是如果你使用一些好的压缩工具,如PNGOUT或等)。我会从最接近所需尺寸的源图像开始缩放

您可以使用此"Duplicate Image Finder"的算法来比较您的高质量图像的指纹与其低质量孪生图像的指纹。你觉得呢?

图像质量完全是主观的,很大程度上取决于原始图像的复杂性。如果你的图像是雪暴中的一只白猫(基本上就是白色),那么500x500图像的主观质量将是相同的,无论你是通过减少1000x1000图像还是通过增加100x100图像来实现它。

但是在所有条件相同的情况下,你可以假设高分辨率的图像会缩小到比低分辨率的图像会放大到更好的质量。

所以在我的脑海里,你可以把大图缩小到目标尺寸,然后用它作为一个度量(理想)来评估放大后的小图片的质量(第9行第7个像素与理想图像中的相同像素有多不同,等等)。这种比较可以对所有像素进行比较,也可以对图像中的采样点进行比较。由此产生的"外度"可以被平均,并用作放大图像质量的指示。