摄像头组很稳定的黑线提取算法

合集下载

基于摄像头的智能车黑色虚线识别算法研究

基于摄像头的智能车黑色虚线识别算法研究

黑色 实线 。x s 1 2 8 ( 飞 思 卡 尔 的芯 片 ) 片 内的 r a n是 8 K, 为减少 r a n的使用 效 率 , 应 尽 量 减小 图像 矩 阵 。 本文 中使 用 6 4 8 4的图像 矩阵 。具体 操作 : 步骤 1 : 从 离摄 像 头 开 始 选 取 1 2行 , 采 用 边 缘
), 求 出这两 点构 成 直 线 的斜 率 和 直 线 方 程 , 即
变的越厉害, 那么就把采集 到的赛道 图像分成几部 分处理 。本文将 图像分 4段采集 , 以远处 的图像小 近处图像大的特点使用远密进疏的原则 , 前2 0 行每
可算 出虚线行 的横坐标 , 来补足虚线 。
收稿 日期 : 2 0 1 3—0 6—2 6
组成 , 综 合 考虑 3种 方案 的特 点 , 本 文采 用 的 下 , 在 实 时 的 图像 数 据 获
取的基础上对图像信息进行数据处理 , 从而提取赛 道 中心 的黑 色 指 引虚 线 , 以此 来 作 为 舵 机 和 驱 动 电 机的控制依据。以往 的赛 道 中的黑色指 引线是实
1 摄像头采样数据 的特点
本 文采用 的数 字摄 像 头 的型号 为 0 V 7 6 2 0 , 将摄
像头固定在车体 的中间, 前 瞻性约 1 i n 。要 想采集 的图像准确 , 必须要了解摄像头的时序, 摄像头 的时
序 图如 图 1 所示。
求, 根据赛道特点 , 主要有 3 种 寻线设计方案 : 光电 传感器方案 、 摄像头方案和电磁方案 。2 0 1 1 年第六 届 比赛 中要求赛道是 由白色底板和黑色的指引虚线
坐标作为中心值。如不符合条件 , 则为无效行。
4 黑色指 引虚线 的提取算法

openmv 循迹黑线思路

openmv 循迹黑线思路

openmv 循迹黑线思路在使用OpenMV进行循迹黑线任务时,可以采用以下思路来实现:1. 图像预处理:首先,从摄像头获取实时图像,然后对图像进行预处理。

可以使用OpenMV的图像处理库,例如图像二值化、滤波、去噪等操作,以便增强图像的对比度和清晰度,以便更好地检测黑线。

2. 黑线检测:在预处理后的图像中,使用OpenMV的图像处理库来检测黑线的位置。

可以通过阈值分割或边缘检测等方法来找到黑线的边缘或轮廓。

可以根据具体情况选择合适的方法,以保证能够准确地检测到黑线。

3. 黑线跟踪:一旦黑线被检测到,可以使用OpenMV的机器视觉库来跟踪黑线的位置。

可以使用直线拟合或函数拟合等方法来获取黑线的几何属性,例如角度、位置等信息。

根据这些信息,可以使机器人相应地调整方向和速度,以保持沿着黑线的运动。

4. 控制反馈:在黑线跟踪的过程中,可以根据OpenMV检测到的黑线位置和机器人当前位置间的差异,进行控制反馈。

通过适当的控制算法,可以调整机器人的转向角度和速度,使其保持在黑线上运动。

可以考虑使用PID控制、模糊控制或神经网络控制等方法,以实现更精确的循迹效果。

5. 异常处理:在循迹过程中,可能会遇到一些异常情况,例如黑线中断、弯曲等。

为了应对这些异常情况,可以使用OpenMV的图像处理库来检测其他特征,例如十字路口、障碍物等。

根据检测到的特征,可以改变机器人的行为,例如停下来等待、绕过障碍物等,以确保机器人能够适应不同的路况。

通过以上的思路,可以利用OpenMV进行循迹黑线任务的实现。

当然,在实际应用中,可能还需要根据具体情况做一些调整和改进。

通过不断优化算法和参数的调整,可以使循迹黑线任务的效果更加准确和稳定。

opevcv lsd线段提取

opevcv lsd线段提取

opevcv lsd线段提取LSD线段提取是基于OpenCV图像处理库的一种算法,用于从图像中提取直线段。

本文将介绍LSD线段提取的原理、应用领域和优缺点。

一、LSD线段提取原理LSD(Line Segment Detector)线段提取算法是一种基于边缘检测的直线段提取方法。

它通过分析图像中的边缘信息,识别出其中的直线段,并给出直线段的起点和终点坐标。

LSD算法主要包括以下几个步骤:1. 边缘检测:使用Canny边缘检测算法对图像进行预处理,提取出图像中的边缘信息。

2. 候选线段生成:根据边缘信息,生成候选直线段。

LSD算法采用了一种基于区域的策略,在不同的尺度上对边缘进行分组,生成候选直线段。

3. 直线段合并:对生成的候选直线段进行合并,得到最终的直线段结果。

LSD算法采用了一种自底向上的策略,从低层次的直线段开始合并,逐渐扩大范围,直到合并完所有相关的直线段。

二、LSD线段提取应用领域LSD线段提取算法在计算机视觉和图像处理领域有着广泛的应用。

以下是一些常见的应用领域:1. 机器人导航:LSD线段提取可以用于识别机器人环境中的直线障碍物,帮助机器人规划路径和避免碰撞。

2. 道路检测:LSD线段提取可以用于车道线检测,帮助自动驾驶车辆实现道路规划和车道保持功能。

3. 工业检测:LSD线段提取可以用于检测工业产品中的缺陷,如裂纹、划痕等,帮助提高产品质量和生产效率。

4. 图像分析:LSD线段提取可以用于图像分析和对象识别,帮助计算机理解图像中的结构和内容。

三、LSD线段提取优缺点LSD线段提取算法具有以下优点:1. 高效性:LSD算法采用了一种快速的合并策略,可以在很短的时间内处理大量的直线段。

2. 精度高:LSD算法能够有效地识别出图像中的直线段,并给出其准确的起点和终点坐标。

3. 鲁棒性强:LSD算法对图像噪声和光照变化具有较强的鲁棒性,能够适应不同的图像环境。

然而,LSD线段提取算法也存在一些缺点:1. 对参数敏感:LSD算法的性能很大程度上取决于参数的选择,需要根据具体应用场景进行调整。

TSL1401线性CCD应用笔记,中文资料,环境光自适应算法

TSL1401线性CCD应用笔记,中文资料,环境光自适应算法

蓝宙TSL1401线性CCD应用笔记本文对第八届飞思卡尔智能车竞赛指定用线性CCD使用相关经验跟大家分享一下,本文不再讲述线性CCD基本原理,基本原理大家可阅读芯片手册,本文重点介绍使用线性CCD时需要考虑的一些问题及注意事项,并给出了参考解决方案。

旨在让大家更有效地使用和深入研究TSL1401线性CCD模块。

环境光影响问题试验表明TSL1401线性CCD的输出信号和环境光线密切相关,在自然光条件比晚上灯光下AO引脚输出电压值高出很多,正对着光线比背着光线输出电压高,白炽灯光下比日光灯下输出电压高。

因此,同一参数(曝光时间、镜头光圈)难以适应各种环境,在光线较弱环境下的参数在强光下会出现输出饱和,在较强光线下调节好的参数在弱光下输出电压过低,甚至处于截止状态。

在智能车应用中,白天自然光环境和晚上灯光环境、正对光和背光、不同的比赛场地之间都不能采用相同的曝光参数。

与输出电压密切相关的参数是曝光量,曝光量取决于CCD模块所采用的镜头光圈大小和程序所控制的曝光时间。

智能车为适应各种运行环境,必须实时感知环境,并根据环境闭环调节曝光量,使得在不同环境中曝光量都处于一个合理的范围,这样才能保证在不同环境中CCD输出电压在合理范围,以利于算法提取黑线信息。

镜头相关参数一旦选定在智能车运行难以改变,曝光时间比较容易通过程序控制,因此比较容易实现的调整曝光量方法是通过软件调整曝光时间。

曝光时间调整方法见“曝光时间自适应策略”一章。

输出信号放大根据上一章所述,可以通过调整曝光时间来适应各种环境,在弱光环境增大曝光时间,在强光下减小曝光时间。

但是曝光时间不能无限增大的,因为增大曝光时间势必降低采样率(每秒采样次数)采样率低控制周期就长,智能车反应就慢。

根据历届摄像头车参赛经验,1米的前瞻,3.5m/s的速度情况下,控制周期不得高于20ms(采样率不得低于50Hz),否则智能车转向机构反应再快也无法很好跟随赛道而冲出赛道。

线激光提取算法

线激光提取算法

线激光提取算法1. 简介线激光提取算法是一种用于从图像或点云数据中提取线激光的方法。

线激光是指由激光器发射的一条细长的光束,通常用于测量和建模三维环境。

线激光提取算法的目标是从复杂的背景中准确地分离出线激光,并提取出其相关属性,如位置、方向和强度等。

线激光提取算法在许多领域都有广泛应用,包括机器人导航、三维建模、自动驾驶等。

通过提取线激光信息,可以实现环境感知、障碍物检测和路径规划等功能。

2. 常见的线激光提取算法2.1 阈值分割算法阈值分割算法是最简单且常用的线激光提取方法之一。

该算法基于图像或点云数据中线激光与背景之间的明显对比,通过设定一个合适的阈值来将线激光与背景分离。

具体步骤如下:1.将图像或点云数据转换为灰度图像或灰度值;2.设定一个合适的阈值,将灰度值高于阈值的像素点标记为线激光;3.根据需要,可以进行后处理操作,如噪声去除、线段连接等。

阈值分割算法简单快速,适用于背景与线激光对比明显的情况。

然而,在复杂背景或光照变化等情况下,该算法可能无法准确提取线激光。

2.2 基于几何特征的算法基于几何特征的线激光提取算法利用线激光在图像或点云中的几何特征进行分割。

这些几何特征可以是直线性质、形状约束或拓扑结构等。

常见的基于几何特征的算法包括:•Hough 变换:通过将图像或点云中的点映射到参数空间,并检测参数空间中的峰值来提取直线;•RANSAC(随机抽样一致性):通过随机选择一组数据点,并根据模型与数据之间的一致性进行迭代优化来提取直线;•拓扑约束:利用线激光的拓扑结构,如端点、交叉点等进行线激光提取。

基于几何特征的算法可以提取出更精确的线激光,但其计算复杂度较高,对噪声和异常点敏感。

2.3 基于机器学习的算法近年来,基于机器学习的线激光提取算法逐渐得到广泛应用。

这些算法利用已标注的线激光数据进行训练,并通过学习线激光与背景之间的关系来提取线激光。

常见的基于机器学习的算法包括:•支持向量机(SVM):通过将线激光和背景分别表示为特征向量,并在特征空间中找到一个超平面来分类;•卷积神经网络(CNN):通过堆叠多个卷积层、池化层和全连接层来实现端到端的线激光提取。

摄像头采集信息的算法

摄像头采集信息的算法

摄像头采集信息的算法全文共四篇示例,供读者参考第一篇示例:摄像头在现代社会中扮演着重要角色,不仅在监控系统、安防领域有着广泛的应用,还在智能手机、笔记本电脑、平板电脑等设备中被广泛使用。

摄像头采集信息的算法是指利用摄像头获取的视频信息进行处理和分析的算法,其涉及到图像处理、计算机视觉和人工智能等多个领域,是当前研究热点之一。

摄像头采集信息的算法可以用于多种应用场景,例如人脸识别、车辆识别、动作检测、人体姿态识别等。

在这些应用中,摄像头首先将所拍摄的图像或视频传输至计算机系统中,而后算法会对图像进行分析和处理,从中提取出有意义的信息,并作出相应的判断和行为反应。

对于摄像头采集信息的算法来说,图像处理是其中一个重要的环节。

图像处理技术包括图像的采集、预处理、特征提取和特征匹配等步骤。

在图像采集阶段,摄像头会不断地捕获图像或视频,将其传输至计算机系统中。

在预处理阶段,图像可能需要进行去噪、平滑处理等,以便提高后续处理的效果。

特征提取是指从图像中提取出具有代表性的信息,例如像素级的颜色、纹理、形状等信息。

特征匹配则是将提取出的特征与预先训练好的模型进行匹配,从而实现对图像中物体或场景的识别和分类。

除了图像处理,计算机视觉也是摄像头采集信息的算法中不可或缺的一部分。

计算机视觉是一门研究如何让计算机“看懂”图像或视频的学科,其包括目标检测、目标跟踪、图像识别、物体检测等多个领域。

通过计算机视觉的技术,摄像头可以实现人脸识别、动作检测、人体姿态识别等功能。

在人工智能领域,深度学习和神经网络技术也被广泛应用于摄像头采集信息的算法中。

深度学习是一种基于人工神经网络的机器学习方法,通过大量的训练数据和复杂的网络结构,可以实现更加精准的图像识别和分类。

神经网络模仿了人脑的神经元网络结构,在处理图像时可以提取出更多的高级特征,提高图像处理的准确性和效率。

在工业领域,摄像头采集信息的算法也被广泛应用于生产自动化和机器视觉系统中。

脊提取算法

脊提取算法

脊提取算法
脊提取算法通常用于图像处理领域,主要目的是从图像中提取出具有明显特征的脊线或脊点,这些特征通常对于图像的分析和理解很有帮助。

以下是一些常见的脊提取算法:
1. 方向滤波器:使用方向滤波器来检测图像中的脊线。

这些滤波器通常是一组在不同方向上敏感的滤波器,例如,Sobel 或Gabor 滤波器。

通过在图像上滑动这些滤波器,可以检测到不同方向上的脊线。

2. Hessian 矩阵:使用 Hessian 矩阵来检测图像中的脊线。

Hessian 矩阵包含了图像局部区域的二阶导数信息,可以用来确定图像中的脊线位置和方向。

3. Ridgelet 变换: Ridgelet 变换是一种用于图像脊提取的多尺度变换方法。

它在不同方向和尺度上对图像进行变换,以突出脊线的特征。

4. 小波变换:小波变换是一种多尺度分析方法,可用于提取图像中的脊线。

小波变换将图像分解为不同尺度和方向上的小波系数,从中可以提取出图像的脊线信息。

5. Frangi 滤波器: Frangi 滤波器是一种基于 Hessian 矩阵的滤波器,特别设计用于检测图像中的血管结构,但同样适用于脊线的提取。

这些算法的选择取决于应用场景和图像的特性。

在实际应用中,可能需要根据具体情况选择合适的算法或进行算法的组合,以获得更好的脊线提取效果。

openmv 循迹黑线思路

openmv 循迹黑线思路

openmv 循迹黑线思路
摘要:
1.OpenMV 简介
2.循迹黑线的概念
3.OpenMV 实现循迹黑线的思路
4.OpenMV 循迹黑线的应用场景
正文:
1.OpenMV 简介
OpenMV 是一种基于MicroPython 的低成本、高性能的嵌入式计算机视觉平台,可以方便地在各种应用中实现计算机视觉功能。

它具有小巧的体积、低功耗、可编程性强等特点,广泛应用于机器人、智能家居、自动驾驶等领域。

2.循迹黑线的概念
循迹黑线,又称为轨迹黑线,是一种基于光学传感器的导航方法。

通过检测地面上的黑线,机器人可以沿着黑线行驶。

这种方法广泛应用于无人驾驶车辆、自动导引车等自动导航领域。

3.OpenMV 实现循迹黑线的思路
OpenMV 实现循迹黑线的思路主要分为以下几个步骤:
(1)图像采集:通过OpenMV 的摄像头模块,获取地面上的黑线图像。

(2)图像处理:对采集到的图像进行预处理,如去噪、滤波等操作,以提
高识别的准确性。

(3)黑线检测:利用图像处理算法,如边缘检测、形态学操作等,从图像中提取出黑线的位置信息。

(4)黑线跟踪:根据检测到的黑线位置信息,控制机器人的行驶方向和速度,使其始终沿着黑线行驶。

4.OpenMV 循迹黑线的应用场景
OpenMV 循迹黑线技术可以广泛应用于各种自动导航领域,如无人驾驶车辆、自动导引车、机器人巡检等。

飞思卡尔智能车摄像头组技术报告 (2)

飞思卡尔智能车摄像头组技术报告 (2)

第十届“飞思卡尔”杯全国大学生智能汽车竞赛技术报告摘要本文设计的智能车系统以K60微控制器为核心控制单元,基于CCD摄像头的图像采样获取赛道图像信息,提取赛道中心线,计算出小车与黑线间的位置偏差,采用PD方式对舵机转向进行反馈控制。

使用PID控制算法调节驱动电机的转速,结合特定算法分析出前方赛道信息实现对模型车运动速度的闭环控制。

为了提高模型车的速度和稳定性,我们用C++开发了仿真平台、蓝牙串口模块、SD卡模块、键盘液晶模块等调试工具,通过一系列的调试,证明该系统设计方案是确实可行的。

关键词:K60,CCD摄像头,二值化,PID控制,C++仿真,SD卡AbstractIn this paper, we will design a intelligent vehicle system based on MC56F8366 as the micro-controller unit. using the CCD image sensor sampling to the track image information to extract the track line center, to calculate the positional deviation between the car with the black line, the use of PD on the rudder. The machine turned to the feedback control. We use PID control algorithm to adjust the speed of the drive motor, combined with specific algorithms to achieve closed-loop control of the movement speed of the model car in front of the track. In order to improve the speed and stability of the model car, we use the C++ to develop a simulation platform, Bluetooth serial module, SD card module, keyboard, LCD modules, debugging tools. Through a series of debugging, the system design is feasible.Key words: K60,CCD_camera, binaryzation, PID control, C++ simulation, SD card目录第1章引言................................................................................... - 1 - 第2章系统总体设计................................................................ - 2 - 2.1 系统分析..................................................................................... - 2 - 2.2 车模整体布局............................................................................. - 3 - 2.3 本章小结....................................................................................... - 4 - 第3章系统机械设计及实现................................................... - 5 - 3.1 前轮定位的调整......................................................................... - 5 -3.1.1主销内倾..............................................................................- 6 -3.1.2 后倾角.................................................................................- 6 -3.1.3 内倾角.................................................................................- 7 - 3.2 舵机安装....................................................................................... - 8 -3.2.1 左右不对称问题的发现与解决........................................- 10 - 3.3 编码器的安装............................................................................ - 10 - 3.4 摄像头安装.................................................................................- 11 -3.4.1 偏振镜的使用......................................................................- 12 -3.4.2 摄像头的标定......................................................................- 12 - 3.5 摄像头的选用.............................................................................- 13 - 3.6 红外接收装置.............................................................................- 14 -3.7 防止静电复位.............................................................................- 15 - 3.8 本章小结.......................................................................................- 15 - 第4章硬件电路系统设计及实现 ...................................... - 16 -4.1 硬件设计方案............................................................................- 16 - 4.2 电源稳压......................................................................................- 17 - 4.3 电机驱动......................................................................................- 18 - 4.4 图像处理部分............................................................................- 19 -4.4.1 摄像头升压电路.............................................................- 19 -4.4.2 视频分离电路.................................................................- 19 -4.4.3 硬件二值化.....................................................................- 19 - 4.5 灯塔电路......................................................................................- 21 - 4.6 本章小结......................................................................................- 21 -第5章系统软件设计.............................................................. - 22 -5.1 软件流程图...............................................................................- 22 - 5.2 算法新思路...............................................................................- 23 -5.2.1中心线提取.......................................................................- 23 -5.2.2 直角检测........................................................................... - 24 -5.2.3 单线检测......................................................................... - 24 - 5.3 舵机控制.....................................................................................- 25 - 5.4 速度控制.....................................................................................- 26 - 5.5 PID算法....................................................................................- 26 - 5.6 路径优化.....................................................................................- 31 -第6章系统联调...................................................................... - 33 - 6.1 开发工具.................................................................................... - 33 - 6.2 无线调试蓝牙模块及蓝牙上位机..........................................- 33 - 6.3 键盘加液晶调试......................................................................- 34 - 6.4 TF卡调试模块.........................................................................- 34 -6.4.1 TF卡.............................................................................- 34-6.4.2 SDCH卡 .........................................................................- 35 -6.4.3 软件实现.......................................................................- 36 - 6.5 C++上位机设计........................................................................- 36 - 6.6 电源放电模块...........................................................................- 38-6.6.1 镍镉电池记忆效应…………………………………….. - 39-6.6.2 放电及电池性能检测设备…………………………….. - 39- 6.7 本章小结....................................................................................- 40 - 第7章模型车技术参数........................................................ - 41 - 第8章总结............................................................................... - 42 - 参考文献...................................................................................... - 44 -第1章引言在半导体技术日渐发展的今天,电子技术在汽车中的应用越来广泛,汽车智能化已成为行业发展的必然趋势。

openmv 循迹黑线思路

openmv 循迹黑线思路

openmv 循迹黑线思路如何使用OpenMV进行黑线循迹。

OpenMV是一款功能强大的嵌入式视觉开发平台,它能够快速进行图像处理和计算机视觉任务。

黑线循迹是OpenMV常见的一个应用训练任务,下面将介绍一步一步使用OpenMV 进行黑线循迹的思路。

第一步:准备硬件首先,我们需要准备相应的硬件设备。

OpenMV官方提供了一款名为OpenMV Cam的嵌入式视觉开发板,它是一款非常适合进行黑线循迹任务的硬件设备。

除了OpenMV Cam之外,我们还需要一条黑色的线路,作为循迹的目标。

确保OpenMV Cam和线路之间的距离适中,并且线路在OpenMV Cam的视野范围内。

第二步:安装OpenMV IDE接下来,我们需要安装OpenMV官方提供的开发环境OpenMV IDE。

打开OpenMV官方网站,选择合适的版本下载并安装。

安装完成后打开OpenMV IDE,并将OpenMV Cam连接到电脑上。

第三步:编写代码现在,我们可以开始编写代码了。

在OpenMV IDE的代码编辑区域,我们可以使用Python语言来编写代码。

以下是一个简单的示例代码:pythonimport sensorimport imageimport time# 初始化摄像头sensor.reset()sensor.set_pixformat(sensor.GRAYSCALE)sensor.set_framesize(sensor.QQVGA)sensor.skip_frames(time = 2000)sensor.set_auto_gain(False)sensor.set_auto_whitebal(False)# 设置阈值threshold_index = 0THRESHOLDS = [(0, 64)]# 启动循迹while(True):img = sensor.snapshot().histeq()blobs = img.find_blobs([THRESHOLDS[threshold_index]], pixels_threshold=200, area_threshold=200)if blobs:# 找到最大的blobmax_blob = max(blobs, key=lambda b: b.pixels())img.draw_rectangle(max_blob.rect())img.draw_cross(max_blob.cx(), max_blob.cy())# 偏移计算offset = max_blob.cx() - img.width() / 2print(offset)以上示例代码首先初始化摄像头,接着设置阈值,然后进入一个无限循环。

openmv 循迹黑线思路

openmv 循迹黑线思路

openmv 循迹黑线思路概述在机器人领域中,循迹黑线是一个常见的问题。

通过使用OpenMV这样的嵌入式视觉模块,我们可以实现机器人沿着黑线行驶的功能。

本文将介绍OpenMV循迹黑线的思路和实现方法。

硬件准备在开始之前,我们需要准备以下硬件设备: 1. OpenMV摄像头模块 2. 电机驱动模块 3. 直流电机 4. 黑线轨迹OpenMV工作原理OpenMV是一款基于ARM微处理器的嵌入式视觉模块。

它具有图像处理和机器视觉功能,可以用于各种应用,包括循迹黑线。

OpenMV模块通过摄像头采集图像,并通过图像处理算法来检测黑线的位置。

图像采集与处理1.初始化摄像头模块,设置图像的分辨率和帧率。

2.连接电机驱动模块,设置电机的控制引脚。

3.循环读取摄像头采集的图像。

4.将图像转换为灰度图像,简化后续处理。

5.对灰度图像应用二值化处理,将图像转换为黑白二值图像。

6.使用图像处理算法检测黑线的位置。

黑线检测算法1.定义阈值,将灰度图像二值化为黑白图像。

2.对二值图像进行形态学处理,消除噪点和平滑图像。

3.使用霍夫变换检测直线,找到黑线的位置。

4.根据直线的位置计算偏差值,用于控制电机转向。

电机控制1.根据偏差值调整电机的转向。

2.控制电机的速度,使机器人沿着黑线行驶。

3.循环执行上述步骤,实现实时的循迹功能。

算法优化与调试1.调整阈值,使得黑线能够被准确地检测出来。

2.优化形态学处理的参数,以获得更好的图像效果。

3.调整电机控制的参数,使机器人行驶更加稳定。

4.在实际场景中进行测试和调试,优化算法的性能和稳定性。

总结通过使用OpenMV模块和相应的图像处理算法,我们可以实现机器人的循迹黑线功能。

在实际应用中,我们可以根据具体需求进行算法优化和调试,以获得更好的效果。

循迹黑线是机器人领域中的一个基础问题,通过学习和实践,我们可以更好地理解和掌握相关的技术和方法。

希望本文对您理解OpenMV循迹黑线的思路和实现方法有所帮助。

openmv 循迹黑线思路

openmv 循迹黑线思路

openmv 循迹黑线思路在使用OpenMV进行循迹黑线时,思路一般可以分为以下几个步骤:图像预处理、特征提取、路径规划和电机控制。

首先,图像预处理是很关键的一步。

OpenMV使用的是MicroPython语言,在进行图像处理前,首先需要对图像进行读取。

我们可以使用OpenMV库中的`sensor`模块来控制OpenMV内置摄像头进行图像读取。

读取到的图像一般是RGB格式的图像,但对于循迹黑线任务来说,我们只需要提取黑色部分即可。

所以,我们可以将图像转换为灰度图像,再进行二值化处理,将黑色部分转为白色,其它部分转为黑色。

这样可以将图像中的黑线轮廓提取出来。

接下来,特征提取是很重要的一步。

在预处理之后的图像中,我们需要提取黑线的特征。

对于循迹黑线任务来说,最常见的特征提取方法就是边缘检测。

我们可以使用OpenMV库中的`image`模块来进行边缘检测,例如使用Canny算法。

接下来,我们可以使用霍夫变换来检测直线。

在OpenMV中,我们可以使用`find_lines`方法来实现这一步骤。

通过边缘检测和直线检测,我们可以得到黑线的大致方向和位置。

然后,路径规划是决定行进方向的一步。

在得到黑线的位置和方向之后,我们需要根据当前的位置和方向来决定下一步的行进方向。

有很多算法可以实现路径规划,例如PID控制算法。

在OpenMV中,我们可以使用`KPID`类来实现PID控制。

我们可以根据当前位置和方向与目标位置和方向之间的差异,计算出我们需要调整的角度,并确定下一步需要转的方向。

最后,电机控制是执行行动的最后一步。

在确定下一步的行进方向之后,我们可以通过控制电机的转速和方向来实现机器人的运动。

在OpenMV中,我们可以使用`pyb`模块来控制电机。

我们可以根据路径规划的结果,设置电机的转速和方向,使机器人向预定的方向行进。

综上所述,使用OpenMV进行循迹黑线任务的思路一般可以包括图像预处理、特征提取、路径规划和电机控制。

TPS7350

TPS7350

TPS7350PS7350是微功耗低压差线性电源芯片,具有完善的保护电路,包括过流、过压、电压反接保护。

使用这个芯片只需要极少的外围元件就能构成高效稳压电路。

与LM2940及AS1117稳压器件相比,TPS7350具有更低的工作压降和更小的静态工作电流,可以使电池获得相对更长的使用时间。

由于热损失小,因此无需专门考虑散热问题。

而且其纹波很小,又为线性稳压芯片,可以为单片机及片外AD模块提供很稳定的工作电压!5.2 黑线提取5.2.1 直接边缘检测算法由于比赛赛道是在白色底板上铺设黑色引导线,所以干扰比较小,采用边缘检测算法较为简单。

该算法的主要过程如下:从最左端的第一个有效数据点开始依次向右进行阀值判断:由于实际中黑白赛道边缘可能会出现模糊偏差,导致阀值并不是个很简单介于两相邻之间,很可能要相隔两个点。

因此:第line为原点,判断和line+3的差是否大于该阀值,如果是则将line+3记为i,从i开始继续在接下的从i+3到该行最末一个点之间的差值是否大于阀值,如果大于则将line+i/2+1的坐标赋给中心给黑线中心位置值,如图5.3所示:图5.3边缘检测算法利用该算法所得到的黑线提取效果可靠,但是每行120个点都进行采集,就使得单片机的负担很重,我们的目标只是把黑线的位置提取出来,而不是把整场整行的数据都进行采集和分析处理。

所以下面介绍另一个算法:跟踪边缘检测算法。

5.2.2 跟踪边缘检测算法这种算法跟上一小节介绍的直接边缘检测算法一样,也是寻找出目标指引线的左边缘,仍然用左边缘的位置代表目标指引线的位置。

但跟踪边缘检测从视频信号矩阵每行中寻找左边缘的方法与上一小节介绍的不同。

因为目标指引线是连续曲线,所以相邻两行的左边缘点比较靠近。

跟踪边缘检测正是利用了这一特性,对直接边缘检测进行了简化。

其思路是:若已寻找到某行的左边缘,则下一次就在上一个左边缘附近进行搜寻,这种方法的特点是始终跟踪每行左边缘的附近,去寻找下一列的左边缘,所以称为“跟踪”边缘检测算法。

面阵CCD

面阵CCD

摄像头工作原理摄像头分为黑白和彩色两种,根据赛道特点,为达到寻线目的,只要提取到画面的灰度信息,而不必要提取其色彩信息,所以设计中采用的是黑白摄像头。

摄像头主要由镜头、图像传感芯片和外围电路构成。

图像传感芯片是其最重要的部分,但该芯片要配以合适的外围电路才能工作。

将芯片和外围电路制作在一块电路板上,称为“单板”。

若给单板配上镜头、外壳、引线和接头,就构成了通常所见的摄像头。

我们比赛用的摄像头主要分为黑白和彩色两种。

彩色摄像头对比度比黑白的要好,对赛道不同背景色有较好的抗干扰能力,但考虑到比赛时我们只关注黑线的提取而不关心图像彩色信息,所以我们只选用黑白摄像头。

接下来,我们用眼睛来打比方以说明成像原理:当光线照射景物,景物上的光线反射通过人的晶状体聚焦,在视网膜上形成图像,之后视网膜的神经将信息传导到大脑,我们就能看见东西了。

摄像头成像的原理和眼睛非常相似,光线照射景物,景物上的光线反射通过镜头聚焦,CCD 图像传感器就会感知到图像。

而感知图像的具体过程是这样的:摄像头按一定的分辨率,以隔行扫描的方式采集图像上的点,当扫描到某点时,就通过图像传感芯片将该点处图像的灰度转换成与之一一对应的电压值,然后将此电压值通过视频信号端输出。

摄像头的工作原理是:按一定的分辨率,以隔行扫描的方式采集图像上的点,当扫描到某点时,就通过图像传感芯片将该点处图像灰度转换成与灰度一一对应的电压值,然后将此电压值通过视频信号端输出。

具体而言(参见图4-1),摄像头连续地扫描图像上的一行,则输出就是一段连续的电压信号,该电压信号的高低起伏反映了该行图像灰度变化。

当扫描完一行,视频信号端就输出一个低于最低视频信号电压的电平(如0.3V),并保持一段时间。

这样相当于,紧接着每行图像信号之后会有一个电压“凹槽”,此“凹槽”叫做行同步脉冲,它是扫描换行的标志。

然后,跳过一行后(摄像头是隔行扫描的),开始扫描新的一行,如此下去,直到扫描完该场的视频信号,接着会出现一段场消隐区。

摄像头pid算法思路

摄像头pid算法思路

基于CCD摄像头智能车分段PID控制算法设计自动寻迹智能车涉及到当前高技术领域内的许多先进技术,其中最主要的是传感技术、路径规划和运动控制。

本课题是以飞思卡尔智能车竞赛为背景,以单片机作为核心控制单元,以摄像头作为路径识别传感器,以直流电机作为小车的驱动装置,以舵机控制小车转向。

车模竞赛的赛道是一个具有特定几何尺寸约束、摩擦系数及光学特性的KT板,其中心贴有对可见光及不可见光均有较强吸收特性的黑色条带作为引导线,宽度为2.5 cm。

在行驶过程中,系统通过摄像头获取前方赛道的图像数据,同时通过测速传感器实时获取智能车的速度,采用路径搜索算法进行寻线判断和速度分析,然后作控制决策,控制转向舵机和直流驱动电机工作。

智能车通过实时对自身运动速度及方向等进行调整来“沿”赛道快速行驶。

本文主要介绍摄像头通过提取赛道黑线信息交予单片机处理,通过单片机输出控制信号控制舵机转向来控制车模的转向,从而很好的自动循迹。

1 总体软硬件结构及思路此智能车辆定位系统用摄像头拍摄车辆前方的赛道,通过MC9S12XS128采样视频信号,获得图像数据。

然后用合适的算法,如跟踪边缘检测算法,分析图像数据,提取目标指引线。

然后,系统根据目标指引线的位置信息,对舵机和电机施以合适的控制。

本智能车运动系统的结构图如图1所示。

因为系统是一个有机的整体,所以需配合好系统的摄像头、控制单片机、电机(包括直流伺服电动机、光电编码器)、舵机和辅助电路(电源板、电机驱动板)等各个部分。

舵机是实时控制车模的转向,是比赛快速性和稳定性的关键,舵机控制有很多的控制算法,如:PID经典控制算法、模糊算法、人工智能算法等。

2 系统程序总体控制流程系统的基本软件流程是:首先,对各功能模块和控制参数进行初始化;然后,通过图像采集模块获取前方赛道的图像数据,同时通过速度传感器模块获取赛车的速度。

采用PID对舵机进行反馈控制。

另外根据检测到的速度,结合速度控制策略,对赛车速度不断进行适当调整,使赛车在符合比赛规则的前提下,沿赛道快速行驶。

摄像头跟踪算法的优化与实现

摄像头跟踪算法的优化与实现

摄像头跟踪算法的优化与实现近年来随着人工智能技术的飞速发展,摄像头跟踪算法的优化与实现成为研究热点之一。

这些算法被广泛应用于视频监控、智能安防等领域,为人们的生活和工作带来了极大的便利。

本文将介绍摄像头跟踪算法的基本原理及其优化方法,并结合实际应用案例进行探讨。

一、摄像头跟踪算法的基本原理摄像头跟踪算法的基本原理是通过摄像机对目标的图像进行采集,并通过图像处理和分析来得到目标的实时位置和运动轨迹,从而完成对目标的跟踪。

在实际应用中,摄像头跟踪算法可以分为两类:基于像素级别的跟踪算法和基于特征点的跟踪算法。

1、基于像素级别的跟踪算法像素级别的跟踪算法是基于对目标图像的像素级别进行处理和分析得到标的跟踪信息的,它们主要包括:基于图像灰度的跟踪算法、基于背景差分的跟踪算法、基于连续检测的跟踪算法等。

其中,基于图像灰度的跟踪算法是最常见的一种,其原理是通过对目标图像的灰度值进行提取,然后通过各种计算方法来找出目标的实时位置。

但是,这种算法有一个明显的缺点就是对光照条件比较敏感。

2、基于特征点的跟踪算法与像素级别的跟踪算法相比,基于特征点的跟踪算法则是通过对图像中的特殊点进行匹配和跟踪,从而实现对目标的跟踪。

这种算法的优点是在目标位置移动或者发生形态变化时,可以保持较好的跟踪效果。

而缺点则是对处理和计算速度要求相对较高。

二、摄像头跟踪算法的优化与实现摄像头跟踪算法在实际应用中不可避免的需要进行优化和改进,以提高算法的速度和精度。

以下是几种常见的优化方法:1、光照处理基于图像灰度的跟踪算法在光照条件发生变化时容易出现误差,因此可以在算法中引入光照处理的方法。

例如,可以通过对图像中的亮度进行归一化操作,从而达到更好的跟踪效果。

2、特征点提取在基于特征点的跟踪算法中,特征点的提取和匹配显然是决定算法性能的关键因素。

因此,可以通过运用各种特征提取算法,如SIFT、SURF等,来提高算法的效果和速度。

此外,还可以采用快速的特征匹配算法,例如RANSAC算法等,来优化特征点的匹配效果。

lsd线特征提取算法

lsd线特征提取算法

lsd线特征提取算法
摘要:
1.线特征提取算法简介
2.LSD 线特征提取算法的原理
3.LSD 线特征提取算法在实际应用中的优势
4.LSD 线特征提取算法的实现
5.总结
正文:
1.线特征提取算法简介
线特征提取算法是一种从图像中提取直线特征的方法,这些直线特征在视觉感知和描述外部环境时具有重要意义。

线特征提取算法广泛应用于目标检测、识别和跟踪等领域,可以提高系统的精度和鲁棒性。

2.LSD 线特征提取算法的原理
LSD(Line Segment Detector)线特征提取算法是一种基于亚像素级精度检测的线段检测算法。

它能够在短时间内获得较高精度的线段检测结果,具有较好的光照和视角不变性特点。

LSD 算法通过计算图像中相邻像素点的梯度幅值和方向,来判断是否存在直线特征。

当梯度幅值大于一定阈值且方向一致时,认为该像素点处于直线上,从而提取出直线特征。

3.LSD 线特征提取算法在实际应用中的优势
LSD 线特征提取算法具有以下优势:
- 快速:在较短的时间内获得较高精度的线段检测结果;
- 高效:可以实现在线性时间内得到亚像素级精度的检测结果;- 稳定:具有较好的光照和视角不变性特点,适用于不同场景;- 鲁棒:能适应不同尺度、旋转和光照条件下的目标检测和识别。

4.LSD 线特征提取算法的实现
LSD 线特征提取算法的实现主要依赖于OpenCV 库。

lsd线特征提取算法

lsd线特征提取算法

lsd线特征提取算法【原创版】目录一、引言二、LSD 线特征提取算法的原理与实现1.LSD 算法的简介2.LSD 算法的线段检测原理3.LSD 算法的线特征提取方法4.LSD 算法在 OpenCV 中的实现三、LSD 线特征提取算法的应用1.视觉感知与环境描述2.提高系统精度和鲁棒性四、总结正文一、引言随着计算机视觉技术的不断发展,人们对于图像的理解和分析能力不断提高。

在图像特征提取方面,线特征作为一种重要的视觉特征,具有光照和视角不变性特点,表现更为稳定、有效。

因此,研究线特征提取算法对于计算机视觉领域具有重要意义。

本文将介绍一种线特征提取算法——LSD 线特征提取算法,并对其原理与实现进行详细阐述。

二、LSD 线特征提取算法的原理与实现1.LSD 算法的简介LSD(Line Segment Detector)算法是一种线段检测算法,可以在线性时间内得到亚像素级精度的检测结果。

它是由 Rafael Grompone von Gioi、Jeremie Jakubowicz、Jean-Michel Morel 和 Gregory Shaker 等人于 2005 年提出的。

2.LSD 算法的线段检测原理LSD 算法的基本思想是通过计算图像中像素点之间的距离,判断哪些像素点组成线段。

具体来说,对于图像中的每一个像素点,LSD 算法会计算其邻域像素点之间的距离,然后根据距离阈值判断这些像素点是否组成线段。

3.LSD 算法的线特征提取方法LSD 算法在检测线段的同时,还可以提取线段的特征。

具体来说,对于检测到的线段,LSD 算法会根据线段的方向和长度提取线段的参数。

这些参数可以用来描述线段的形状和位置,从而作为线特征进行使用。

4.LSD 算法在 OpenCV 中的实现OpenCV 是一个开源的计算机视觉库,提供了丰富的图像处理功能。

在 OpenCV 中,可以通过调用 LineSegmentDetector 类实现 LSD 算法。

摄像头信号传输与识别

摄像头信号传输与识别

◆◆◆◆◆有关摄像头组的材料◆◆◆◆◆图像采集与路径识别要实现一个完整的基于摄像头的智能小车,第一步要做的就是将摄像头输出的模拟信号通过DSP的A/D转换采集到DSP中,然后对采集到的原始图像数据进行处理,以获取赛道中央的黑线在图像坐标系中的位置。

接着,就要利用处理得到的图象信息对智能小车进行控制。

所以,可以说对于基于摄像头的智能小车,图像采集是至关重要的。

只有做好了图像采集,才谈得上“智能”,否则小车只能是个“瞎子”摄像头。

要做图像采集,那么首先要选择好摄像头。

摄像头分黑白和彩色两种,由于赛道是“白底黑线”,所以为达到寻线目的,只需提取画面的灰度信息,而不必提取其色彩信息,所以我们选择采用黑白摄像头。

较使用同等分辨率的彩色摄像头而言,这样可减少单片机采样的负担。

此外,摄像头根据成像原理,分为CCD和CMOS两种,CCD成像效果好,CMOS 更省电,可以根据自己队的侧重点进行选择。

摄像头的工作原理是:按一定的分辨率以隔行扫描的方式采集图像上的点,当扫描到某点时,就通过图像传感芯片将该点处图像的灰度转换成与灰度一一对应的电压值,然后将此电压值通过视频信号端输出。

摄像头连续地扫描图像上的一行,则输出就是一段连续的电压信号,该电压信号的高低起伏反映了该行图像的灰度变化。

当扫描完一行,视频信号端就输出一个低于最低视频信号电压的电平(如0.3V),并保持一段时间。

这样相当于,紧接着每行图像信号之后会有一个电压“凹槽”,此“凹槽”叫做行同步脉冲,它是扫描换行的标志。

然后,跳过一行后(因为摄像头是隔行扫描的),开始扫描新的一行,如此下去,直到扫描完该场的视频信号,接着又会出现一段场消隐区。

该区中有若干个复合消隐脉冲,其中有个远宽于(即持续时间长于)其它的消隐脉冲,称为场同步脉冲,它是扫描换场的标志摄像头每秒扫描25 幅图像,每幅又分奇、偶两场,先奇场后偶场,故每秒扫描50 场图像。

奇场时只扫描图像中的奇数行,偶场时则只扫描偶数行。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

//本程序对黑线提取做了很大的改进,未对十字弯处理/*******************************************///本程序中加入了一些用于显示车模状态的LED灯/*经实测发现,近处的赛道宽度为60左右,远处为30左右,所以用可变赛道宽度进行搜索*/#include <hidef.h> /* common defines and macros */#include "derivative.h" /* derivative-specific definitions */#include <MC9S12XS128.h>//-----------函数声明-----------------//void delay(unsigned int t);#define HighSpeedLimit 40#define LowSpeedLimit 16#define SteerLeftLimit -35#define SteerRightLimit 35#define COLUMN 90 //采集列数#define MID_COLUMN 45 // 中间黑线#define ROW 40//采集行数#define LeftLED PORTB_PB0//左转方向灯#define RightLED PORTB_PB1//右转方向灯#define SpeedUpLED PORTB_PB2//加速指示灯#define SlowDownLED PORTB_PB3//减速方向灯#define Crossing_RoadLED PORTB_PB4//十字弯#define Dashed_RoadLED PORTB_PB5//虚线路段#define Mid_Route_Width_Factor 0.48 //赛道宽度系数int steer_dire_label=0;int SteerDelta=0;//舵机最终的偏转增量unsigned int Speed=0;//显示当前PWM2占空比大小unsigned int PreSpeed=0;float Threshold_Factor=0.9; //阈值系数设置unsigned int Threshold=120; //初设动态阈值为90,以后每传来一帧数据更新一次float Kp=0.8;//舵机方向比例系数float Kd=5.0;//舵机方向微分系数float MotorSpeed_Factor=6.0;//马达控制unsigned char Image_Data[ROW][COLUMN];unsigned int Left[ROW],Right[ROW];//左右黑线unsigned int VisualMiddle[ROW];//虚拟中线unsigned int Middle[ROW];//最终存放中间黑线值的二维数组unsigned int Row_Attribute[ROW];//行属性unsigned int row,column;int m=0;//计算采集到的行数unsigned char Line_Flag=0; //奇偶场unsigned int Line_C=0; //采集行数d int PreSteerDirection=50;//之前的舵机方向,用与前后比较unsigned int LeftFlag=0,RightFlag=0;//左右黑线标志unsigned int Left_Start_Flag=0,Right_Start_Flag=0;//左右起始黑线找到标志unsigned int L_lost_count=0;//左黑线丢失计数unsigned int R_lost_count=0;//右黑线丢失计数unsigned int L_last_lost=0;//左行上一行丢线标志unsigned int R_last_lost=0;//右行上一行丢线标志unsigned int L_last_memory=0;//左行上一次有黑线的黑线所在列数unsigned int R_last_memory=0;//右行上一次有黑线的黑线所在列数unsigned int HS_Data[ROW]={40,45,50,55,60,65,70,75,80,85,90,95,100,105, 110,115,120,124,128,132,136,140,144,148,152,156,160,163,166,169,172,175,178,181,184,187,189,191,193,194}; unsigned int HS_Pointer=0;//指向行数数组中的数据int error[2]={0,0};//舵机PD调节时的误差参数void delay(unsigned int Time){ //一般,Time设为10000,可以实现1秒一次int i,j;for(i=0;i<Time;i++)for(j=0;j<8;j++) {}}void SlowDown(int timer){int i;PWMDTY2=0;PWMDTY3=50;for(i=0;i<timer;i++)_asm(nop);PWMDTY3=0;PWMDTY2=Speed;}/**************************************************** 函数名称: 图像灰度值采集** 功能描述: 采集像素值** 输入: 无** 输出: 无** 说明:***************************************************/void Data_collect(void){int ia=0;while(ia<COLUMN){ //这样把赛道取的窄一点_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);_asm(nop);Image_Data[Line_C][ia++] = PORTA; //portA是8位的,可表示0~255,即灰度值。

注意采集的数据先放在数组的后部,即从124->}}/***************************************************** 函数名称: PLL_Init** 功能描述: 时钟初始化函数** 说明:BUS CLOCK=80M****************************************************/void PLL_Init(void) //pllclock=2*osc*(1+SYNR)/(1+REFDV);{CLKSEL=0x00; //disengage PLL to systemPLLCTL_PLLON=1; //turn on PLLSYNR =0xc0 | 0x09;REFDV=0x80 | 0x01;POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=160MHz; while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it;CLKSEL_PLLSEL =1; //engage PLL to system;}/***********************************************//* P0输出频率为300Hz的方波,用于控制舵机 *//* P2,P3输出频率为20KHZ,用于驱动电机的转速 *//************************************************/void PWM_Init(void){PWME_PWME0=0x00; //禁止P0PWME_PWME2=0x00; //禁止P2PWME_PWME3=0x00; //禁止P3PWMPOL_PPOL0=1;//PWM Polarity 0开始输出高电平.PWMPOL_PPOL2=1;//PWM Polarity 2开始输出高电平.PWMPOL_PPOL3=1;//PWM Polarity 3开始输出高电平.PWMPRCLK=0x43; //0100 0011 A=80M/8=10M,B=80M/16=5M时钟预分频PWMSCLA=150; // SA=A/(2*150)=33.33KHZPWMSCLB=20; //SB=B/(2*20)=125KHZ;PWMCLK_PCLK0=1; //P0选的是SA时钟PWMPOL_PPOL0=1; //选用开始为高电平方式PWMCAE_CAE0=0; //选用左对齐方式PWMCLK_PCLK2=1; //P2选的是SB时钟PWMPOL_PPOL2=1; //选用开始为高电平方式PWMCAE_CAE2=0; //选用左对齐方式PWMCLK_PCLK3=1; //P2选的是SB时钟PWMPOL_PPOL3=1; //选用开始为高电平方式PWMCAE_CAE3=0; //选用左对齐方式PWMCTL=0x00; //控制寄存器设置为无联接//对舵机,驱动电机PWM波初始化PWMDTY0=50; //P0占空比为50%PWMDTY2=20; //P2占空比为50%PWMDTY3=33; //P3占空比为50%PWMPER0=100; //P0:Frequency=SA/100=333.33hzPWMPER2=100; //P2:Frequency=SB/100=1.25KHZPWMPER3=100; //P3:Frequency=SB/100=1.25KHZPWME_PWME0=1; //打开P0PWME_PWME2=1; //打开P2PWME_PWME3=1; //打开P3}/*************************************************** ** 函数名称: TIM_Init** 功能描述: 行场中断初始化函数** 说明:****************************************************/ void TIM_Init(void){TIOS =0x00; //定时器通道0,1 为输入捕捉TCTL4=0x09; //通道0 捕捉上升沿,通道1 捕捉下降沿TIE=0x03; //通道0,1 中断使能TFLG1=0xFF; //清中断标志位TSCR1=0x80; //定时器使能}/*************************************************** ** 函数名称: SCI0_Init** 功能描述: 串口1初始化函数** 说明: PS2--RX,PS3--TX****************************************************/{SCI0BDL = (byte)((80000000 /* OSC freq *//1) / 57600 /* baud rate */ / 16/*factor*/);SCI0CR1 = 0X00; /*normal,no parity*/SCI0CR2 = 0X0C; /*RIE=1,TE=1,RE=1, */}/**************************************************** 函数名称: 串口发射端程序** 功能描述: 发送赛道信息 1为黑线 0为白板** 输入: 无** 输出: 无** 说明:***************************************************/void SCI0_Transmit(unsigned char data){while (!(SCI0SR1&0x80));//如果SCI状态寄存器SCI1SR1的TDRE位为0,则一直执行这个无语句的循环,否则,执行下面语句SCI0DRL = data;//把要发送的数据存在SCI数据寄存器的低8位中}/***************************************************** 函数名称: IO_Init** 功能描述: 初始化函数** 说明:****************************************************/{DDRA=0X00;//A端口的数据传送方向为输入DDRB=0XFF;//端口B为输出PORTB=0XFF;//端口B全部打开}/************************************************/ /* 提取出图像的基本特征*//************************************************/ void Image_Operates(){char i,j;char Scan_Start,Scan_End;//扫描起始点,扫描终止点char Gate,Range;unsigned char Temp_Mid_Route;int t,temp0;Left_Start_Flag=0,Right_Start_Flag=0;//左右起始黑线找到标志 L_lost_count=0;//左黑线丢失计数R_lost_count=0;//右黑线丢失计数L_last_lost=0;//左行上一行丢线标志R_last_lost=0;//右行上一行丢线标志L_last_memory=0;//左行上一次有黑线的行计数器R_last_memory=0;//右行上一次有黑线的行计数器for(i=ROW-1;i>=0;i--) //数据初始化{Left[i]=0;Right[i]=COLUMN;VisualMiddle[i]=0;Row_Attribute[i]=0;}for(i=ROW-1;i>=0;i--){if(i>30){Gate=45;Range=40;}else if(i>20){Gate=35;Range=35;}else if(i>10){Gate=25;Range=30;}else{Gate=20;Range=20;}LeftFlag=RightFlag=0;//左右黑线标志位清零if(i>=ROW-2)//前两行全局扫描{//////////////////左边黑线起始行提取for(j=MID_COLUMN;j>1;j--){if(Image_Data[i][j]<Threshold/*&&Image_Data[i][j-1]<Threshold*/) {// if((Image_Data[i][j+1]-Image_Data[i][j]>Gate)||(Image_Data[i][j+2]-Image_Data[i][j]>Gate)){Left[i]=j;Left_Start_Flag=1;//识别到黑线LeftFlag=1;break;}}else if(j==2){Left[i]=0;break;}}//end for(j=MID_COLUMN;j>1;j--)///////////////////////////////右边黑线起始行提取for(j=MID_COLUMN;j<COLUMN-1;j++){if(Image_Data[i][j]<Threshold/*&&Image_Data[i][j+1]<Threshold*/) {// if((Image_Data[i][j-1]-Image_Data[i][j]>Gate)||(Image_Data[i][j-2]-Image_Data[i][j]>Gate)){Right[i]=j;Right_Start_Flag=1;//识别到黑线RightFlag=1;break;}}else if(j==COLUMN-2){Right[i]=COLUMN;break;}}//end for(m=MID_COLUMN;m<COLUMN-1;m++)}//end if(i<2) //前两行全局扫描else // (i<ROW-2){///////////////////左边if(Left_Start_Flag&&!L_last_lost) //识别到起始行且前一行没有丢失{Scan_End=Left[i+1]-Range;if(Scan_End<1)Scan_End=1;Scan_Start=Left[i+1]+Range;if(Scan_Start>VisualMiddle[i+1])Scan_Start=VisualMiddle[i+1];for(j=Scan_Start;j>Scan_End;j--)if(Image_Data[i][j]<Threshold/*&&Image_Data[i][j-1]<Threshold*/){//if((Image_Data[i][j+1]-Image_Data[i][j]>Gate)||(Image_Data[i][j+2]-Image_Data[i][j]>Gate)){Left[i]=j;LeftFlag=1;//识别到黑线break;}}else if(j==(Scan_End+1)){Left[i]=0;L_last_lost=1;//这一行数据丢失标识位L_last_memory=Left[i+1];break;}}//end if(Left_Start_Flag&&!L_last_lost) //识别到起始行且前一行没有丢失 else if(!Left_Start_Flag) //没有识别到起始行,继续寻找起始行{for(j=VisualMiddle[i+1];j>1;j--){if(Image_Data[i][j]<Threshold/*&&Image_Data[i][j-1]<Threshold*/) {// if((Image_Data[i][j+1]-Image_Data[i][j]>Gate)||(Image_Data[i][j+2]-Image_Data[i][j]>Gate)){Left[i]=j;Left_Start_Flag=1;//识别到黑线LeftFlag=1;break;}}else if(j==2){Left[i]=0;break;}}//end for(j=MID_COLUMN;j>1;j--)}//end else if(!Left_Start_Flag) //没有主识别到起始行,继续寻找起始行else if(L_last_lost) //识别到起始行但前一行丢失从虚拟中线开始循线{Scan_End=L_last_memory-Range;if(Scan_End<1)Scan_End=1;for(j=VisualMiddle[i+1];j>Scan_End;j--){if(Image_Data[i][j]<Threshold/*&&Image_Data[i][j-1]<Threshold*/) {//if((Image_Data[i][j+1]-Image_Data[i][j]>Gate)||(Image_Data[i][j+2]-Image_Data[i][j]>Gate)){Left[i]=j;LeftFlag=1;L_last_lost=0;break;}}else if(j==Scan_End+2){Left[i]=0;L_last_lost=1;//中间有数据丢失标识位break;}// end for(j=VisualMiddle[i-1];j>Scan_End;j--)}// end else if(L_last_lost) //识别到起始行但前一行丢失从虚拟中线开始循线 /////////////////////////////////右边if(Right_Start_Flag&&!R_last_lost) //识别到起始行且前一行没有丢失{Scan_End=Right[i+1]+Range;if(Scan_End>COLUMN)Scan_End=COLUMN;Scan_Start=Right[i+1]-Range;if(Scan_Start<VisualMiddle[i+1])Scan_Start=VisualMiddle[i+1];for(j=Scan_Start;j<Scan_End;j++)if(Image_Data[i][j]<Threshold/*&&Image_Data[i][j+1]<Threshold*/) {// if((Image_Data[i][j-1]-Image_Data[i][j]>Gate)||(Image_Data[i][j-2]-Image_Data[i][j]>Gate)){Right[i]=j;RightFlag=1;//识别到黑线break;}}else if(j==(Scan_End-2)){Right[i]=COLUMN;R_last_lost=1;//这一行数据丢失标识位R_last_memory=Right[i+1];break;}//end if(R_Start_Flag&&!R_last_lost)else if(!Right_Start_Flag) //没有别到右起始行,继续寻找起始行{for(j=VisualMiddle[i+1];j<COLUMN-1;j++){if(Image_Data[i][j]<Threshold/*&&Image_Data[i][j+1]<Threshold*/) {// if((Image_Data[i][j-1]-Image_Data[i][j]>Gate)||(Image_Data[i][j-2]-Image_Data[i][j]>Gate)){Right[i]=j;Right_Start_Flag=1;//识别到黑线RightFlag=1;break;}}else if(j==COLUMN-2){Right[i]=COLUMN;break;}}//end for(j=VisualMiddle[i-1];j<COLUMN-1;j++)}//end else if(!Right_Start_Flag) //没有主识别到起始行,继续寻找起始行else if(R_last_lost) //识别到起始行但前一行丢失从虚拟中线开始循线{Scan_End=R_last_memory+Range;if(Scan_End>COLUMN)Scan_End=COLUMN;for(j=VisualMiddle[i+1];j<Scan_End-1;j++){if(Image_Data[i][j]<Threshold/*&&Image_Data[i][j+1]<Threshold*/) {//if((Image_Data[i][j-1]-Image_Data[i][j]>Gate)||(Image_Data[i][j-2]-Image_Data[i][j]>Gate)){Right[i]=j;RightFlag=1;R_last_lost=0;break;}}else if(j==COLUMN-2){Right[i]=COLUMN;R_last_lost=1;//中间有数据丢失标识位break;}}// end for(j=VisualMiddle[i-1];j<Scan_End-1;j++)}// end else if(R_last_lost) //识别到起始行但前一行丢失从虚拟中线开始循线 }//end of else // (i>2)//////////////////////////////////属性判断if(LeftFlag&&RightFlag) Row_Attribute [i]=1;//两边都有黑线else if(LeftFlag) Row_Attribute [i]=2;//左边有黑线else if(RightFlag) Row_Attribute [i]=3;//左边丢失,仅右边有黑线else Row_Attribute [i]=0; //两边丢失////////////////////////中线读取if(i==ROW-1)VisualMiddle[i]=MID_COLUMN;else{ //要知道,最前面还有一个大大的for(n=0;n<Rows;n++)循环语句 if(Row_Attribute [i]) VisualMiddle[i]=(int)(Right[i]+Left[i])/2; else VisualMiddle[i]=VisualMiddle[i+1];}}//end of for(i=0;i<ROW;i++)////////把只有左黑线或右黑线的所在行补其另一黑线for(t=ROW-1;t>=0;t--){if(Row_Attribute[t]==1)Middle[t]=(Left[t]+Right[t])/2;if(Row_Attribute[t]==2)//只有左行{Temp_Mid_Route=(int)(16+Mid_Route_Width_Factor*t);Right[t]=Left[t]+2*Temp_Mid_Route;Middle[t]=Left[t]+Temp_Mid_Route;}else if(Row_Attribute[t]==3)//只有右行{Temp_Mid_Route=(int)(16+Mid_Route_Width_Factor*t);Left[t]=Right[t]-2*Temp_Mid_Route;Middle[t]=Right[t]-Temp_Mid_Route;}}///////第一行没有数据,利用以后行进行补if(!Row_Attribute[ROW-1]||!Row_Attribute[ROW-2]){for(t=ROW-1;t>0;t--)if(Row_Attribute[t]){temp0=t;break;}for(t=temp0;t<ROW;t++){Middle[t+1]=Middle[t];Row_Attribute[t+1]=1;//认为它找到了左,右黑线}}//////////中间有行丢失,用前一行补充,其实这里也可用线性插值法补充,但二者影响不大if(Row_Attribute[ROW-1]==0)Middle[ROW-1]=MID_COLUMN;for(t=ROW-2;t>0;t--)if(Row_Attribute[t]==0) {Middle[t]=Middle[t+1];Row_Attribute[t]=1;}/////////////给Image_Data赋值for(row=0;row<ROW;row++) {// if(Row_Attribute[row])Image_Data[row][Middle[row]]=0;}}// end of Image_Operates//舵机方向控制void SteeringCtl_PD() //我这里先用位置式PD调节{int i=0;int SteerSum=0;{ LeftLED=RightLED=0;error[0]=error[1];for(i=35;i>=16;i--) //仅对近处的20行取平均值 SteerSum+=Middle[i]-COLUMN/2;error[1]=(int)(SteerSum/20);SteerDelta=Kp*error[1]+Kd*(error[1]-error[0]); if(SteerDelta<0){LeftLED=1;RightLED=0;}if(SteerDelta>0){RightLED=1;LeftLED=0;}if(SteerDelta>SteerRightLimit)//防止舵机抱死PWMDTY0=50+SteerRightLimit;else if(SteerDelta<SteerLeftLimit)PWMDTY0=50+SteerLeftLimit;elsePWMDTY0=50+SteerDelta;}steer_dire_label=PWMDTY0;}//马达速度控制/************************************************//** 对采集的前20行处理,用来控制马达速度 *//*********************************************/void MotorSpeedCtl(){int Sum=0;int i=0;int Front_Black_Line_Warp=0;SlowDownLED=SpeedUpLED=0;//对前20行处理,判断是弯道,S弯等,用以控制电机速度//对黑直线上下界限制for(i=10;i<30;i++)Front_Black_Line_Warp+=(Middle[i]-COLUMN/2);//取远处黑线与"黑直线"之间的偏差值if(Front_Black_Line_Warp<0)Front_Black_Line_Warp=-Front_Black_Line_Warp; //我们现在要的只是它偏离的绝对值Speed=(int)(MotorSpeed_Factor*500/((Front_Black_Line_Warp)*(Front_Black_Line_ Warp)));if(Speed<=LowSpeedLimit)//速度上下界限制PWMDTY2=LowSpeedLimit;else if(Speed>=HighSpeedLimit)PWMDTY2=HighSpeedLimit;elsePWMDTY2=Speed;PreSpeed=Speed;}/***************************************************** 函数名称: All_Init** 功能描述: 初始化函数** 说明:****************************************************/ void All_Init(void){PLL_Init();SCI0_Init();TIM_Init();IO_Init();PWM_Init();}/*************************************************** ** 函数名称: main** 功能描述: 主函数** 说明:****************************************************/ void main(void){DisableInterrupts;All_Init();EnableInterrupts;for(;;){}}//---------------------中断定义---------------------#pragma CODE_SEG NON_BANKED/**************************************************** 函数名称: 中断处理函数** 功能描述: 行中断处理函数** 输入: 无** 输出: 无** 说明: TIME0 上升沿,这里从第57行每3行采集一次,一直到第204行,一共采50行***************************************************/interrupt 8 void IC0_ISR(void){TFLG1_C0F =1; //清行中断m++;if(m==HS_Data[HS_Pointer]){Data_collect();HS_Pointer++;//指向行数的数组指针也加1Line_C++;//图像数组行数也加1}else{Line_Flag=1;return;}//end if}/**************************************************** 函数名称: 中断处理函数** 功能描述: 场中断处理函数** 输入: 无** 输出: 无** 说明: TIME1 下降沿***************************************************/ interrupt 9 void IC1_ISR(void){int ThresholdCount=0;int i=0;TIE=0X00;m=0;//每次行数都清0TFLG1_C1F =1; //清场中断TFLG1_C0F = 1; //清行中断Line_C = 0; //行计数器HS_Pointer=0;//行数计数器为0if(Line_Flag==1){Line_Flag=0;Image_Operates();SteeringCtl_PD();//舵机方向处理// MotorSpeedCtl();//图像发送://下面发送命令字:0 255 1 0SCI0_Transmit(0X00);SCI0_Transmit(0Xff);SCI0_Transmit(0X01);SCI0_Transmit(0X00);//紧接着发送数据for(row=0;row<ROW;row++){for(column=0;column<COLUMN;column++){SCI0_Transmit(Image_Data[row][column]); //SCI传送}}// */}//end if//下面这个对左右数组初始化是相当有有必要的,如果不初始化,黑线提取很不稳定,我试过多次验证的TIE=0X03;//open interrupt}#pragma CODE_SEG DEFAULT////////////////////////下面是一些想加入还未加的思路/* Row_Label=ROW-3;while(Row_Label>0){Dashed_Start=Dashed_End=0;for(t=Row_Label;t>1;t--){if(Row_Attribute [t]&&!Row_Attribute [t-1])//本行有黑线,但下一行没黑线Dashed_Start=t;if(Dashed_Start&&!Row_Attribute [t]&&Row_Attribute [t-1]){Dashed_End=t-1;break;}}// end for(t=1;t<ROW-10;i++)//对虚线开始点和结束点进行判断和修正for(t=Dashed_Start-1;t>Dashed_End;t--)//一次线性插值算法Middle[t]=Middle[Dashed_Start]+(int)((Middle[Dashed_End]-Middle[Dashed_Start])*(t-Dashed_Start)/(Dashed_End-Dashed_Start)); Row_Label=Dashed_End-1;}//end of while(Row_Label<ROW)*//*******************************************************/ /***************提取中间黑线****************************/ /*******************************************************/ /*void GetBlackLine(){unsigned char Temp_Mid_Route;int t,temp0;char Row_Label;char Dashed_Start,Dashed_End;//扫描起始点,扫描终止点////////把只有左黑线或右黑线的所在行补其另一黑线for(t=ROW-1;t>=0;t--){if(Row_Attribute[t]==2)//只有左行{Temp_Mid_Route=(int)(15+Mid_Route_Width_Factor*temp0);Right[t]=Left[t]+2*Temp_Mid_Route;Middle[t]=Left[t]+Temp_Mid_Route;}else if(Row_Attribute[t]==3)//只有右行{Temp_Mid_Route=(int)(15+Mid_Route_Width_Factor*temp0);Left[t]=Right[t]-2*Temp_Mid_Route;Middle[t]=Right[t]-Temp_Mid_Route;}}///////第一行没有数据if(!Row_Attribute[ROW-1]||!Row_Attribute[ROW-2]){for(t=ROW-1;t>0;t--)if(Row_Attribute[t]){temp0=t;break;}if(Row_Attribute[temp0]==1)for(t=temp0;t<ROW;t++){Middle[t+1]=Middle[t];Row_Attribute[t+1]=1;//也认为它找到了左,右黑线}else if(Row_Attribute[temp0]==2)// temp0行也仅仅找到左黑线{Temp_Mid_Route=(int)(15+Mid_Route_Width_Factor*temp0);//算出赛道半宽Middle[temp0]=Left[temp0]+Temp_Mid_Route;//对这行中线进行修正for(t=temp0;t<ROW;t++){Middle[t+1]=Middle[t];Row_Attribute[t+1]=2;//也认为它只找到了左黑线}}else if(Row_Attribute[temp0]==3)// temp0行也仅仅找到右黑线{Temp_Mid_Route=(int)(15+Mid_Route_Width_Factor*temp0);//算出赛道半宽Middle[temp0]=Right[temp0]-Temp_Mid_Route;//对这行中线进行修正for(t=temp0;t<ROW;t++){Middle[t+1]=Middle[t];Row_Attribute[t+1]=3;//也认为它只找到了右黑线}}}//end if(!Row_Attribute[0]||!Row_Attribute[1])////////////////////中间有丢行的/* Row_Label=ROW-3;while(Row_Label>0){Dashed_Start=Dashed_End=0;for(t=Row_Label;t>0;t--){if(Row_Attribute [t]&&!Row_Attribute [t+1])//本行有黑线,但下一行没黑线 Dashed_Start=t;if(Dashed_Start&&!Row_Attribute [t]&&Row_Attribute [t+1]){Dashed_End=t+1;break;}}// end for(t=1;t<ROW-10;i++)//对虚线开始点和结束点进行判断和修正Temp_Mid_Route=(int)(35-0.41*Dashed_Start);//算出赛道半宽if(Row_Attribute[Dashed_Start]==2)// 虚线断点开始行也仅仅找到左黑线Middle[Dashed_Start]=Left[Dashed_Start]+Temp_Mid_Route;//对这行中线进行修正else if(Row_Attribute[Dashed_Start]==3)// temp0行也仅仅找到右黑线Middle[Dashed_Start]=Right[Dashed_Start]-Temp_Mid_Route;//对这行中线进行修正Temp_Mid_Route=(int)(35-0.41*Dashed_End);//算出赛道半宽if(Row_Attribute[Dashed_End]==2)// 虚线断点开始行也仅仅找到左黑线Middle[Dashed_End]=Left[Dashed_End]+Temp_Mid_Route;//对这行中线进行修正else if(Row_Attribute[Dashed_End]==3)// temp0行也仅仅找到右黑线Middle[Dashed_End]=Right[Dashed_End]-Temp_Mid_Route;//对这行中线进行修正for(t=Dashed_Start;t<=Dashed_End;t++)//一次线性插值算法Middle[t]=Middle[Dashed_Start]+(int)((Middle[Dashed_End]-Middle[Dashed_Start])*(t-Dashed_Start)/(Dashed_End-Dashed_Start));Row_Label=Dashed_End+1;}//end of while(Row_Label<ROW)} */。

相关文档
最新文档