问题描述:利用opencv 库函数contourArea()计算轮廓面积得到的面积比实际面积小的原因,及其求精确面积方法。
opencv contourArea()使用方法:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
Mat image = imread("example.jpg", IMREAD_GRAYSCALE); // 读取灰度图像
if (image.empty()) {
cout << "Could not read the image." << endl;
return -1;
}
vector<vector<Point>> contours; // 存储轮廓的向量
findContours(image, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE); // 查找轮廓
double area = 0; // 轮廓面积
for (size_t i = 0; i < contours.size(); i++) {
area += contourArea(contours[i]); // 计算轮廓面积
}
cout << "Total contour area: " << area << endl; // 输出轮廓面积
return 0;
}
如图所示,以求一个半径为10的圆面积为例:
利用contourArea()提取圆的外轮廓,计算外轮廓面积为:288;
利用圆面积公式计算圆的面积为:10*10*3.14=314;
原因分析:
contourArea()面积计算原理,如下图所示:
利用contourArea()计算轮廓面积实际为轮廓中心点所围成虚拟轮廓的面积,而非实际轮廓面积。
解决方法:
方法1:
使用drawContours
函数将轮廓绘制到空白图像上,然后使用countNonZero
函数统计非零像素的数量。下面是示例代码:
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
// 读取图像并转换为灰度图像
Mat image = imread("image.jpg");
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
// 检测轮廓并绘制到空白图像上
vector<vector<Point>> contours;
findContours(gray, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
Mat drawing = Mat::zeros(image.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++) {
drawContours(drawing, contours, i, Scalar(255, 255, 255), 1);
}
// 统计非零像素的数量
int count = countNonZero(drawing);
cout << "Number of pixels in contours: " << count << endl;
return 0;
}
方法1 ,计算圆面积为317,与原实际面积314相差3
方法2:
利用contourArea()函数计算面积,加上轮廓周长的一半,
轮廓精确周长就算方法见:微信用户:opencv ArcLength()计算轮廓周长偏大问题,及解决办法
c++代码示例:
#include<opencv2//opencv.hpp>
#include<math.h>
using namespace std;
using namespace cv;
int main()
{
Mat img = Mat::zeros(Size(300,300), CV_8UC1);
circle(img,Point(150,150),10,Scalar(255),-1);
vector<vector<Point>>contours;
findContours(img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
double a=contourArea(contours[0]);
float b = arcLength(contours[0],true);
vector<Point>contours_poly;
approxPolyDP(contours[0], contours_poly, 1, true);
float d = arcLength(contours_poly, true);
float circle_area = a + d / 2;
cout << circle_area << endl;
return 0;
}
方法2 ,计算圆面积为318,与原实际面积314相差4