代码github.com
中学时,我们学习了几何中的各种形状。比较容易找到圆形、正方形、三角形、椭圆形等标准形状的圆心。
但是当要找到任意形状的质心时,方法就不那么简单了。
当你在计算机视觉中工作时,寻找质心的问题也很重要——除了,你要处理的是像素而不是原子!在这篇文章中,我们将首先讨论如何找到一个任意形状的blob的中心,然后再讨论多个blob的情况。
What is a blob?
blob是图像中一组相互连接的像素,它们具有一些共同的属性(例如,灰度值)。在这篇文章中,我们的目标是使用c++中的OpenCV找到binary blob的中心。如果我们感兴趣的形状不是binary的,我们必须先将其binary。
形状的质心是什么?
形状的质心是形状中所有点的算术平均值(即平均值)。假设一个形状由n个不同的点组成,x1…x_n,则形心由
在图像处理和计算机视觉的背景下,每个形状都是由像素构成的,而形心则是构成形状的所有像素的加权平均值。
Image Moments
我们可以在OpenCV中使用矩来找到blob的中心。但首先,我们应该知道图像时刻到底是什么。图像矩是图像像素强度的一种特殊的加权平均值,它可以帮助我们发现图像的一些特定性质,如半径、面积、质心等。为了找到图像的质心,我们通常把它转换成二进制格式,然后找到它的中心。
质心由公式给出:
,
为x坐标,
为质心的y坐标,M为力矩。
在OpenCV中查找Blob形心的步骤
要找到blob的中心,我们将执行以下步骤:转换图像为灰度。
对图像执行二值化。
求出图像的中心后,计算的矩。
// declare Mat variables, thr, gray and srcMat thr, gray, src;
// convert image to grayscalecvtColor( src, gray, COLOR_BGR2GRAY );
// convert grayscale to binary imagethreshold( gray, thr, 100,255,THRESH_BINARY );
// find moments of the imageMoments m = moments(thr,true);
Point p(m.m10/m.m00, m.m01/m.m00);
// coordinates of centroidcout<< Mat(p)<< endl;
// show the image with a point mark at the centroidcircle(src, p, 5, Scalar(128,0,0), -1);
imshow("Image with center",src);
waitKey(0);
下图显示了图像中单个blob的中心
Center of multiple blobs in an Image
只找到一个blob的中心是很容易的,但是如果图像中有多个blob呢?然后,我们必须使用find等值线来找到图像中的等值线的数量并找到它们的中心。让我们看看它是如何工作的!
Mat canny_output;
vector > contours;
vector hierarchy;
// detect edges using cannyCanny( gray, canny_output, 50, 150, 3 );
// find contoursfindContours( canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
// get the momentsvector mu(contours.size());
for( int i = 0; i
{ mu[i] = moments( contours[i], false ); }
// get the centroid of figures.vector mc(contours.size());
for( int i = 0; i
{ mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }
// draw contoursMat drawing(canny_output.size(), CV_8UC3, Scalar(255,255,255));
for( int i = 0; i
{
Scalar color = Scalar(167,151,0); // B G R valuesdrawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
circle( drawing, mc[i], 4, color, -1, 8, 0 );
}
// show the resultant imagenamedWindow( "Contours", WINDOW_AUTOSIZE );
imshow( "Contours", drawing );
waitKey(0);
请注意,在查找多个blobs的中心时,我们使用了函数find等高线,它输出等高线和层次结构,其中等高线是图像中出现的所有等高线的列表。
参考