Более быстрый способ обнаружить самое яркое из нескольких пятен на изображении с помощью imagemagick?

У меня есть несколько обнаруженных полигонов на изображении, и я пытаюсь найти самые яркие из них. Я нашел способ, но он сравнительно медленный, когда он сравнивает много полигонов.

Код делает следующее:

  1. Это изменяет размер области до того же размера и
  2. возвращает 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";

Результат ярчайшая часть отмечена

3

Решение

В зависимости от вашего фона, условий освещения и задействованных форм, вы можете обнаружить, что можете достичь этого быстрее с «Анализ связанных компонентов». Это также потенциально означает, что вам не нужно делать шаг, который вы делали ранее, чтобы определить ваши прямоугольники, чтобы время могло быть еще лучше — я имею в виду, что это не только говорит вам о средней яркости форм, но и находит их для тебя.

В командной строке это выглядит так:

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 читать это еще быстрее с диска.

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

введите описание изображения здесь

Это говорит нам о том, что белая область содержит 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
1

По вопросам рекламы [email protected]