使用Imagemagick快速检测图像中多个点中最亮的方法是什么?

3
我在图像中检测到多个多边形,我试图找到其中最亮的一个。我找到了一种方法,但是当它比较很多多边形时,它相对较慢。
代码执行以下操作:
  1. 将区域调整为相同大小
  2. 返回 format "%\[mean\]" 值并返回最大值
就我所见,这个过程被调整大小的命令拖慢了速度。 有什么想法或不同的方法来加快该算法吗?

例子

这里有一个例子,比较了两个多边形。计算仍需要约0.3457秒

// 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


你实际上是扭曲整个图像,以便测量的矩形填充一个矩形。也许你可以先将图像裁剪到包含矩形,然后再进行扭曲... - Mark Setchell
你检测到的实际矩形是否相当均匀?如果是这样,你可以将图像裁剪为最小包含矩形,然后裁剪出其中心的20-50%并测量其平均亮度。你的真实形状是否可能包含“孔” - 例如字母“e”? - Mark Setchell
不,它们并不太规则,因为照片角度是可变的。此外,形状可能包含孔。这就是为什么我使用Canny边缘检测Hough线检测器相结合来检测多边形的原因。 - wittich
2个回答

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

也许你可以在加载图像之后,-fuzz之前立即插入-resize 50%x50%,以进一步加快速度。如果你的实际输入图像是JPEG格式,你也可以使用resize on load来更快地从磁盘中读取它。

谢谢你的方法,@mark-setchell。它非常快。不幸的是,对我来说并不起作用,因为我的背景通常更加复杂。我会尝试在背景上放置一个蒙版,并按照这些方法进行操作... - wittich
你能否将图像在每个维度上缩小50%以加快速度呢? - Mark Setchell
好主意,我将原始图像缩小后再检查结果。使用9个不同的多边形需要以下时间:100% => 约42秒,50% => 约32秒,25% => 约34秒。从100%到50%有一点改善,但进一步缩小后就没有了。似乎shell_exec()本身就需要时间...也许使用已经实现的php5命令会更快... - wittich
所以我只使用了php5命令来实现它,而且运行时间完全相同。对我来说,这意味着透视畸变使得该过程变慢。但是到目前为止,我没有更好的比较多边形的想法... - wittich
1
这就是为什么我在最初的评论中建议在进行透视扭曲之前将其裁剪到最小边界矩形。如果您有一个不错的2+核心CPU,另一个选择可能是并行处理各种多边形... - Mark Setchell
我现在又尝试了一下,但它并没有加快进程。出于测试原因,我只是将每个多边形裁剪到最小的边界矩形... - wittich

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接