对图像中的对象(圆)进行提取

本文介绍了图像处理中的对象提取技术,包括二值化、形态学操作及霍夫圆变换的应用。通过实例展示了如何从图像中准确提取圆形对象,对比了不同方法的效果,并详细解释了霍夫圆变换的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.问题描述
对图像中对象进行提取,获取所需要的对象,去掉其它干扰和非目标对象。
二.参考的博客
https://blog.youkuaiyun.com/weixin_41695564/article/details/80099917
https://blog.youkuaiyun.com/a369189453/article/details/86602403
上面两个博客的思路差不多,都是通过二值分割+形态学处理+横纵比计算,鉴于他们的程序注释清晰,方便以后自己查阅。
三.实际的问题
一开始,学习对象提取的时候,跟着教程学习的,由于视频中处理的图像我没有找到资源,于是我就随便找了个图像,想试试通过视频中的方法能不能也达到对象提取的效果,结果却不尽人意,找出了两个圆,我也换了二值化的几个方法,还是不行。程序如下:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
using namespace std;

Mat srcImage, dstImage;

int main(int argc, char** argv)
{
	srcImage = imread("E:\\pictures\\44.jpg", IMREAD_GRAYSCALE);
 	if (!srcImage.data)
 	{
 		cout << "图片读取错误,请检测路径!" << endl;
  		return -1;
 	}
 	namedWindow("原图", WINDOW_AUTOSIZE);
 	imshow("原图", srcImage);

	//二值化
 	Mat binaryImage;
 	threshold(srcImage, binaryImage, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
 	imshow("二值化后", binaryImage);

	//形态学操作:闭运算
 	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
 	morphologyEx(binaryImage, dstImage, MORPH_CLOSE, kernel, Point(-1, -1));
 	imshow("闭运算后", dstImage);
 	
	//开运算
 	morphologyEx(binaryImage, dstImage, MORPH_OPEN, kernel, Point(-1, -1));
 	imshow("开运算后", dstImage);

	//寻找轮廓
 	vector<vector<Point>> contours;
 	vector<Vec4i> hireachy;
 	findContours(dstImage, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());

	//轮廓的绘制
 	//同时通过对轮廓的面积、横纵比大小的过滤,留下我们想要的那个圆
 	Mat resultImage = Mat::zeros(srcImage.size(), CV_8UC3); 
 	Point circle_center;              //定义圆心坐标
 	//计算点集所围区域的面积
 	for (auto t = 0; t < contours.size(); ++t)
 	{
 		double area = contourArea(contours[t]);     //计算点集所围区域的面积
  		if (area < 100)     //晒选出轮廓面积大于100的轮廓   
   			continue;  // 横纵比过滤 
   		Rect rect = boundingRect(contours[t]);  // 求点集的最小直立外包矩形  
  		float ratio = float(rect.width) / float(rect.height);   //求出宽高比   
  		if (ratio < 1.1 && ratio > 0.9)   //因为圆的外接直立矩形肯定近似于一个正方形,因此宽高比接近1.0  
  		{
  			//在黑色背景图上画出圆,注意其中参数-1的意义 
  			drawContours(resultImage, contours, t, Scalar(0, 0, 255), -1, 8, Mat(), 0, Point()); 
  			printf("圆的面积: %f\n", area);
   			double arc_length = arcLength(contours[t], true);    //计算点集所围区域的周长
   			printf("圆的周长 : %f\n", arc_length);
   			int x = rect.x + rect.width / 2;
   			int y = rect.y + rect.height / 2;
   			circle_center = Point(x, y);    //得到圆心坐标   
   			cout << "圆心坐标:" << "宽" << circle_center.x << " " << "高" << circle_center.y << endl;
   			circle(resultImage, circle_center, 2, Scalar(0, 255, 255), 2, 8, 0);
  		}
 	}
 	imshow("效果图", resultImage);
 	Mat circle_img = srcImage.clone();
 	cvtColor(circle_img, circle_img, COLOR_GRAY2BGR); //灰度图转化为彩色图 
 	circle(circle_img, circle_center, 2, Scalar(0, 0, 255), 2, 8, 0);    
 	//在原图上画出圆心 
 	imshow("最终结果", circle_img);
 	
 	waitKey(0);
	return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四.解决的办法
后来突然想到了霍夫圆变换:HoughCricles()函数。

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <cmath>

using namespace cv;
using namespace std;

const double PI = atan(1.) * 4.; //圆周率

int main(int argc, char** argv)
{
	//【1】载入原始图、Mat变量定义   
 	Mat srcImage = imread("E:\\pictures\\44.jpg");  
 	Mat midImage, dstImage;//临时变量和目标图的定义

	//【2】显示原始图
 	imshow("【原始图】", srcImage);

	//【3】转为灰度图并进行图像平滑
 	cvtColor(srcImage, midImage, COLOR_BGR2GRAY);//转化边缘检测后的图为灰度图
 	GaussianBlur(midImage, midImage, Size(9, 9), 2, 2);

	//【4】进行霍夫圆变换
 	vector<Vec3f> circles;
 	HoughCircles(midImage, circles, HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);

	//【5】依次在图中绘制出圆
 	for (size_t i = 0; i < circles.size(); i++)
 	{
 		//参数定义
  		Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
  		int radius = cvRound(circles[i][2]);
  		//绘制圆心
  		circle(srcImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);
  		//绘制圆轮廓
  		circle(srcImage, center, radius, Scalar(155, 50, 255), 3, 8, 0);
  		cout << "圆心坐标:宽:" << center.x << " 高:" << center.y << endl;
  		cout << "圆的周长:" << 2 * PI * radius << endl;
  		cout << "圆的面积:" << PI * pow(radius, 2) << endl;
 	}

	//【6】显示效果图  
 	imshow("【效果图】", srcImage);
 	
 	waitKey(0);
 	return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
终于解决了。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

boss-dog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值