[OpenCV实战]9 使用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组成,那么质心由下式给出

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


Cx是质心的x坐标,Cy是质心的y坐标。M表示图像几何矩。注意M00可能等于0
其中图像矩计算如下:

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)
结果如下所示:

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)
结果:


4 参考
https://www.learnopencv.com/find-center-of-blob-centroid-using-opencv-cpp-python/
[OpenCV实战]9 使用OpenCV寻找平面图形的质心的更多相关文章
- [OpenCV实战]50 用OpenCV制作低成本立体相机
本文主要讲述利用OpenCV制作低成本立体相机以及如何使用OpenCV创建3D视频,准确来说是模仿双目立体相机,我们通常说立体相机一般是指双目立体相机,就是带两个摄像头的那种(目就是指眼睛,双目就是两 ...
- [OpenCV实战]48 基于OpenCV实现图像质量评价
本文主要介绍基于OpenCV contrib中的quality模块实现图像质量评价.图像质量评估Image Quality Analysis简称IQA,主要通过数学度量方法来评价图像质量的好坏. 本文 ...
- [OpenCV实战]46 在OpenCV下应用图像强度变换实现图像对比度均衡
本文主要介绍基于图像强度变换算法来实现图像对比度均衡.通过图像对比度均衡能够抑制图像中的无效信息,使图像转换为更符合计算机或人处理分析的形式,以提高图像的视觉价值和使用价值.本文主要通过OpenCV ...
- [OpenCV实战]45 基于OpenCV实现图像哈希算法
目前有许多算法来衡量两幅图像的相似性,本文主要介绍在工程领域最常用的图像相似性算法评价算法:图像哈希算法(img hash).图像哈希算法通过获取图像的哈希值并比较两幅图像的哈希值的汉明距离来衡量两幅 ...
- [OpenCV实战]47 基于OpenCV实现视觉显著性检测
人类具有一种视觉注意机制,即当面对一个场景时,会选择性地忽略不感兴趣的区域,聚焦于感兴趣的区域.这些感兴趣的区域称为显著性区域.视觉显著性检测(Visual Saliency Detection,VS ...
- [OpenCV实战]44 使用OpenCV进行图像超分放大
图像超分辨率(Image Super Resolution)是指从低分辨率图像或图像序列得到高分辨率图像.图像超分辨率是计算机视觉领域中一个非常重要的研究问题,广泛应用于医学图像分析.生物识别.视频监 ...
- [OpenCV实战]19 使用OpenCV实现基于特征的图像对齐
目录 1 背景 1.1 什么是图像对齐或图像对准? 1.2 图像对齐的应用 1.3 图像对齐基础理论 1.4 如何找到对应点 2 OpenCV的图像对齐 2.1 基于特征的图像对齐的步骤 2.2 代码 ...
- [OpenCV实战]52 在OpenCV中使用颜色直方图
颜色直方图是一种常见的图像特征,顾名思义颜色直方图就是用来反映图像颜色组成分布的直方图.颜色直方图的横轴表示像素值或像素值范围,纵轴表示该像素值范围内像素点的个数或出现频率.颜色直方图属于计算机视觉中 ...
- [OpenCV实战]33 使用OpenCV进行Hough变换
目录 1 什么是霍夫变换 1.1 应用霍夫变换以检测图像中的线条 1.2 累加器 1.3 线条检测 1.4 圆环的检测 2 代码 3 参考 1 什么是霍夫变换 霍夫变换是用于检测图像中的简单形状(诸如 ...
随机推荐
- ULID规范解读与实现原理
前提 最近发现各个频道推荐了很多ULID相关文章,这里对ULID的规范文件进行解读,并且基于Java语言自行实现ULID,通过此实现过程展示ULID的底层原理. ULID出现的背景 ULID全称是Un ...
- 蓝桥杯赛前复习C++
C标准库常用函数 memset函数:暴力清空 void *memset(void *str, int c, size_t n) str -- 指向要填充的内存块. c -- 要被设置的值.该值以 in ...
- ATT&CK框架整理(中英文整理)
工作需要了解了一下ATT&CK框架,留个记录.
- Android开发 对接微信分享SDK总结
原文:Android开发 对接微信分享SDK总结 - Stars-One的杂货小窝 公司项目需要对接微信分享,本来之前准备对接友盟分享的,但友盟的分享实际参数太多,而我又只需要对接一个微信分享,于是便 ...
- Python基础部分:4、 python语法之注释
目录 一.python语法之注释 1.什么是注释 2.如何编写注释 二.PEP8规范 一.python语法之注释 1.什么是注释 注释用来向用户提示或解释某些代码的作用和功能,它可以出现在代码中的任何 ...
- perl chmod
chmod函数改变一列文件的权限.列表的第一个元素必须是数字模式.chmod函数返回成功改变了的文件的数目.如: $cnt = chmod 0755, 'file1', 'file2'; 其中最前面 ...
- C#一个16进制数用二进制数表示是几位?
1个字节是8位,二进制8位:xxxxxxxx 范围从00000000-11111111,表示0到255.一位16进制数(用二进制表示是xxxx) 最多只表示到15(即对应16进制的F),要表示到255 ...
- Go语言核心36讲37
你好,我是郝林,今天我们继续来分享并发安全字典sync.Map的内容. 我们在上一篇文章中谈到了,由于并发安全字典提供的方法涉及的键和值的类型都是interface{},所以我们在调用这些方法的时候, ...
- 顺序表代码总结——SqList
在C++编译器下可直接运行 #include <stdio.h> #include <stdlib.h> #include <malloc.h> //顺序表存储结构 ...
- Java-数组工具类Arrays
java.util.Arrays是一个与数组相关的工具类,里面提供了大量静态方法,用来实现数组常见的操作. toSting方法 public static String toString(数组):将参 ...