网站首页 > 文章精选 正文
使用OpenCV寻找平面图形的质心
在中学,我们学习了几何的中各种平面图形。找到标准平面图形的中心(几何中心)比较容易,如圆形,方形,三角形,椭圆形等。中心是几何名词,质心是物理名词。质心是针对实物体而言的,而几何中心是针对抽象几何体而言的,对于密度均匀标准形状的物体,质心和几何中心重合。
但是当要找到任意形状的质心时,就不那么容易了。
在处理图像时,很多时候需要找到质心。在这篇文章中,我们将首先讨论如何找到任意形状blob的质心,然后我们将转向多个blob的情况。
工程代码:
https://download.csdn.net/download/luohenyj/11025933
https://github.com/luohenyueji/OpenCV-Practical-Exercise
1 名词解释
(1)blob
blob在机器视觉中是指图像中的具有相似颜色、纹理等特征所组成的一块连通区域。。在这篇文章中,我们的目标是在Python和C ++中使用OpenCV找到blob的中心。
(2)质心
一个平面图形的质心是平面图形所有点的算术平均值(即平均值)。假设一个平面图形由n个点xi组成,那么质心由下式给出
添加图片注释,不超过 140 字(可选)
在图像处理和计算机视觉领域中,每个平面图形由像素点构成,并且质心坐标为构成平面图形的所有像素点坐标的加权平均。
(3)图像矩
在OpenCV,我们用blob来称呼平面图形。我们可以在OpenCV中使用图像矩找到blob的中心。图像矩是图像像素值的加权平均值,借助它我们可以找到图像的一些特定属性,如半径,面积,质心等。为了找到图像的质心,我们通常将其二值化然后找到它的质心。质心由下式给出:
添加图片注释,不超过 140 字(可选)
添加图片注释,不超过 140 字(可选)
Cx是质心的x坐标,Cy是质心的y坐标。M表示图像几何矩。注意M00可能等于0
其中图像矩计算如下:
添加图片注释,不超过 140 字(可选)
1
2 在OpenCV中查找Blob质心的步骤
要找到blob的质心,我们将执行以下步骤:-
1.将图像转换为灰度图。
2.对图像执行二值化。
3.计算图像矩后找到图像的中心。
单个blob的质心寻找。pch为预编译文件
C++代码:
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
int main()
{
String img_path = "./image/circle.png";
Mat src, gray, thr;
src = 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 << Mat(p) << 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)
结果如下所示:
添加图片注释,不超过 140 字(可选)
3 图像多个blob下的质心获取
找到一个blob的质心非常容易,但是如果Image中有多个blob,我们将不得不使用findContours来查找图像中的轮廓数量并找到每个轮廓的中心。然后再计算几何矩。
C++代码:
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
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 = 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<vector<Point> > contours;
//轮廓输出结果向量
vector<Vec4i> 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<Moments> mu(contours.size());
//求取每个轮廓的矩
for (int i = 0; i < contours.size(); i++)
{
mu[i] = moments(contours[i], false);
}
/// Get the centroid of figures. 轮廓质点
vector<Point2f> mc(contours.size());
for (int i = 0; i < 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 < 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 np
img = 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)
结果:
添加图片注释,不超过 140 字(可选)
添加图片注释,不超过 140 字(可选)
4 参考
https://www.learnopencv.com/find-center-of-blob-centroid-using-opencv-cpp-python/
引用链接
[1] https://download.csdn.net/download/luohenyj/11025933: https://download.csdn.net/download/luohenyj/11025933
[2] https://github.com/luohenyueji/OpenCV-Practical-Exercise: https://github.com/luohenyueji/OpenCV-Practical-Exercise
[3] https://www.learnopencv.com/find-center-of-blob-centroid-using-opencv-cpp-python/ : https://www.learnopencv.com/find-center-of-blob-centroid-using-opencv-cpp-python/
- 上一篇: opencv实战——机器视觉检测和计数
- 下一篇: 数字图像处理库-OpenCV
猜你喜欢
- 2025-01-01 前端智能化实践:从图片识别UI样式
- 2025-01-01 OpenCV 和 Python 识别数字的结果是怎样的呢
- 2025-01-01 HALCON_极坐标变换
- 2025-01-01 python使用fitz和opencv库提取pdf中的表格
- 2025-01-01 Fluent 多孔介质仿真(Porous Media)
- 2025-01-01 基于密度(Density-based)的聚类——核密度估计(KDE)
- 2025-01-01 机器视觉halcon学习系列---XLD的介绍和使用
- 2025-01-01 平学(26):Matlab学习之三维曲面图与常见函数(2)
- 2025-01-01 [OpenCV实战]13 OpenCV中使用Mask R-CNN进行对象检测和实例分割
- 2025-01-01 OpenCV使用分水岭算法实现图像分割
- 05-05MyBatis的三种分页方式,你学废了吗?
- 05-05如何写一个简单的分页(最简单的分页)
- 05-05详解如何使用Spring Data JPA进行数据的分页与排序
- 05-05手速太快引发分页翻车?前端竞态陷阱揭秘
- 05-05前端分页机制的具体实现(分页前端需要做什么)
- 05-05一个后勾腿动作,有效疏通血管,改善下肢发麻,促进全身燃脂
- 05-05大型调相机起动及并网研究(什么是调相机,与发电机区别)
- 05-05你们都是托:动态对比度其实是骗你的
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 稳压管的稳压区是工作在什么区 (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)