[OpenCV实战]9 使用OpenCV寻找平面图形的质心

出门莫恨无人随,书中车马多如簇。这篇文章主要讲述[OpenCV实战]9 使用OpenCV寻找平面图形的质心相关的知识,希望能为你提供帮助。
在中学,我们学习了几何的中各种平面图形。找到标准平面图形的中心(几何中心)比较容易,如圆形,方形,三角形,椭圆形等。中心是几何名词,质心是物理名词。质心是针对实物体而言的,而几何中心是针对抽象几何体而言的,对于密度均匀标准形状的物体,质心和几何中心重合。
但是当要找到任意形状的质心时,就不那么容易了。
在处理图像时,很多时候需要找到质心。在这篇文章中,我们将首先讨论如何找到任意形状blob的质心,然后我们将转向多个blob的情况。
工程代码:
1 名词解释(1)blob
blob在机器视觉中是指图像中的具有相似颜色、纹理等特征所组成的一块连通区域。。在这篇文章中,我们的目标是在python和C ++中使用OpenCV找到blob的中心。
(2)质心
一个平面图形的质心是平面图形所有点的算术平均值(即平均值)。假设一个平面图形由n个点xi组成,那么质心由下式给出

[OpenCV实战]9 使用OpenCV寻找平面图形的质心

文章图片

在图像处理和计算机视觉领域中,每个平面图形由像素点构成,并且质心坐标为构成平面图形的所有像素点坐标的加权平均。
(3)图像矩
在OpenCV,我们用blob来称呼平面图形。我们可以在OpenCV中使用图像矩找到blob的中心。图像矩是图像像素值的加权平均值,借助它我们可以找到图像的一些特定属性,如半径,面积,质心等。为了找到图像的质心,我们通常将其二值化然后找到它的质心。质心由下式给出: -
[OpenCV实战]9 使用OpenCV寻找平面图形的质心

文章图片

[OpenCV实战]9 使用OpenCV寻找平面图形的质心

文章图片

Cx是质心的x坐标,Cy是质心的y坐标。M表示图像几何矩。注意M00可能等于0
其中图像矩计算如下:
[OpenCV实战]9 使用OpenCV寻找平面图形的质心

文章图片

2 在OpenCV中查找Blob质心的步骤要找到blob的质心,我们将执行以下步骤: -
1.将图像转换为灰度图。
2.对图像执行二值化。
3.计算图像矩后找到图像的中心。
单个blob的质心寻找。pch为预编译文件
C++代码:
#include "pch.h" #include & lt; opencv2/opencv.hpp& gt; #include & lt; iostream& gt; #include & lt; stdio.h& gt; #include & lt; stdlib.h& gt; using namespace cv; using namespace std; int main()String img_path = "./image/circle.png"; Mat src, gray, thr; src = https://www.songbingjia.com/android/imread(img_path); // convert image to grayscale 获取灰度图 cvtColor(src, gray, COLOR_BGR2GRAY); // convert grayscale to binary image 二值化 threshold(gray, thr, 0, 255, THRESH_OTSU); // find moments of the image 提取二值图像矩,true表示图像二值化了 Moments m = moments(thr, true); Point p(m.m10 / m.m00, m.m01 / m.m00); // coordinates of centroid 质心坐标 cout & lt; & lt; Mat(p) & lt; & lt; endl; // show the image with a point mark at the centroid 画出质心 circle(src, p, 5, Scalar(128, 0, 0), -1); imshow("show", src); waitKey(0); return 0;

python代码:
#coding=utf-8 import cv2 import numpy as np# read image through command line img = cv2.imread(./image/circle.png)# convert image to grayscale image gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# convert the grayscale image to binary image ret,thresh = cv2.threshold(gray_image,127,255,0)# calculate moments of binary image M = cv2.moments(thresh)# calculate x,y coordinate of center cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"])# put text and highlight the center cv2.circle(img, (cX, cY), 5, (255, 255, 255), -1) cv2.putText(img, "centroid", (cX - 25, cY - 25),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)# display the image cv2.imshow("Image", img) cv2.waitKey(0)

结果如下所示:
[OpenCV实战]9 使用OpenCV寻找平面图形的质心

文章图片

3 图像多个blob下的质心获取找到一个blob的质心非常容易,但是如果Image中有多个blob,我们将不得不使用findContours来查找图像中的轮廓数量并找到每个轮廓的中心。然后再计算几何矩。
C++代码:
#include "pch.h" #include & lt; opencv2/opencv.hpp& gt; #include & lt; iostream& gt; #include & lt; stdio.h& gt; #include & lt; stdlib.h& gt; using namespace cv; using namespace std; RNG rng(12345); void find_moments(Mat src); int main()String img_path = "./image/multiple.png"; /// Load source image, convert it to gray Mat src, gray; src = https://www.songbingjia.com/android/imread(img_path); cvtColor(src, gray, COLOR_BGR2GRAY); //显示原图 namedWindow("Source", WINDOW_AUTOSIZE); imshow("Source", src); // call function to find_moments 寻质心函数 find_moments(gray); waitKey(0); return(0); void find_moments(Mat gray)Mat canny_output; //各个轮廓的点集合 vector& lt; vector& lt; Point& gt; & gt; contours; //轮廓输出结果向量 vector& lt; Vec4i& gt; hierarchy; /// Detect edges using canny 边缘算子提取轮廓 Canny(gray, canny_output, 50, 150, 3); // Find contours 寻找轮廓 RETR_TREE表示提取所有轮廓 findContours(canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0)); /// Get the moments 图像矩 vector& lt; Moments& gt; mu(contours.size()); //求取每个轮廓的矩 for (int i = 0; i & lt; contours.size(); i++)mu[i] = moments(contours[i], false); ///Get the centroid of figures. 轮廓质点 vector& lt; Point2f& gt; mc(contours.size()); for (int i = 0; i & lt; contours.size(); i++)mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00); /// Draw contours //画轮廓 Mat drawing(canny_output.size(), CV_8UC3, Scalar(255, 255, 255)); for (int i = 0; i & lt; contours.size(); i++)Scalar color = Scalar(167, 151, 0); //画轮廓 drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point()); //画质心 circle(drawing, mc[i], 4, color, -1, 7, 0); /// Show the resultant image namedWindow("Contours", WINDOW_AUTOSIZE); imshow("Contours", drawing); waitKey(0);

python代码:
#coding=utf-8 import cv2 import numpy as npimg = cv2.imread(./image/multiple.png)# convert the image to grayscale gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # convert the grayscale image to binary image ret,thresh = cv2.threshold(gray_image,127,255,0)# find contour in the binary image contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) # find contour in the binary image(opencv4) #binary, contours, opt= cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) for c in contours: # calculate moments for each contour M = cv2.moments(c) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"])# calculate x,y coordinate of center cv2.circle(img, (cX, cY), 5, (255, 255, 255), -1) cv2.putText(img, "centroid", (cX - 25, cY - 25),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)# 3.4.1 im2, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # 3.2.0 im2, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)# display the image cv2.imshow("Image", img) cv2.waitKey(0)

结果:
[OpenCV实战]9 使用OpenCV寻找平面图形的质心

文章图片

【[OpenCV实战]9 使用OpenCV寻找平面图形的质心】
[OpenCV实战]9 使用OpenCV寻找平面图形的质心

文章图片


    推荐阅读