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单目视觉定位实现方法 的相关文章

  • 使用Houdini输出四面体网格并输出tetgen格式

    我们的目标是从houdini输出生成的四面体 xff0c 希望是tetgen格式的 众所周知 xff0c houdini是不能直接输出四面体的 有三方案去解决 xff1a 输出点云ply文件 xff0c 然后利用tetgen生成网格 输出H
  • Everything about PBD:关于PBD的一切!

    参考资料汇总 我的笔记 PBD初探 https blog csdn net weixin 43940314 article details 126065813 XPBD 文献笔记 https blog csdn net weixin 439
  • taichi windows编译 build from source

    先编译 env span class token punctuation span PY span class token operator 61 span span class token string 34 3 10 34 span e
  • Neohooken PBD 文献笔记

    Neohooken的本构模型为 定义能量密度为cosntraint的函数 能量密度的负梯度就是力 以上的能量密度分为CH与CD两项 CH就是净水应力造成的弹性力 CD就是应力偏量造成的弹性力 H stands for Hydrostatic
  • houdini vex 查找最近点的距离

    i span class token punctuation span span class token punctuation span 64 nears span class token operator 61 span span cl
  • OpenFOAM后处理,paraview创建动画视频的三种方式

    首先在 paraView中保存图片序列 点击file gt save Animation xff0c 可以保存为tif png jpg等格式的图片序列 可以规定保存的帧数 xff0c 默认是每个timestep一帧 注 xff1a 图片很多
  • 总结入门学习OpenFOAM的资料(网址、论坛、帖子、博客等)

    为了自己记录学习OpenFOAM的过程 xff0c 把收藏夹里面的网页整理一下 来源 首先 xff0c 大部分资料来源自 放羊君的博客 里面有很多入门建议 xff0c 网址等等 有入门者应该进行的步骤等等 正文 1 官方文档 xff08 O
  • ONOS简介

    一 与ODL区别 ONOS与OpenDayLight 两个控制器之间的较量 ODL 立场 xff1a 设备厂商 xff1a Cisco Citrix Systems Red Hat Brocade Ericsson ClearPath HP
  • centos7中mysql的安装配置

    1 在命令行输入以下命令下载 rpm的安装包 执行以下命令下载rpm的安装包 cd usr local src wget https dev mysql com get mysql80 community release el7 1 noa
  • onos1.10安装 Ubuntu18 java1.8

    版本1 10 tar包安装 xff0c java8 onos2 2以上需要jdk11 1 10是apache karaf 3 0 8 xff0c karaf直接进入ONOS xff0c 2 0以上版本启动均产生ERROR不知为何 xff08
  • prometheus数据持久化 docker部署

    https segmentfault com a 1190000015710814 prometheus修改配置不需要停掉 xff0c 只要修改yml之后用docker restart重启 prometheus存储方式 prometheus
  • 什么是私有云?私有云有哪些优势和劣势?

    私有云也是云计算的一种 xff0c 它具有云计算的通用优势 xff0c 主要包括超强的扩展性和自助服务 我们通常讲的云服务器和云主机 xff0c 一般指的公有云 xff0c 私有云相比公有云价格较高 xff0c 一般大中型企业的首选 xff
  • BigDecimal类型 比较大小的方法

    1 转成int BigDecimal b1 61 new BigDecimal 34 121454125453 145 34 if b1 intValue lt 0 System out println 34 金额为负数 xff01 34
  • Git报错解决:OpenSSL SSL_read: Connection was reset, errno 10054 错误解决

    首先 xff0c 造成这个错误很有可能是网络不稳定 xff0c 连接超时导致的 xff0c 如果再次尝试后依然报错 xff0c 可以执行下面的命令 打开Git命令页面 xff0c 执行git命令脚本 xff1a 修改设置 xff0c 解除s
  • java小知识:http请求传输文件流

    前文 xff1a 项目里要给第三方传输图片 xff0c 对方接口要求传文件流 xff0c 而不是常用的base64编码 xff0c 在此记录一下 xff5e 直接贴代码吧 xff1a import com alibaba fastjson
  • SSH无法启动错误解决:Failed to start OpenSSH server daemon.

    一 错误信息如下 xff1a sshd service OpenSSH server daemon Loaded loaded usr lib systemd system sshd service enabled vendor prese
  • linux小知识:修改/etc/profile全局变量文件出错,导致服务命令全部失效解决方案

    现象 xff1a 由于修改profile文件时改错了 xff0c 导致所有的命令都失效了 赶紧解决赶紧解决 1 在当前窗口执行以下命令 export PATH 61 usr local sbin usr local bin sbin bin
  • docker容器如何迁移

    docker容器如何迁移 xff1f 前言 xff1a 迁移容器涉及到备份和恢复 xff0c 可以将任何一个docker容器从一台机器迁移到另一台机器 在迁移过程中 xff0c 首先将把容器备份为Docker镜像快照 然后 xff0c 该D
  • 缓存IO和直接IO的区别

    1 缓存IO 缓存I O又被称作标准I O xff0c 大多数文件系统的默认I O操作都是缓存I O 在Linux的缓存I O机制中 xff0c 数据先从磁盘复制到内核空间的缓冲区 xff0c 然后从内核空间缓冲区复制到应用程序的地址空间
  • 修改svn的配置文件并对密码加密

    svn管理 公司项目进出新人 xff0c 需要对代码管理工具进行增删 由于对linux不是很了解 对svn的配置有没有进行过交接 所有的操作都是自己在centos服务器上进行尝试 对于普通的svn的账号密码管理有了基本了解 但是在服务器上看

随机推荐

  • deepin安装微信qq

    在网页上下载最新微信或者qq env WINEPREFIX 61 deepinwine Deepin WeChat deepin wine WeChatSetup exe 该命令运行在WeChatSetup exe所在文件夹 xff0c 最
  • 在Java中,执行SQL查询到数据后,存储在哪里了?

    前言 xff1a 我们项目运行过程中 xff0c 肯定会有查询数据库这步操作 xff0c 无论你是MySQL还是Oracle 那么这种情况就必须搞清楚 xff0c 从数据库里查询得到的数据默认存储到哪了 xff0c 为什么一次查询过多的数据
  • Java小知识:摆脱BeanUtil.copyProperties!! 最优的替代方案 -Bean Converter插件使用方式来了~

    前言 xff1a 开发中为什么不推荐使用BeanUtil copyProperties xff1f 使用BeanUtil copyProperties会有哪些严重后果 xff1f 这些就不在这里眼神了哈 xff0c 大家可以自行查阅一下即可
  • Vue小知识: $ is not defined错误解决

    错误原因 xff1a 该错误是未安装JQuery依赖包导致 解决方案 xff1a 安装依赖包 1 执行安装jquery依赖包命令 cnpm install jquery save 2 webpack配置 xff08 1 xff09 在项目根
  • JVM小知识:linux 命令查看jvm堆内存信息

    1 查看当前java进程的pid pgrep lf java 2 查看java堆的详细信息 jmap heap PID 3 查看java堆中对象的相关信息 xff0c 包含数量以及占用的空间大小 jmap histo PID 4 查看监控
  • IDEA小知识:查看内存使用情况的步骤

    1 展示idea自带的内存指标 xff0c 如图 1 图 2 点击File gt 选择Setting gt 进入APPearance gt 勾选Show memory indicator 图 xff08 1 xff09 图 xff08 2
  • 【无标题】

    CMake Error at xxaipkg CMakeLists txt 50 add message files Unknown CMake command add message files Configuring incomplet
  • npm安装淘宝镜像报错

    npm install g cnpm registry 61 https registry npm taobao org 执行命令报错 无法安装cnpm 解决方案 xff1a 用管理员方式打开命令行 xff0c 就可以安装成功了
  • Leetcode——贪心算法(c++和java实现)

    本来有一段时间没有刷题了 xff0c 但是突然发现了这本书LeetCode 101 A LeetCode Grinding Guide C 43 43 Version xff0c 感觉真不错 xff0c 思路简单清晰 xff0c 没有过多的
  • 树莓派3B+安装c++版本opencv3.4.1,配置开发环境以及注意事项

    树莓派3B 43 安装c 43 43 版本opencv3 4 1 xff0c 配置开发环境以及注意事项 树莓派3B 43 ubuntu mate系统的安装 树莓派 xff0c Raspberry Pi xff0c 是一个只有信用卡大小的微型
  • 由frankmocap得到的.pkl文件转为.bvh或者.fbx

    需求 由Frankmocap所得到的 pkl文件转为blender里的 bvh或者Maya里的 fbx Frankmocap github项目地址 2D转3D转 bvh可以看VideoTo3dPoseAndBvh xff0c bvh转3D相
  • centos 安装docker

    查看系统内核版本 docker需要内核版本在3 8以上 centos7 版本是3 10 安装支持aufs CentOS7 默认不支持aufs文件系统 需要自己安装支持aufs的内核 进入repo目录 cd etc yum repo d 下载
  • echarts框架下大数据量展示的解决方案

    echarts 43 大数据量 这是个无解的问题 xff01 大数据量 xff0c 什么样的数据才算大呢 xff1f 在echart 4 5 0版本中 xff0c 画折线图 xff0c 数据线一共1001000条 xff0c 每条数据500
  • Open vSwitch介绍

    Open vSwitch介绍 1 vSwitch功能2 OvS架构3 OvS报文处理3 1 传统OvS方式3 2 OvS 43 DPDK处理方式 4 OvS补充说明4 1 基本概念4 2 匹配项与规则4 2 1 匹配项4 2 2 动作 本节
  • Python写ROS话题

    Python写ROS话题 导入ROS模块发送话题接收话题第一种方式 xff1a rospy Subscriber第二种方式 xff1a rospy wait for message完整程序 多线程处理同时接受多个话题 导入ROS模块 用py
  • Python写ROS程序常用数据结构std_msgs、geometry_msgs、sensor_msgs

    Python写ROS程序常用数据结构 std msgsFloat64MultiArray geometry msgsVector3TwistWrenchPointQuaternionPosePose2D Stamped sensor msg
  • ROS中gazebo配置教程详解

    ROS中gazebo配置教程详解 机器人模型文件获取原始URDF模型文件采用xacro格式改写文件增加gazebo插件描述增加传动transmission最后将上面三个文件合成一个文件 环境XX world文件配置文件 yaml启动文件la
  • gazebo添加末端六维力传感器

    gazebo添加末端六维力传感器 建立六维力矩传感器模型将传感器拼接到机器人模型配置传感器gazebo参数 常用的机器人只支持位置控制 xff0c 但实际运用中 xff0c 却对末端力控制有迫切的需求 xff0c 其中一种常用的方法是基于位
  • gazebo .world文件中导入dae模型的问题

    gazebo world文件中导入dae模型的问题 gazebo环境提供了很多可以直接导入的模型 xff0c 如果想往环境中导入自己的静态模型 xff0c 需将自己的模型转化为dae格式 xff0c 并编写相应的 world文件 准备好da
  • OpenCV单目视觉定位实现方法

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