У меня есть несколько обнаруженных полигонов на изображении, и я пытаюсь найти самые яркие из них. Я нашел способ, но он сравнительно медленный, когда он сравнивает много полигонов.
Код делает следующее:
format "%\[mean\]"
значение и вернуть самый большойНасколько я вижу, процесс замедляется командой изменения размера.
Любая идея или другой подход, чтобы закрепить этот алгоритм?
Вот пример, где сравниваются только два полигона. Это все еще займет ~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";
В зависимости от вашего фона, условий освещения и задействованных форм, вы можете обнаружить, что можете достичь этого быстрее с «Анализ связанных компонентов». Это также потенциально означает, что вам не нужно делать шаг, который вы делали ранее, чтобы определить ваши прямоугольники, чтобы время могло быть еще лучше — я имею в виду, что это не только говорит вам о средней яркости форм, но и находит их для тебя.
В командной строке это выглядит так:
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)
Затем вы просто сравнили бы яркость средних цветов двух объектов, перечисленных выше.
Может быть, вы можете поскользнуться в -resize 50%x50%
сразу после загрузки изображения и до -fuzz
чтобы ускорить это еще дальше. Если ваше реальное входное изображение — JPEG, вы также можете использовать resize on load
читать это еще быстрее с диска.
Я думаю, что это будет самый быстрый способ сделать это …
Некоторые из писем 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
Это говорит нам о том, что белая область содержит 125 642 из 597 600 пикселей, или примерно 25%.
Если мы теперь загрузим исходное изображение и замаскируем его этой маской и определим его среднее значение, мы можем определить среднее значение области, замаскированной белыми пикселями, потому что мы знаем, сколько белого из предыдущего шага:
convert image.png mask.mpc -compose copyopacity -composite -format "%[mean]" info:
22012.6
convert image.png mask.mpc -compose copyopacity -composite result.png