使用imagemagick更快速地检测图像中最亮的几个点?

时间:2015-09-25 11:02:56

标签: php imagemagick imagemagick-convert

我在图像中有几个检测到的多边形,我试图找到最亮的多边形。我发现了一种方法,但是当它比较很多多边形时它相对较慢。

代码执行以下操作:

  1. 它将区域大小调整为相同的大小和
  2. 返回format "%\[mean\]"值并返回最大值
  3. 据我所知,进程因调整大小命令而变慢。 任何想法或不同的方法来固定该算法?

    实施例

    这里是一个只比较两个多边形的例子。计算仍然需要~0.3457 sec

    // the example image
    $image = "http://i.stack.imgur.com/hmPYh.png";
    
    // get parameters of the image
    list ($width, $height, $type) = getimagesize ("$image");
    
    // the polygones
    $quadrilateral[0] = array('pointA' => array ('x' => 50, 'y' => 105),
                              'pointB' => array ('x' => 470.593, 'y' => 105),
                              'pointC' => array ('x' => 475.714, 'y' => 398.404),
                              'pointD' => array ('x' => 50, 'y' => 405.835));
    $quadrilateral[1] = array('pointA' => array ('x' => 525, 'y' => 185),
                              'pointB' => array ('x' => 935, 'y' => 185),
                              'pointC' => array ('x' => 935, 'y' => 477),
                              'pointD' => array ('x' => 525, 'y' => 477));
    
    // measure time
    $start_time = microtime(true);
    
    // start with zero
    $brightest = 0;
    
    // loop through $quadrilateral
    foreach ( $quadrilateral as $key => $q) {
    
        $resize_factor = .5; // resize factor for check if it works faster
        $newHeight = $height*$resize_factor;
        $newWidth = $width*$resize_factor;
    
        // resize image and return %mean            
        $command = "convert $image \\
                    -background none \\
                    -gravity NorthWest  \\
                    -extent ".$width."x".$height." \\
                    -alpha set -virtual-pixel transparent \\
                    -distort Perspective \"\\
                        ".$q['pointA']['x'].",".$q['pointA']['y']." 0,0 \\
                        ".$q['pointB']['x'].",".$q['pointB']['y']." $newWidth,0 \\
                        ".$q['pointC']['x'].",".$q['pointC']['y']." $newWidth,$newHeight \\
                        ".$q['pointD']['x'].",".$q['pointD']['y']." 0,$newHeight \"\\
                    -crop ".$newWidth."x".$newHeight."+0+0 +repage \\
                    -format \"%[mean]\" info: ";    
    
        $output = shell_exec("$command");
    
        $draw =  "polygon ".$q['pointA']['x'].",".$q['pointA']['y']." "
                           .$q['pointB']['x'].",".$q['pointB']['y']." "
                           .$q['pointC']['x'].",".$q['pointC']['y']." "
                           .$q['pointD']['x'].",".$q['pointD']['y']." ";
    
        // check $output is brighter then $brightest
        if ($output > $brightest) {
    
            $result = $draw;                                        
            $brightest = $output;
    
        }
    
    }
    
    // measure time
    $end_time = microtime(true);
    
    $command = "convert  $image \\
                    -fill none -stroke red -strokewidth 3 \\
                    -draw \"$result\" \\
                    $image2";
    
    $output = shell_exec("$command");
    
    echo "<pre>".number_format(($end_time-$start_time), 4)  . " sec</pre>\n";
    

    result brightest part is marked

2 个答案:

答案 0 :(得分:1)

根据您的背景,光照条件以及所涉及的形状,您可能会发现使用“连接组件分析”可以更快地到达目的地。它也可能意味着您不必执行先前确定矩形的步骤,因此时间可能更好 - 我的意思是这不仅告诉您形状的平均亮度,而且还可以找到它们对你而言。

在命令行看起来像这样:

convert input.png -fuzz 30% -fill black -opaque black \
  -define connected-components:verbose=true           \
  -define connected-components:area-threshold=500     \
  -connected-components 8 -auto-level output.png

<强>输出

Objects (id: bounding-box centroid area mean-color):
0: 996x600+0+0 504.2,305.1 349020 srgba(0,0,0,1)
3: 429x304+49+104 261.0,254.1 128277 srgba(187,184,186,1)
10: 415x294+523+185 730.4,331.7 120303 srgba(177,156,161,1)

然后,您只需比较上面列出的两个对象的平均颜色的亮度。

enter image description here

也许您可以在加载图片后立即在-resize 50%x50%内滑动-fuzz,以便进一步加快速度。如果您的真实输入图像是JPEG,您也可以使用resize on load从磁盘中更快地读取它。

答案 1 :(得分:1)

我认为这将是最快的方式......

  • 用黑色填充图像。
  • 绘制一个白色填充多边形,以匹配您要分析亮度的形状。
  • 计算白色像素 - 即形状中的像素数。
  • 加载原始图像并将其与上面创建的蒙版相乘。
  • 计算整个图像的平均值。
  • 缩放,表示整个图像中的像素数超过蒙版中像素数。

以下内容中对MPR:something的一些写入是不必要的,但它们会告诉您我正在做什么,所以我将它们留在了:

#!/bin/bash
convert image.png -write MPR:orig                                             \
  -print "Pixels in entire image: %[fx:w*h]\n"                                \
  -colorspace gray -threshold 100% -write MPR:black                           \
  -fill white -draw "polygon 50,105 470,105 475,398 50,405" -write MPR:mask   \
  MPR:black                                                                   \
  -metric AE -compare -print "Pixels in polygon: %[distortion]\n" -delete 0   \
  MPR:orig MPR:mask -evaluate-sequence multiply -print "Mean (entire image): %[mean]\n" null:

<强>输出

Pixels in entire image: 597600
Pixels in polygon: 126357
Mean (entire image): 10160.5

原始答案

我将以下内容作为踏脚石,因为它显示了其他几种技术和中间文件......

另一个选项可能是绘制与检测到的多边形形状对应的白色填充多边形,然后将所有其他像素设置为黑色。将其保存为稍后的掩码,然后计算多边形中的白色像素数 - 通过复制它并使副本变为黑色然后在两者之间做差异 - 幸运地比听起来更容易:

convert image.png                                            \
  -fill white -draw "polygon 50,105 470,105 475,398 50,405"  \
  -fill black +opaque white -colorspace gray -write mask.mpc \
  \( +clone -threshold 100% \)                               \
  -metric AE -compare -format "%[distortion]" info:
125642

enter image description here

这告诉我们白色区域包含总共597,600个像素中的125,642个,或大约25%。

如果我们现在加载原始图像并使用该蒙版进行遮罩并确定其平均值,我们可以确定白色像素遮盖区域的平均值,因为我们知道上一步有多少是白色的:

convert image.png mask.mpc -compose copyopacity -composite -format "%[mean]" info:
22012.6

enter image description here

convert image.png mask.mpc -compose copyopacity -composite result.png