Я пытаюсь определить ширину цветного прямоугольника внутри изображения. Для обработки изображений я использую Imagick для PHP.
Идея состояла в том, чтобы преобразовать изображение в текстовый формат и искать этот текстовый текст с помощью регулярного выражения для всех пикселей, которые имеют определенный цвет (# 00FF00).
Вот пример того, как выглядит этот текст (отрывок, начиная с столбца 0 строки 83):
0,83: (255,255,255,1) #FFFFFF graya(255,1)
1,83: (255,255,255,1) #FFFFFF graya(255,1)
2,83: (255,255,255,1) #FFFFFF graya(255,1)
3,83: (0,255,0,1) #00FF00 graya(0,1)
4,83: (0,255,0,1) #00FF00 graya(0,1)
5,83: (0,255,0,1) #00FF00 graya(0,1)
6,83: (255,255,255,1) #FFFFFF graya(255,1)
7,83: (255,255,255,1) #FFFFFF graya(255,1)
8,83: (255,255,255,1) #FFFFFF graya(255,1)
0,84: (255,255,255,1) #FFFFFF graya(255,1)
1,84: (255,255,255,1) #FFFFFF graya(255,1)
2,84: (255,255,255,1) #FFFFFF graya(255,1)
3,84: (0,255,0,1) #00FF00 graya(0,1)
4,84: (0,255,0,1) #00FF00 graya(0,1)
5,84: (0,255,0,1) #00FF00 graya(0,1)
....
Вот мой код:
$canvasImg = new Imagick("_sources/passepartout/". $deviceName .".png");
$canvasImg->setFormat(txt);
preg_match_all("/(\\d+),(\\d+): \\(0,255,0,1\\)/is", $canvasImg, $colorMatchAll);
$firstPixelX = reset($colorMatch[1]);
$lastPixelX = end($colorMatch[1]);
$canvasWidth = $lastPixelX - $firstPixelX;
Пока это работает нормально, но очень медленно, так как находит все пиксели в цветном прямоугольнике, включая полную высоту оси y.
Теперь, когда меня интересует только ширина этого прямоугольника # 00FF00, я подумал, что будет быстрее, если регулярное выражение просто найдет первый пиксель, который является # 00FF00, а затем пройдет через ряд пикселей до конца (строка 83 в моем примере) и останавливается, как только он достигает 84-го ряда.
Могу ли я изменить свое регулярное выражение, чтобы оно выполняло то, что я ищу?
Вы можете либо использовать $ imagick-> trimImage (), а затем $ imagick-> getImagePage (), чтобы получить местоположение, если прямоугольник — единственная вещь на изображении, или вы можете перебирать пиксели и делать свое собственное обнаружение края.
$imagick = new \Imagick(realpath($imagePath));
$imageIterator = $imagick->getPixelRegionIterator(0, 0,
$imagick->getImageWidth(),
$imagick->getImageHeight(),
);
/* Loop through pixel rows */
foreach ($imageIterator as $pixels) {
/** @var $pixel \ImagickPixel */
/* Loop through the pixels in the row (columns) */
foreach ($pixels as $column => $pixel) {
$red = $pixel->getColorValue(\Imagick::COLOR_RED);
$green = $pixel->getColorValue(\Imagick::COLOR_GREEN);
$blue = $pixel->getColorValue(\Imagick::COLOR_BLUE);
//Do detection here
}
/* Sync the iterator, this is important to do on each iteration */
$imageIterator->syncIterator();
}
$imageIterator->clear();
Других решений пока нет …