OpenCV单目视觉定位(测量)系统(新增 含代码)

2023-05-16

OpenCV单目视觉定位(测量)系统

The System of Vision Location with Signal Camera



Abstract:This passage mainly describes how to locate with signalcamera,which bases on OpenCV library.

Key words: OpenCV; Locate;Signalcamera

摘  要:本文主要描述的是利用开源计算机视觉库OpenCV实现单目视觉定位系统。

关键词: OpenCV;单位视觉定位

1     总体设计方案

单目视觉定位系统是通过单个分辨率为640*480,20万的USB手动调焦摄像头获取图片并传到计算机利用OpenCV进行预处理、识别、定位、测量等图像处理算法,进而得出目标物体相对摄像头的二维坐标距离。

2     预处理

对摄像头获取的图片进行均值滤波处理,目的是抑制电气元件或者环境因素引起的噪声。滤波也叫平滑处理,滤波的目的是抑制噪声,平滑滤波属于低频增强空间滤波技术,因为图像的能量大部分集中在幅度谱的低中频,噪声一般存在于高频段。

在本系统中主要采用均值滤波算法,也叫邻域平均算法。领域平均算法的基本思想是对含噪声图像的每一个像素点f(x,y)取领域S,用领域S中所包含的像素灰度平均值来代替该点的灰度值。

领域平均法的优点是处理方法简计算速度快,缺点是在降低噪声的同时是图像产生一定程度的模糊,领域半径越大,去噪效果越好,但图像越模糊。

因此,本系统采用3 X 3模板h,其转置矩阵为:1/9 [1,1,1 ; 1,1,1 ; 1,1,1],设f(x,y)为原图像的每一个像素值,g(x,y)为输出图像对应的每一个像素值,则均值滤波核心算法为原图像的每一个像素(除图像边缘像素)和3 X 3模板h进行卷积运算得出输出图像。

 图一 灰度图                 


图二 均值滤波                           


3     识别

对于目标物体的识别,本系统是采用Canny边缘检测找出所有可能的边缘信息,然后对边缘信息进行提取和分析,进而识别出目标物体。与该目标物体的识别还有一种方法是采用阈值算法分割出特定灰度值范围内的物体,但该算法受光照影响较大,而边缘检测受光照影响较少,因此Canny采用边缘检测算法。

3.1目标物体

对目标物体的设计,我采用了外面六边形,里面五边形,六边形与五边形之间黑色填充,其余白色填充,六边形与五边形中心基本上一致。如下图所示


 图三打印的目标物体

 

 3.2 Canny边缘检测

边缘检测的算法只要是基于图像增强的一阶和二阶导数。Canny边缘检测算子是JohnF.Canny于1986年开发出来的一个多级边缘检测算法。Canny的目标是找到一个最优的边缘检测算法。其具有的优点是:

l  低错误性:标识出尽可能多的实际边缘,同时尽可能地减少噪声产生的误报。

l  高定位性:标识出的边缘要与图像中的实际边缘尽可能接近

l  最小效应:图像中的边缘只能标识一次,并且可能存在的图像噪声不应标识为边缘

其步骤是,首先使用高斯平滑滤波器卷积降噪,计算梯度幅值和方向,然后进行非极大值抑制,排除非边缘像素,仅仅保留了一些细线条,最后滞后阈值。

对上面经过均值滤波的灰度图进行Canny边缘检测。


 图四 边缘检测图

 

3.3 轮廓分析

对上面的Canny边缘检测得出的信息运用OpenCV提供的findContours函数边缘信息转化为轮廓信息,最后再对轮廓进行分析处理,找出目标物体。

 

图五 轮廓图

轮廓分析算法:遍历所有轮廓,排除凹轮廓和轮廓面积小于100像素的轮廓,找出轮廓为逼近六边形和逼近五边形的所有轮廓,找出这些逼近六边形和逼近五边形轮廓的最小外接矩形,并各提取最小外接矩形的中心(即逼近六边形和逼近五边形轮廓中心),若逼近六边形轮廓的最小外接矩形和逼近五边形轮廓的最小外接矩形中心基本在同一点(考虑畸变原因,中心点不一定一致),则为目标物体。

3       定位

本系统是采用640*480分辨率,20万像素的手动调焦的USB摄像头进行实验的,该摄像头广角较低,畸变不厉害。

定位功能得出的坐标是相对于自定义的图像坐标原点,在该系统中,定义的原点就是图像中心(320,240)单位为像素。因此,在摄像头水平放置的情况下,自定义图像原点即为二维空间上的摄像头正下方。

定位的基本思想是利用已知目标物体的长度和求出的目标物体的像素长度,得出像素的尺寸,再利用像素尺寸和目标物体在自定义原点的X,Y方向的像素距离,进而求出目标物体相对水平放置的摄像头的X,Y方向实际距离。

实验结果,本实验是摄像头距目标物体正上方大约50cm上进行测量的,摄像头为水平放置。经过多次测量,测出距离与实际距离误差基本上维持在1cm到2cm之间。如下图所示:(红色点为自定义的图象原点,左上方的Target_X,Target_Y分别为系统测出的目标距原点(摄像头正下方)的X和Y方向的测出距离。图像上的白色坐标系为实际理论距离。

 

图六 实验结果图

 


                                                                               图、实验情况

1     结束语

该测量系统只在短范围内测量,实验还存在误差。因为该摄像头本身畸变不大,没有进行标定,矫正等一系列处理,实验数据还能接受,但对于广角大、畸变大的摄像头,本系统根本无法适用。还有的是,本系统还没有进行相机姿态估计,因此,对于摄像头与水平面有一定角度时,误差会大大增加。

在接下来的时间里,作者会尽量完善该系统,争取能用于无人机以及机器人的单目视觉定位系统。

本文难免有错漏,欢迎大家指出,本人联系方式:821992904@qq.com。


核心代码:

//定位函数
void Location(){

	//均值滤波
	blur(gray, gray_blur, Size(3, 3));

	//边缘检测提取边缘信息
	Canny(gray_blur, dstThreshold, 150, 450);
	imshow("canny边缘检测", dstThreshold);
	
	//对边缘图像提取轮廓信息
    vector<vector<Point> >contours;
	findContours(dstThreshold, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
	
	//画出轮廓
	drawContours(contours_image, contours, -1, Scalar(0, 0, 255));
	imshow("contours", contours_image);

	//画出定义的原点
	circle(src, Point2f(oriX, oriY), 2, Scalar(0, 0, 255), 3);

	//定义分别逼近六边形和五边形的轮廓
	vector< vector<Point> > Contour1_Ok, Contour2_Ok;

	//轮廓分析
	vector<Point> approx;
	for (int i = 0; i < contours.size(); i++){
		approxPolyDP(Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.04, true);

		//去除 小轮廓,只提取凸轮廓
		if (std::fabs(cv::contourArea(contours[i])) < 600 || !cv::isContourConvex(approx))
			continue;

	    //保存逼近六边形的轮廓 到 Contour1_Ok
		 if (approx.size() == 6){
			Contour1_Ok.push_back(contours[i]);
		}
	    //保存逼近五边形的轮廓 到 Contour2_Ok
		 else if (approx.size() == 5){
			 Contour2_Ok.push_back(contours[i]);
		}

	}

	//对所有符合要求的六边形,五边形轮廓进行分析
	//识别出自定义的物体的关键是:
	//1.六边形和五边形轮廓的最小外接矩形的中心基本在同一点
	//2.六边形轮廓的最小外接矩形的任一边长大于五边形轮廓的最小外接矩形的任一边长
	for (int i = 0; i < Contour1_Ok.size(); i++){
		for (int j = 0; j < Contour2_Ok.size(); j++){
			RotatedRect minRect1 = minAreaRect(Mat(Contour1_Ok[i]));  //六边形轮廓的最小外接矩形
			RotatedRect minRect2 = minAreaRect(Mat(Contour2_Ok[j]));  //五边形轮廓的最小外界矩形
			//找出符合要求的轮廓的最小外接矩形
			if ( fabs(minRect1.center.x - minRect2.center.x) < 30 && fabs(minRect1.center.y - minRect2.center.y)<30 && minRect1.size.width > minRect2.size.width){
				Point2f vtx[4];
				minRect1.points(vtx);
				
				//画出找到的物体的最小外接矩形
				for (int j = 0; j < 4; j++)
					line(src, vtx[j], vtx[(j + 1) % 4], Scalar(0, 0, 255), 2, LINE_AA);

				//画出目标物中心到图像原点的直线
				line(src, minRect1.center, Point2f(oriX, oriY), Scalar(0, 255, 0), 1, LINE_AA);

				//目标物距图像原点的X,Y方向的像素距离
				targetImage_X = minRect1.center.x - oriX;
				targetImage_Y = oriY - minRect1.center.y;

				line(src, minRect1.center, Point2f(minRect1.center.x, oriY), Scalar(255, 0, 0), 1, LINE_AA);
				line(src, Point2f(oriX, oriY), Point2f(minRect1.center.x, oriY), Scalar(255, 0, 0), 1, LINE_AA);

                Point2f pointX((oriX + minRect1.center.x) / 2, oriY);
				Point2f pointY(minRect1.center.x, (oriY + minRect1.center.y) / 2);  
		
		        //找出最大边
				float a = minRect1.size.height, b = minRect1.size.width;
				if (a < b) a = b;
				
				mm_per_pixel = targetLength / a;               //计算像素尺寸 = 目标物的实际长度(cm)/ 目标物在图像上的像素长度(pixels)
				targetActualX = mm_per_pixel *targetImage_X;   //计算实际距离X(cm)
				targetActualY = mm_per_pixel *targetImage_Y;   //计算实际距离Y(cm)

				//打印信息在图片上
				String text1 = "X:"+format("%f", targetImage_X);
				String text2 = "Y:"+format("%f", targetImage_Y);
				putText(src, text1, pointX, FONT_HERSHEY_SIMPLEX, 0.4, Scalar(0, 0, 255), 1, 8);
				putText(src, text2, pointY, FONT_HERSHEY_SIMPLEX, 0.4, Scalar(0, 0, 255), 1, 8);

				String text3 = "Target_X:"+format("%f", targetActualX);
				String text4 = "Target_Y:"+format("%f", targetActualY);
				putText(src, text3, Point(10,30), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 0, 255), 1, 8);
				putText(src, text4, Point(10,60), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 0, 255), 1, 8);

				
			}
			break;
		}       
        break;
	}

	imshow("SRC", src);

}

完整代码

http://download.csdn.net/download/chenmohousuiyue/9947409
点击打开链接



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV单目视觉定位(测量)系统(新增 含代码) 的相关文章

  • Nuttx驱动(一)简介

    第一次写Nuttx系统的驱动 xff0c 用惯了rt thread FreeRTOS等RTOS或裸机的驱动编写 写Nuttx驱动感觉好蹩脚 xff0c 顺便记录一下 xff08 by the way 先完成 xff0c 再完善 xff09
  • Nuttx驱动(二)实例

    接上一篇文章 xff0c 这篇主要是nuttx驱动编写实践部分 基础部分请移驾 Nuttx驱动 xff08 一 xff09 简介 Nuttx驱动例程 在该例程中 xff0c 假设有这么一个设备 xff1a 有3个IO输出和一个IO输入的RG
  • 【转】CAN总线学习笔记(1)- CAN基础知识

    依照瑞萨公司的 CAN入门书 的组织思路来学习CAN通信的相关知识 xff0c 并结合网上相关资料以及学习过程中的领悟整理成笔记 好记性不如烂笔头 xff0c 加油 xff01 1 CAN的一些基本概念 1 1 什么是CAN总线 CAN 是
  • git如何找回本地被覆盖的代码

    1 方法1 git reflog 查看提交记录 xff0c 找到对应的commitId git reset hard 版本号 就回到当时的那个版本 xff08 git reset hard HEAD 64 n xff09 2 git pul
  • PID入门及无人机实战

    一 PID的理论知识 大家可以搜索 PID控制算法的C语言实现 绝对的好东西 很好的入门材料 下图就是从上面摘下来的PID控制流程图 二 利用温控讲解单环PID 我们可以在电路板上焊几个电阻进行加热 xff08 PWM控制加热速度 xff0
  • 无人机姿态解算_互补滤波(1)

    一 基础知识 1 坐标系 xff1a 遵循右手定则 1 1 大地坐标系 xff08 地球坐标系 xff09 xff1a 北 xff08 x轴 xff09 东 xff08 y轴 xff09 地 xff08 z轴 xff09 xff0c 地就是
  • C++从入门到进阶的系列书籍推荐

    目录 1 C 43 43 入门书籍 1 1 C语言程序设计 xff08 谭浩强 xff09 1 2 C 43 43 Primer中文版 xff08 第5版 xff09 2 VC 43 43 MFC书籍 2 1 VC 43 43 深入详解 x
  • 无人机姿态解算_扩展卡尔曼滤波(2)

    一 扩展卡尔曼滤波 KF和EKF的公式对比 xff08 基本没差别 xff09 二 扩展卡尔曼五个公式 利用扩展卡尔曼滤波估计四元数 下图是论文中的截图 可以和前面的卡尔曼滤波估计高度文章的那五个公式对应一下 观测矩阵的确定 三 代码的实现
  • 无人机高度估计_卡尔曼滤波

    一 卡尔曼滤波公式 线性系统的离散状态空间表达式 xff1a 这是卡尔曼五个标准公式的基础 式叫做系统状态方程 xff1a xk k时刻系统状态变量值 Ak 状态转移矩阵 Bk 控制矩阵 uk 1 k 1时刻系统的输入 wk 1 k 1时刻
  • 日常记录4_pixhawk电流计的使用

    1 实物图以及连接 注意事项 接电流计的时候 xff0c 先别给电流计通电 xff0c 要先接负载 xff08 即接到飞机那一端 xff09 再给电流计供电 xff0c 不然空载的时候 xff0c 电池给电流计的电流会很大 xff0c 导致
  • Android中的ListView

    文章目录 1 ListView概述2 适配器2 1 ArrayAdapter2 2 SimpleAdapter2 3 BaseAdapter 1 ListView概述 下面看一下ListView的应用场景 xff1a 2 适配器 先看下适配
  • Android中的ViewPager2

    文章目录 1 ViewPager2简介1 1 ViewPager2应用场合1 2 ViewPager2应用背景 2 应用案例2 1 图片轮播2 2 导航 1 ViewPager2简介 1 1 ViewPager2应用场合 ViewPager
  • Qt界面语言国际化

    文章目录 1 Qt界面语言国际化1 1 操作步骤 1 Qt界面语言国际化 1 1 操作步骤 操作步骤如下 xff1a 生成TS文件 xff08 LUPDATE xff09 编辑TS文件 xff08 LINGUIST xff09 发布TS文件
  • Qt工程pro文件配置详解

    文章目录 1 pro文件常用配置1 1 注释1 2 CONFIG1 3 DEFINES1 4 FORMS1 5 HEADERS1 6 INCLUDEPATH1 7 LIBS1 8 QT1 9 SOURCES1 10 TRANSLATIONS
  • Qt配置GUI程序控制台输出

    文章目录 1 Qt配置GUI程序控制台输出 1 Qt配置GUI程序控制台输出 下面看一下如何控制GUI程序控制台输出 xff1a 在 在 pro 文件中添加 xff1a CONFIG 43 61 console 选择 xff1a 项目 gt
  • 列表框QListWidget 类

    文章目录 1 QListWidget 简介2 QListWidget 常用操作2 1 添加操作2 2 删除操作 1 QListWidget 简介 Qt 提供 QListWidget 类列表框控件用来加载并显示多个列表项 QListWidge
  • Qt中的QSpinBox

    文章目录 1 QSpinBox1 1 QSpinBox 简介1 2 QSpinBox的主要属性 1 QSpinBox 1 1 QSpinBox 简介 QSpinBox 类提供了一个微调框部件 QSpinBox 允许用户选择一个值 xff0c
  • C/C++面试题1

    目录 1 C 面向对象的三大特性是什么 谈谈你对这三大特性的认识 2 include 和 include filename
  • QCheckBox

    文章目录 1 QCheckBox1 1 QCheckBox简介 1 QCheckBox 1 1 QCheckBox简介 QCheckBox 继承自 QAbstractButton xff0c 它提供了一个带文本标签的复选框 QCheckBo
  • QSlider

    文章目录 1 QSlider1 1 QSlider 简介 1 QSlider 1 1 QSlider 简介 QSlider 部件提供了一个垂直或水平滑动条 滑块是一个用于控制有界值的典型部件 它允许用户沿水平或垂直方向移动滑块 xff0c

随机推荐

  • QComboBox

    文章目录 1 QComboBox1 1 QComBox简介 1 QComboBox 1 1 QComBox简介 QComboBox 是下拉列表框组件类 xff0c 它提供一个下拉列表供用户选择 xff0c 也可以直接当作一个 QLineEd
  • QTreeWidget

    文章目录 1 QTreeWidget1 1 QTreeWidget简介 1 QTreeWidget 1 1 QTreeWidget简介 在 Qt 中的树形控件称为 QTreeWidget xff0c 而控件里的树形节点称为 QTreeWid
  • QMouseEvent

    文章目录 1 QMouseEvent1 1 特别说明 2 通过QMouseEvent事件实现窗口移动 1 QMouseEvent 1 1 特别说明 QMouseEvent没啥要注意的 xff0c 就是对于mouseMoveEvent xff
  • 1.基础概念【七天物联网智能家居训练营】

    本文是百问网七天物联网智能家居训练营学习笔记 xff0c 官网链接 1 ARM 我们经常听所ARM xff0c 其实ARM有两种含义 xff1a ARM是一家公司 xff0c ARM也是一种处理器架构 RISC是精简指令集 xff0c 旨在
  • 2.单片机开发模式【七天物联网智能家居训练营】

    本文是百问网七天物联网智能家居训练营学习笔记 xff0c 官网链接 1 单片机上手思路 对于一款新单片机 xff0c 我们可以采取如下思路进行上手 xff1a 去芯片原厂官网 xff0c 下载资料 xff0c 主要是获取数据手册和参考手册
  • 3.时钟与GPIO【七天物联网智能家居训练营】

    本文是百问网七天物联网智能家居训练营学习笔记 xff0c 官网链接 1 时钟系统 首先我们要知道时钟的主要作用是用来同步 xff0c 现代的计算机系统是必然有时钟的 并且 xff0c 对于高级的单片机系统 xff0c 还会存在着不同频率的时
  • 4.中断与串口【七天物联网智能家居训练营】

    本文是百问网七天物联网智能家居训练营学习笔记 xff0c 官网链接 1 中断 我们先来看一下什么是中断 xff1a 其实这种就是前后台的程序设计模式 我们来看下CM3内核都有哪些中断 xff0c 如下表 xff1a 对于CM3内核的单片来说
  • APT Hash sum mismatch错误的常见解决方法总结

    APT Hash sum mismatch错误的常见解决方法总结 LINUX报这个错误的时候 xff0c 有很多的原因 xff0c 通常是出现在使用apt get update的时候 xff0c apt 的全称是Advanced Packa
  • 安装Nvidia驱动run文件

    本文系转载 xff0c 出处 xff1a https blog csdn net lhx 998 article details 76135936 下载指定NVIDIA驱动安装包 xff08 run格式 xff09 run格式文件安装有时比
  • 5.AT指令【七天物联网智能家居训练营】

    本文是百问网七天物联网智能家居训练营学习笔记 xff0c 官网链接 1 ESP8266 本文要使用的wifi模块为ESP8266 xff0c 我们直接使用官方提供的固件即可 xff0c 无须单独开发 直接通过串口和wifi模块进行通信 xf
  • 6.编写初步程序【七天物联网智能家居训练营】

    本文是百问网七天物联网智能家居训练营学习笔记 xff0c 官网链接 1 程序流程回顾 先来回顾下TCP连接的流程 xff1a 下面看下UDP连接的流程 xff1a 整个程序的框架如下 xff1a 2 代码实现 这里我们使用串口2来操作 xf
  • 7.进一步完善程序【七天物联网智能家居训练营】

    本文是百问网七天物联网智能家居训练营学习笔记 xff0c 官网链接 1 增加UDP发送函数 再来回顾下UDP发送的流程 xff1a 对于AT指令来说 xff0c 只是使用的具体指令不同而已 和TCP发送函数非常类似 xff0c 代码如下 x
  • ubuntu16 PL-SLAM编译 踩坑

    首先贴出pl slam readme的第一句话 xff1a 对pl slam的精度不要有太高要求 Notice that this repository is only an open source version of PL SLAM r
  • ROS kinetic 运行s_msckf和 vins_fusion

    s msckf xff1a 采用多状态约束的双目vio系统 注意 imuCallback xff1a 接收IMU数据 xff0c 将IMU数据存到imu msg buffer中 xff0c 这里只会利用开头200帧IMU数据进行静止初始化
  • 服务器查看配额限制: OSError: [Errno 122] Disk quota exceeded

    OSError Errno 122 Disk quota exceeded 是因为磁盘配额不够了 xff0c 即磁盘已满或超出了用户所能使用的配额上限 可以通过如下命令查看配额限制和已经使用的配额 xff1a quota uvs usern
  • colmap 已知pose 重建 kitti数据尝试

    Frequently Asked Questions COLMAP 3 7 documentation COLMAP已知相机内外参数重建稀疏 稠密模型 thronsbird 博客园 Colmap根据相机内外参数重建稀疏模型 m0 47677
  • Umap与 t-sne可视化CNN特征

    考虑到umap 比 t sne快 xff0c 而且全局结构更好 demo网站 Understanding UMAP doc xff1a https github com lmcinnes umap How to Use UMAP umap
  • nn.AdaptiveAvgPool2d() 与 nn.AvgPool2d() 模块的区别

    nn AdaptiveAvgPool2d 与 nn AvgPool2d 模块的区别 jinfeng2411的博客 CSDN博客 nn adaptiveavgpool
  • dataloader卡住

    pin memory 知乎 dataloader卡住 xff01 xff01 xff01 只会git clone的程序员的博客 CSDN博客 dataloader 卡死 PyTorch 训练时中遇到的卡住停住等问题 yyywxk的博客 CS
  • OpenCV单目视觉定位(测量)系统(新增 含代码)

    OpenCV单目视觉定位 xff08 测量 xff09 系统 The System of Vision Location with Signal Camera Abstract This passage mainly describes h