智能车数字图像处理算法入门及C语言实现
https://www.bilibili.com/video/BV1eL411L7NR?spm_id_from=333.999.0.0&vd_source=d59d7bc22106d87da35c63b8af6491e8
文章目录
- 图像简单处理附加提升
- 图像二值化
- 数据示例
- 大津阈值法代码实现
- 图像二值化代码实现
- 图像处理
- 找中线代码实现
- 完整实现
- 优化
- 求车身横向偏差
- 方向 PD 控制
图像简单处理附加提升
二值化 - 边缘提取 - 特征识别 - 补线 - 中心巡线 - 偏差曲率计算
图像二值化
0 - 255 >> 0 - 1
1. 固定阈值
最简单,不用
2. 动态阈值
由近向远逐行迭代阈值
3. 大津法
灰度直方图找谷底
数据示例
一行数据:
38 36 40 60 55 78 99 111 114 121 115 120 118 100 110 106 80 60 40 35 42 40 36
二值化:
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0
边缘提取:
0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0
差比和计算偏差
if( (dat[0]-dat[1]/dat[0]+dat[1]) > 斜率阈值) dat[0]=1; dat[1]=1;
大津阈值法代码实现
// DMA 模块+外部中断结合,自动读取摄像头数据
#define pixel_num 4800
uchar image[pixel_num]; // 图像数组 60*80// 大津法二值化
uint huidu[256]={0}; // 灰度直方图数组
uchar YUZHI; // 二值化阈值for(i=0; i<4800; i++) // 遍历所有像素
{huidu[image[i]]++; // 统计灰度直方图
}uint H1=0, H2=0; //第一、第二高峰海拔值
uchar D1=0, D2=0; // 第一、第二高峰位置#define KUAN 30 // 山峰宽度阈值for(i=0; i<256; i++) // 遍历灰度直方图
{if(huidu[i] > H1) // 寻找最大值{H1 = huidu[i]; // 记录海拔D1 = i; // 记录位置}}bit OK = 0; // 是否找到第二高峰
/* 要找的是第二高峰,不是第二高点 */
for(i=H1-5; i>0; i-=5) // 向下切,找第二高峰
{for(j=0; j<256; j++) // 遍历这一行{if(huidu[j] > i && abs(j-D1) > KUAN) // 有上面部分{H2 = i; // 记录第二高峰海拔D2 = j; // 记录第二高峰位置OK = 1; // 标志置位break;}}if(OK) break; // 如果找到,直接跳出
}uint H3=pixel_num; // 山谷海拔值
uchar D3=0; // 山谷位置
if(OK) // 已经找到2座山
{if(D1<D2) // 找山谷{for(i=D1; i<D2; i++){if(huidu[i]<H3) // 寻找最小值{H3 = huidu[i];D3 = i;}}}else{for(i=D2; i<D1; i++){if(huidu[i]<H3){H3 = huidu[i];D3 = i;}}}YUZHI = D3; // 获取阈值
}
图像二值化代码实现
uchar image1[60][80]; // 二维图像临时处理数组1
uchar image2[60][80]; // 二维图像临时处理数组2for(i=0; i<4800; i++)
{if(image[i]>YUZHI) // 判断灰度值{image1[i/80][i%80] = 1; // 白点}else{image1[i/80][i%80] = 0; // 黑点}
}
图像处理
灵魂
通过关键点特征来判断
uchar AX, AY; // A点
uchar BX, BY; // B点
uchar CX, CY; // C点
uchar DX, DY; // D点AY = 59; // 获取 AB 点
BY = 59;
for(i=39; i>=1; i--) // 从中间向左找上升
{if(image1[59][i] - image1[59][i-1] == 1) // 找到上升沿 {AX = i; // A 横坐标}
}for(i=39; i<79; i++) // 从中间向右找上升沿
{if(image1[59][i] - image1[59][i+1] == 1) // 找到上升沿{BX = i; // B 横坐标}
}CY = AY-1; // 迭代 C 点
CX = AX-1; // 去到下一行的边界黑点
for(i=CY; i>0; i--) // 由近及远
{for(j=CX; j<80; j++) // 由左向右{if(image[i][j] == 1) // 找到白点{CX = j-1; // 得到上一行黑点X位置break;}}if(image1[i-1][CX] == 1) // 判断上方是否还有黑点{CY = i; // 得到C点Y位置break;}
}DY = BY-1; // 迭代D点
DX = BX+1; // 得到下面一行黑点
for(i=DY; i>0; i--) // 由近及远
{for(j=DX; j>0; j--){if(image1[i][j] == 1) // 找到白点{DX = j + 1;break;}}if(image1[i-1][DX] == 1){DY = i;break;}
}if(abs(CY-DY)<10) && CY > 30 && DY > 30) // 初级判断十字路口
{uchar Y = min(CY, DY); // 获取CD高度较小值uchar HEI = 0; // 十字路口上方区域黑点数量for(i=Y; i>Y-10; i-=2) // Y抽点轮训{for(j=10; j<70; j+=5) // X抽点轮训{if(image1[i][j] == 0) // 如果有黑点{HEI++; // 计数变量++}}}if(HEI < 10) // 最终判断十字路口,并补线{float K; // 补线斜率K = (CX-AX)/(CY-AY); // 计算AC点斜率for(i=CY; i>CY-20; i--) // 补AC延长2像素宽线{image1[i][CX+(CY-i)*K] = 0; //把图像对应点涂黑image1[i][(CX+(CY-i)*K)-1] = 0;}K = (DX-BX)/(DY-BY); // 计算AC点斜率for(i=DY; i>DY-20; i--) // 补AC延长2像素宽线{image1[i][DX+(DY-i)*K] = 0; //把图像对应点涂黑image1[i][(DX+(DY-i)*K)-1] = 0;}}
}
找中线代码实现
uchar ZHONGXIAN[60] = {39}; // 中线位置
uchar ZUO[60] = {0}; // 左线位置
ucahr YOU[60] = {79}; // 右线位置// 先找最底下一行中心线
for(i=ZHONGXIAN[59]; i>=1; i--) // 从中间向左找上升
{if(image1[59][i] - image1[59][i-1] == 1) // 找到上升沿 {ZUO[59] = i;}
}for(i=ZHONGJIAN[59]; i<79; i++) // 从中间向右找上升沿
{if(image1[59][i] - image1[59][i+1] == 1) // 找到上升沿{YOU[59] = i; // 右线}
}ZHONGJIAN[59] = (ZUO[59] + YOU[59]) /2; // 最底下一行中心线位置找到
完整实现
uchar ZHONGXIAN[60] = {39}; // 中线位置
uchar ZUO[60] = {0}; // 左线位置
ucahr YOU[60] = {79}; // 右线位置for(i=59; i>=0; i--) // 向上迭代中心线 ,从靠近摄像头到远离摄像头
{for(j=ZHONGJIAN[i]; j>=1; j--) // 从中间向左找上升沿{if(image1[i][j] - image1[i][j-1] == 1) // 找到上升沿ZUO[i] = j; // 左线}for(j=ZHONGJIAN[i]; j<79; j++) // 从中间向右找上升沿{if(image1[i][j] - image1[i][j+1] == 1) // 找到上升沿YOU[i] = j; // 右线}ZHONGJIAN[i] = (ZUO[i] + YOU[i]) / 2; // 计算当前行中心点
}
优化
- 大湾
for(j=ZHONGJIAN[i+1]; j<79; j++) // 从中间向右找上升沿
以上一次的中间值为这一行的中值向两侧寻找
避免如下情况,找不到中间值
2. 图像截取
图片拟出来的中点向上应该为白色;否则此时不为赛道。
if(h > 1 && ZHONGJIAN[h-1]==0) // 此时截止
求车身横向偏差
可以通过求曲率,太复杂这里不展示
uchar QIANZHAN = 15; // 摄像头前瞻uchar YUAN, ZHONG, JIN; // 中线所在位置char ERR = 0; // 前瞻偏差char YERR = 0; // 车身横向偏差JIN = ZHONGJIAN[59];ZHONG = ZHONGJIAN[59-QIANZHAN];YUAN = ZHONGJIAN[59-QIANZHAN*2];/* 分情况讨论,右负左正 */if(YUAN<ZHONGJIAN && ZHONG < JIN) // 情况1{ERR = ( (ZHONG - YUAN ) + (JIN - ZHONG) )/2; // 获取前瞻偏差}else if(YUAN < ZHONG && ZHONG >= JIN) // 情况2{ERR = JIN - ZHONG; // 获取前瞻偏差}else if(YUAN >= ZHONG && ZHONG < JIN) // 情况3{ERR = JIN - ZHONG; // 获取前瞻偏差}else{ERR = ( (ZHONG - YUAN ) + (JIN - ZHONG) )/2; // 获取前瞻偏差}YERR = JIN - 39; // 获取车身横向偏差
方向 PD 控制
PID参数随机编撰
float KP = 1.0; // 方向控制前瞻比例系数
float KD = 1.0; // 方向控制前瞻微分系数
float YKP = 1.0; // 方向横向控制比例系数float GYRO_Z; // 车身Z轴角速度#define DUOji_ZHONGZHI 840 // 前轮正方向的舵机占空值uint DUOJI_PWM; // 舵机PWMGET_z = GET_GYRO(Z); // 获取车身Z轴角速度DUOJI_PWM = DUOJI_ZHONGZHI + KP*ERR + YKP*YERR - KD*GYRO_Z; // 舵机参数计算PWM_OUT(DUOJI_PWM); // 控制舵机
智能车数字图像处理算法入门及C语言实现相关推荐
- 第十六届全国大学生智能车| AI视觉组新手入门教程
▌00 整体内容 进入正文前,我们通过下方框图整体了解每个章节的内容,先大概了解每个章节做的工作是什么作用,这样有助于理解每个章节的内容.同学们可以参考以下章节内容训练模型,但这只是一个初级参考,相信 ...
- 第十五届智能车入门浅谈
@TOC第十五届智能车入门浅谈 写博客原因 这次第十五届全国智能车大赛已经结束了,对于我而言,确实是我大学中一个不可多得的经历,我希望我的这段经历可以保存下来通过博客的形式,同时可以对于其他人有帮助, ...
- 第十七届智能车竞赛英飞凌专题培训 ——四轮摄像头组入门讲解
四轮摄像头组,作为走过16年仍然最纯粹的竞速组,充满着速度与激情,既有高手选择该组挑战极限,也是新手最喜欢的传统组,还是最能体现智能汽车竞赛魅力和初心的组别,可以说集万千宠爱于一身啦!每届参加人数 ...
- 智能车技术与实践_ROS入门
智能车技术与实践--ROS入门 前言:本次作业旨在通过不同的任务使同学掌握ROS基础,包括工作环境.功能包的创建. 预先要求:ubuntu18.04 + ROS melodic 任务一:创建ROS工作 ...
- 智能车入门——‘教程引导’ <新手从零做车>
前言 本系列文章是针对 第一次接触智能车 /学校没有传承 不知道 如何上手做智能车 的同学 将这个系列看完,应该就能够 做出正常的 一个低速完赛的电磁车, 如果你是想提速,寻找新的方案,那么这个教 ...
- 智能车阳光算法(含大津法)
** ## 智能车阳光算法 ** 谈不上真正的阳光算法,但是对于一些光干扰的场景和一些有噪点的图像还是可以进行处理. 在之前主流的摄像头主要是ov7725这个摄像头的优点就是硬件二值化,它的处理速度比 ...
- 智能车入门——跑车前的零碎知识<新手从零做车>
17届技术报告 | 杭电四轮电磁一队_卓晴的博客-CSDN博客 建议多看一下一些强校的技术报告 调整舵机中值 装舵机舵盘时,要保证车能够左右打死, 装好舵机后,要调整舵机中值,也就是占空比为何值时车走 ...
- [智能车]平衡车/直立车的入门经验(代码讲解)
做为第十六届智能车的FW,在半年的做车经历中把能踩的坑都踩了个遍.写这篇文章是为了留个纪念,也是为了帮新车友快速入门(可能完全0基础).我自己的经验也不足,所以可能会存在一些漏洞,还请大佬指正. 车模 ...
- 第十七届智能车竞赛英飞凌 | 逐飞联合直播-平衡单车组入门讲解
自平衡.单车.自动驾驶--听起来是不是很像稚晖君的出圈开源项目"我把自行车做成了 自 动 驾 驶 !!".的确,这几个要素放在一起,真有那味道了,虽然车模小了点,更像是电动摩托 ...
最新文章
- 【C++标准库】特殊容器
- 小学计算机课知识点总结,小学计算机教学总结3篇
- 编程学将成为必然趋势,青少年编程,从哪里开始?这里推荐Python
- 在wildfly中使用SAML协议连接keycloak
- 360更新补丁一直提示正在安装_远程利用POC公布|CVE20200796:微软发布SMBv3协议“蠕虫级”漏洞补丁通告...
- 最简单 NDK 样例
- 看完这些美食海报,你是不是又有灵感了?
- 解决jz2440不能ping同主机问题
- Rust 1.34替代Cargo注册表 与crates.io共存
- 工业革命 书_工业革命以来最重大的变化
- Aug.2019_Memory
- 我的大一C++学习笔记
- Google Chrome显示粉红色屏幕
- Linux下校对服务器时间同网络时间一致
- 前端vs图片:0 为什么需要重视图片
- 微信支付不成功的几个原因
- 改造一台可以计算滤芯使用寿命的智能空气净化器——硬件篇
- android最新版下载安装,安卓市场APP2020最新版下载
- 【HTML】HTML5网页作业----模仿京东,模仿站点
- 2016一周年点滴收获总结——遇见Elixir