基于opencv的物体定位

7 篇文章 0 订阅
2 篇文章 0 订阅

opencv是一个很强大的机器视觉库,利用它我们可以开发出丰富多彩的使用项目。近日,我在研究一个图中物体定位系统。本程序用的是OpenCV2.4.9,附带OpenCV3.0。

程序中的原图为我随手拍的一张图片


图中有三个物体,都是蓝色的,我首先取原图的蓝色通道变为灰度图


灰度图经过中值滤波后可以得到去噪后的图片


根据原图的蓝色通道和红色通道的大概取值范围,我们可得到比较满意的二值图


为了去掉物体中少量的黑色部分,我用闭运算


然而,图中最上面的那个物体里面还有一块很大的黑色(目前我也不知道怎么去掉,如果有大神知道望告知~~)

接下来就是找出物体的轮廓


最后找到能包围轮廓的最小矩形


好了,占时就这么多了

下面是配套的程序

OpenCV2.4.9半根

#include<opencv2\opencv.hpp>
#include<iostream>
#define BIN_DIV 110

using namespace std;
using namespace cv;

int main()
{
	Mat srcImg, midImg, dstImg;
	srcImg = imread("hehe.jpg");
	Mat xianshi = srcImg.clone();
	Mat redChannel;
	namedWindow("【原图】", WINDOW_NORMAL);
	imshow("【原图】", srcImg);
	Mat grayImg;
	vector<Mat> channels;
	split(srcImg, channels);
	//cvtColor(srcImg,grayImg,COLOR_BGR2GRAY);
	grayImg = channels.at(0);
	redChannel = channels.at(2);
	namedWindow("【灰度图】", WINDOW_NORMAL);
	imshow("【灰度图】", grayImg);
	//均值滤波
	blur(grayImg, grayImg, Size(20, 20), Point(-1, -1));
	namedWindow("【均值滤波后】", WINDOW_NORMAL);
	imshow("【均值滤波后】", grayImg);
	//转化为二值图
	Mat midImg1 = grayImg.clone();
	int rowNumber = midImg1.rows;
	int colNumber = midImg1.cols;

	for (int i = 0; i<rowNumber; i++)
	{
		uchar* data = midImg1.ptr<uchar>(i);  //取第i行的首地址
		uchar* redData = redChannel.ptr<uchar>(i);
		for (int j = 0; j<colNumber; j++)
		{
			if (data[j]>BIN_DIV&&redData[j]<BIN_DIV *2/ 3)
				data[j] = 255;
			else
				data[j] = 0;
		}
	}
	namedWindow("【二值图】", WINDOW_NORMAL);
	imshow("【二值图】", midImg1);
	Mat midImg2 = midImg1.clone();
	Mat element = getStructuringElement(MORPH_RECT, Size(40, 40));
	morphologyEx(midImg1, midImg2, MORPH_CLOSE, element);
	namedWindow("【闭运算后】", WINDOW_NORMAL);
	imshow("【闭运算后】", midImg2);
	cout << "midImg1.channel=" << midImg1.channels() << endl;
	cout << "mdiImg1.depth" << midImg1.depth() << endl;
	//查找图像轮廓
	Mat midImg3 = Mat::zeros(midImg2.rows, midImg2.cols, CV_8UC3);
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(midImg2, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
	int index = 0;
	for (; index >= 0; index = hierarchy[index][0])
	{
		Scalar color(255, 255, 255);
		drawContours(midImg3, contours, index, color, NULL, 8, hierarchy);
	}
	namedWindow("【轮廓图】", WINDOW_NORMAL);
	imshow("【轮廓图】", midImg3);
	Mat midImg4 = midImg3.clone();
	//创建包围轮廓的矩形边界
	for (int i = 0; i<contours.size(); i++)
	{
		//每个轮廓
		vector<Point> points = contours[i];
		//对给定的2D点集,寻找最小面积的包围矩形
		RotatedRect box = minAreaRect(Mat(points));
		Point2f vertex[4];
		box.points(vertex);
		//绘制出最小面积的包围矩形
		line(xianshi, vertex[0], vertex[1], Scalar(100, 200, 211), 6, CV_AA);
		line(xianshi, vertex[1], vertex[2], Scalar(100, 200, 211), 6, CV_AA);
		line(xianshi, vertex[2], vertex[3], Scalar(100, 200, 211), 6, CV_AA);
		line(xianshi, vertex[3], vertex[0], Scalar(100, 200, 211), 6, CV_AA);
		//绘制中心的光标
		Point s1, l, r, u, d;
		s1.x = (vertex[0].x + vertex[2].x) / 2.0;
		s1.y = (vertex[0].y + vertex[2].y) / 2.0;
		l.x = s1.x - 10;
		l.y = s1.y;

		r.x = s1.x + 10;
		r.y = s1.y;

		u.x = s1.x;
		u.y = s1.y - 10;

		d.x = s1.x;
		d.y = s1.y + 10;
		line(xianshi, l, r, Scalar(100, 200, 211), 2, CV_AA);
		line(xianshi, u, d, Scalar(100, 200, 211), 2, CV_AA);
	}
	namedWindow("【绘制的最小面积矩形】", WINDOW_NORMAL);
	imshow("【绘制的最小面积矩形】", xianshi);
	waitKey(0);
	return 0;
}

OpenCV3.0版本

#include<opencv2\opencv.hpp>
#include<iostream>
#define BIN_DIV 120

using namespace std;
using namespace cv;

int main()
{
	Mat srcImg=imread("haha.jpg");
	Mat xianshi=srcImg.clone();
	Mat redChannel;
	namedWindow("【原图】",WINDOW_NORMAL);
	imshow("【原图】",srcImg);
	Mat grayImg;
	vector<Mat> channels;
	split(srcImg,channels);
	//cvtColor(srcImg,grayImg,COLOR_BGR2GRAY);
	grayImg=channels.at(0);
	redChannel=channels.at(2);
	namedWindow("【灰度图】",WINDOW_NORMAL);
	imshow("【灰度图】",grayImg);	
	//均值滤波
	blur(grayImg,grayImg,Size(20,20),Point(-1,-1));
	namedWindow("【均值滤波后】",WINDOW_NORMAL);
	imshow("【均值滤波后】",grayImg);
	//转化为二值图
	Mat midImg1=grayImg.clone();
	int rowNumber=midImg1.rows;
	int colNumber=midImg1.cols;

	for(int i=0;i<rowNumber;i++)
	{
		uchar* data=midImg1.ptr<uchar>(i);  //取第i行的首地址
		uchar* redData=redChannel.ptr<uchar>(i);
		for(int j=0;j<colNumber;j++)
		{
			if(data[j]>BIN_DIV&&redData[j]<BIN_DIV/2)
				data[j]=0;
			else
				data[j]=255;
		}
	}
	namedWindow("【二值图】",WINDOW_NORMAL);
	imshow("【二值图】",midImg1);
	Mat midImg2=midImg1.clone();
	Mat element=getStructuringElement(MORPH_RECT,Size(20,20));
	morphologyEx(midImg1,midImg2,MORPH_OPEN,element);
	namedWindow("【开运算后】",WINDOW_NORMAL);
	imshow("【开运算后】",midImg2);
	cout<<"midImg1.channel="<<midImg1.channels()<<endl;
	cout<<"mdiImg1.depth"<<midImg1.depth()<<endl;
	//查找图像轮廓
	Mat midImg3=Mat::zeros(midImg2.rows,midImg2.cols,CV_8UC3);
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(midImg2,contours,hierarchy,RETR_CCOMP,CHAIN_APPROX_SIMPLE);
	int index=0;
	for(;index>=0;index=hierarchy[index][0])
	{
		Scalar color(255,255,255);
		drawContours(midImg3,contours,index,color,NULL,8,hierarchy);
	}
	namedWindow("【轮廓图】",WINDOW_NORMAL);
	imshow("【轮廓图】",midImg3);
	Mat midImg4=midImg3.clone();
	//创建包围轮廓的矩形边界
	for(int i=0;i<contours.size();i++)
	{
		//每个轮廓
		vector<Point> points=contours[i];
		//对给定的2D点集,寻找最小面积的包围矩形
		RotatedRect box=minAreaRect(Mat(points));
		Point2f vertex[4];
		box.points(vertex);
		//绘制出最小面积的包围矩形
		line(xianshi,vertex[0],vertex[1],Scalar(100,200,211),6,LINE_AA);
		line(xianshi,vertex[1],vertex[2],Scalar(100,200,211),6,LINE_AA);
		line(xianshi,vertex[2],vertex[3],Scalar(100,200,211),6,LINE_AA);
		line(xianshi,vertex[3],vertex[0],Scalar(100,200,211),6,LINE_AA);
		//绘制中心的光标
		Point s1,l,r,u,d;
		s1.x=(vertex[0].x+vertex[2].x)/2.0;
		s1.y=(vertex[0].y+vertex[2].y)/2.0;
		l.x=s1.x-10;
		l.y=s1.y;

		r.x=s1.x+10;
		r.y=s1.y;

		u.x=s1.x;
		u.y=s1.y-10;

		d.x=s1.x;
		d.y=s1.y+10;
		line(xianshi,l,r,Scalar(100,200,211),2,LINE_AA);
		line(xianshi,u,d,Scalar(100,200,211),2,LINE_AA);
	}
	namedWindow("【绘制的最小面积矩形】",WINDOW_NORMAL);
	imshow("【绘制的最小面积矩形】",xianshi);
	waitKey(0);
	return 0;
}


### 回答1: VC是Visual C++(可视化C++)的简写。它是一款由微软公司开发的面向对象的编程语言,VC开发环境中包含了许多微软提供的工具,例如对话框设计器、资源编辑器、集成编译器和链接器等。VC对于图形图像处理方面的应用十分强大,特别是在opencv物体追踪方面。 OpenCV是一个基于BSD许可(开放源代码)发行的跨平台计算机视觉和机器学习软件库。它由一系列的计算机视觉和机器学习算法库组成。利用 OpenCV,我们可以实现一些常用的计算机视觉应用,例如图像或视频的处理、特征的提取和匹配、目标检测与跟踪等等。其中物体追踪是十分实用和广泛使用的应用之一。 利用VC编程可以很容易的调用OpenCV的接口,从而实现物体追踪功能。通常来说,物体追踪包含两个步骤:目标检测和目标跟踪。目标检测用于寻找目标物体,例如在视频序列中寻找特定物体的位置,多采用特征提取和机器学习算法。然后在目标检测的基础上进行目标跟踪,即在不同帧之间跟踪目标的运动轨迹,常见的跟踪算法包括卡尔曼滤波算法、粒子滤波算法等。 可以使用VC+OpenCV进行物体追踪的应用开发,不仅实现了在图像和视频中实时定位和跟踪目标的功能,也为物体识别、自动驾驶、区域监控等提供了强大的技术支持。 ### 回答2: VC和OpenCV物体追踪是一种基于视觉的技术,可以实现实时跟踪目标对象的位置和运动轨迹。VC是Visual C++的简称,是一种编程语言和开发环境,可以集成OpenCV库进行图像处理和计算机视觉应用的开发。OpenCVOpen Source Computer Vision的缩写,是一款跨平台的计算机视觉库,提供了丰富的图像处理、分析和识别算法。 物体追踪是计算机视觉中的一个重要研究领域,是指在视频流中自动监测和跟踪目标物体,识别物体的运动,并输出目标物体的位置和轨迹。VC和OpenCV物体追踪主要包括目标检测、特征提取、跟踪算法和运动模型等步骤。其中,目标检测是对视频流中的每一帧图像进行图像分割和目标区域提取,特征提取是提取目标物体的颜色、纹理、边缘等特征信息,跟踪算法是基于目标物体的特征信息计算目标物体的位置和速度,运动模型是根据先前的目标位置和速度预测下一时刻目标物体的位置。 VC和OpenCV物体追踪在实际的应用中,可以用于自动驾驶、安防监控、人脸跟踪、AR游戏等领域,实现了对目标物体的精准跟踪和监测,为计算机视觉的发展提供了重要的技术支撑。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值