关于 OpenCV 算法 contourArea想法

一 :问题提出

       最近使用OpenCV做图像处理 使用 contourArea算法来计算, 通过findContours 获取的轮廓的面积

		findContours(img_edge, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
		sort(contours.begin(), contours.end(), Contour_Area);

		vector<Spot>spotProperty(((int)contours.size()) - 1);
		for (int i = 0; i < ((int)contours.size()); i++)
		{
			int area = contourArea(contours[i]);
        }

通过数据显示发现得到的 area有值为0的情况,但是轮廓的最小外接矩形的长、 宽又不为0 很是奇怪,而且明显不符合对面积的筛选实际。

具体解析可以参考 博客:https://blog.csdn.net/yiqiudream/article/details/51858421 的解释说明。

二:解决方式

通过在网上查询及探讨 发现可以通过 countNonZero算法来获取非0 数值的面积

具体解决算法如下  方式一:

		vector<vector<Point>> contours;
		vector<Vec4i> hierarchy;
		findContours(img_edge, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
		sort(contours.begin(), contours.end(), Contour_Area);

		vector<Spot>spotProperty(((int)contours.size()) - 1);
		for (int i = 0; i < ((int)contours.size()); i++)
		{
			RotatedRect minRect = minAreaRect(contours[i]);
			//int area = contourArea(contours[i]);

			Rect rect = boundingRect(contours[i]);
			Mat rectImg = Mat(curImg, rect);
			int area = countNonZero(rectImg);

			int width = minRect.size.width;
			int height = minRect.size.height;

			result += to_string(area) + "," + to_string(minRect.center.x) + "," + to_string(minRect.center.y) + "," + to_string(minRect.center.x - imgWidth / 2) + "," + to_string(minRect.center.y - imgHeight / 2) + "," + to_string(width) + "," + to_string(height) + ";";
		}

通过 boundingRect 算法获取轮廓的外接矩形 并在原图像上进行截取,然后使用 countNonZero算法获取非0值作为轮廓面积。

方式二 :通过轮廓的特征矩获取 轮廓的面积和轮廓的重心

针对一幅图像,我们把像素的坐标看成是一个二维随机变量(X, Y),那么一副灰度图可以用二维灰度图密度函数来表示,因此可以用矩来描述灰度图像的特征。 

		vector<vector<Point>> contours;
		vector<Vec4i> hierarchy;
		findContours(img_edge, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
		sort(contours.begin(), contours.end(), Contour_Area);

  /// 计算矩
  ///vector<Moments> mu(contours.size() );
  ///for( int i = 0; i < contours.size(); i++ )
  ///   { mu[i] = moments( contours[i], false ); }

  /// 计算中心矩:
  /// 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 ); }

		vector<Spot>spotProperty(((int)contours.size()) - 1);
		for (int i = 0; i < ((int)contours.size()); i++)
		{
			RotatedRect minRect = minAreaRect(contours[i]);

            //int area = contourArea(contours[i]);

            Moments mu= moments( contours[i], false );
            double centerX=mu.m10/mu.m00;
            double centerY=mu.m01/mu.m00;
            int  area=mu.m00;
		
			int width = minRect.size.width;
			int height = minRect.size.height;

			result += to_string(area) + "," + to_string(centerX) + "," + to_string(centerY) + "," + to_string(centerX - imgWidth / 2) + "," + to_string(centerY - imgHeight / 2) + "," + to_string(width) + "," + to_string(height) + ";";
		}

令Xc,Yc表示区域重心的坐标,则:

Xc = M10/M00;

Yc = M01/M00;

在二值图像的情况下,M00表示区域的面积

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐细雨如春风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值