PHP:计算图像中的对象组
PHP: Count object groups in image
我需要自动计算这张图片中的点数。我们可以假设这些点总是红色的(如果有帮助的话,也可以是黑色的)并且在白色背景上总是这个大小。位置和计数经常变化
起初我以为我可以使用 Tesseract OCR 并且可以计算句点或项目符号,但是无论我如何处理图像或白名单字符,结果都是空的。
我尝试的另一件事是使用 Imagick,它有一个连接组件函数,但在我的测试中我使用了相同的代码但没有得到任何结果...
我查看了 OpenCV,但 PHP 的唯一端口使用主要用中文编写的文档并且不支持完整的库,因此抛出霍夫变换 window。
下面的代码:最后我冒险使用 PHP 读取图像并循环遍历像素并找到任何超出特定阈值的像素,但我对如何对单个像素进行实际分组感到困惑到一个对象。 -- 请注意,尽管没有内存限制和执行时间限制,但我无法使用全尺寸图像(即使它们已经缩小)。
我花了一天半的时间在这上面,看起来很简单,形状一致,但不...
图片如下:
// creating the initial image
$starting_img = imagecreatefrompng("converted.png");
//Dimentions
$imgDims = getimagesize($source_image);
$scanWidth = $imgDims[0];
$scanHeight = $imgDims[1];
//New image
$final = imagecreatetruecolor($scanWidth,$scanHeight);
$white = imagecolorallocate($final, 255, 255, 255);
imagefill($final,0,0,$white);
$imageData = array();
for ($y=1; $y < $scanHeight - 1; $y++) {
// Get First Row, the scan each row col
$currentRow = array();
for ($x=1; $x < $scanWidth - 1; $x++) {
// Get first col in row 1 and check its data
$rgb = imagecolorat($starting_img,$x,$y);
$color = array(
'r' => ($rgb >> 16) & 255,
'g' => ($rgb >> 8) & 255,
'b' => $rgb & 255
);
$currentCol = array(
'x' => $x,
'y' => $y,
'r' => $color['r'],
'g' => $color['g'],
'b' => $color['b'],
);
//Is the pixel red?
// if ($color['r'] > 200 && $color['g'] < 100 && $color['b'] < 100) {
array_push($currentRow, $currentCol);
// }
}
//Does this row have any red pixels?
// if (count($currentRow) > 1) {
array_push($imageData, $currentRow);
// }
}
foreach ($imageData as $currentRow => $row) {
foreach ($row as $currentCol => $col) {
$newColoredPixel = imagecolorallocate($final,$col['r'],$col['g'],$col['b']);
// adding the new pixel to the new image
imagesetpixel($final,$col['x'],$col['y'],$newColoredPixel);
}
}
file_put_contents('imageData.txt', print_r($imageData, true));
imagepng($final,"final.png");
imagedestroy($final);
imagedestroy($starting_img);
好问题!
如果斑点不重叠 - 您可以通过公式计算它们:
blob_count = total_blob_area / blob_unit_area
在你的例子中,blob 是一个圆,所以公式变成:
blob_count = total_blob_area / (π * r^2)
total_blob_area 只是一个带红色的 像素数 ,但您必须根据经验找到 blob 单位直径。
顺便说一句,函数 imagecolorat() returns 仅当图像是 truecolor 类型时才使用 RGB 值,但是您给定的 PNG 具有索引颜色 space,所以为了能够从中提取真实的 RGB 值 - 您必须将 imagecolorat() 的输出传递给 imagecolorsforindex().
上面描述的blob计数方法的代码是这样的:
function countBlobs($imfile, $blob_diameter) {
$blob_area = pi()*pow($blob_diameter/2, 2);
$im = imagecreatefrompng($imfile);
list($width, $height, $type, $attr) = getimagesize($imfile);
$total_blob_area = 0;
for ($x=0; $x < $width; $x++) {
for ($y=0; $y < $height; $y++) {
$rgb = imagecolorat($im, $x, $y);
$colors = imagecolorsforindex($im, $rgb);
$avg = ($colors['red']+$colors['green']+$colors['blue'])/3;
if ($avg < 150)
{
$total_blob_area++;
}
}
}
$blobs = $total_blob_area / $blob_area;
return round($blobs);
}
echo ('blobs : ' . countBlobs('countblobs.png', 16));
您可以使用 GIMP 中的距离测量工具找到斑点单位直径。但是,如果您的斑点可以具有不同的形状/大小 - 那么您将需要对斑点单位面积进行某种平均。
我需要自动计算这张图片中的点数。我们可以假设这些点总是红色的(如果有帮助的话,也可以是黑色的)并且在白色背景上总是这个大小。位置和计数经常变化
起初我以为我可以使用 Tesseract OCR 并且可以计算句点或项目符号,但是无论我如何处理图像或白名单字符,结果都是空的。
我尝试的另一件事是使用 Imagick,它有一个连接组件函数,但在我的测试中我使用了相同的代码但没有得到任何结果...
我查看了 OpenCV,但 PHP 的唯一端口使用主要用中文编写的文档并且不支持完整的库,因此抛出霍夫变换 window。
下面的代码:最后我冒险使用 PHP 读取图像并循环遍历像素并找到任何超出特定阈值的像素,但我对如何对单个像素进行实际分组感到困惑到一个对象。 -- 请注意,尽管没有内存限制和执行时间限制,但我无法使用全尺寸图像(即使它们已经缩小)。
我花了一天半的时间在这上面,看起来很简单,形状一致,但不...
图片如下:
// creating the initial image
$starting_img = imagecreatefrompng("converted.png");
//Dimentions
$imgDims = getimagesize($source_image);
$scanWidth = $imgDims[0];
$scanHeight = $imgDims[1];
//New image
$final = imagecreatetruecolor($scanWidth,$scanHeight);
$white = imagecolorallocate($final, 255, 255, 255);
imagefill($final,0,0,$white);
$imageData = array();
for ($y=1; $y < $scanHeight - 1; $y++) {
// Get First Row, the scan each row col
$currentRow = array();
for ($x=1; $x < $scanWidth - 1; $x++) {
// Get first col in row 1 and check its data
$rgb = imagecolorat($starting_img,$x,$y);
$color = array(
'r' => ($rgb >> 16) & 255,
'g' => ($rgb >> 8) & 255,
'b' => $rgb & 255
);
$currentCol = array(
'x' => $x,
'y' => $y,
'r' => $color['r'],
'g' => $color['g'],
'b' => $color['b'],
);
//Is the pixel red?
// if ($color['r'] > 200 && $color['g'] < 100 && $color['b'] < 100) {
array_push($currentRow, $currentCol);
// }
}
//Does this row have any red pixels?
// if (count($currentRow) > 1) {
array_push($imageData, $currentRow);
// }
}
foreach ($imageData as $currentRow => $row) {
foreach ($row as $currentCol => $col) {
$newColoredPixel = imagecolorallocate($final,$col['r'],$col['g'],$col['b']);
// adding the new pixel to the new image
imagesetpixel($final,$col['x'],$col['y'],$newColoredPixel);
}
}
file_put_contents('imageData.txt', print_r($imageData, true));
imagepng($final,"final.png");
imagedestroy($final);
imagedestroy($starting_img);
好问题!
如果斑点不重叠 - 您可以通过公式计算它们:
blob_count = total_blob_area / blob_unit_area
在你的例子中,blob 是一个圆,所以公式变成:
blob_count = total_blob_area / (π * r^2)
total_blob_area 只是一个带红色的 像素数 ,但您必须根据经验找到 blob 单位直径。
顺便说一句,函数 imagecolorat() returns 仅当图像是 truecolor 类型时才使用 RGB 值,但是您给定的 PNG 具有索引颜色 space,所以为了能够从中提取真实的 RGB 值 - 您必须将 imagecolorat() 的输出传递给 imagecolorsforindex().
上面描述的blob计数方法的代码是这样的:
function countBlobs($imfile, $blob_diameter) {
$blob_area = pi()*pow($blob_diameter/2, 2);
$im = imagecreatefrompng($imfile);
list($width, $height, $type, $attr) = getimagesize($imfile);
$total_blob_area = 0;
for ($x=0; $x < $width; $x++) {
for ($y=0; $y < $height; $y++) {
$rgb = imagecolorat($im, $x, $y);
$colors = imagecolorsforindex($im, $rgb);
$avg = ($colors['red']+$colors['green']+$colors['blue'])/3;
if ($avg < 150)
{
$total_blob_area++;
}
}
}
$blobs = $total_blob_area / $blob_area;
return round($blobs);
}
echo ('blobs : ' . countBlobs('countblobs.png', 16));
您可以使用 GIMP 中的距离测量工具找到斑点单位直径。但是,如果您的斑点可以具有不同的形状/大小 - 那么您将需要对斑点单位面积进行某种平均。