【飞思卡尔】飞思卡尔摄像头算法基本方法

飞思卡尔摄像头算法

1.接脚说明以及与程序的关系

在这里插入图片描述

  1. 左边八个引脚与单片机IO口相连,在某一个时刻,并行向单片机发送八个数据 数值为(0-255)代表某一个点的灰度值
  2. VS脚 HR脚和CLK脚 其中在摄像头向单片机要发送一张图像时 VS会给一个高脉冲 来表示第一个信号的开始 HR表示行信号 在一张图像的信息传递过程中 会有60个高脉冲来表示60个行(不需要接线) 而CLK表示点信号在每两个HR脉冲之间会有80个高脉冲来表示80个点。这样的话总共有60x80共4800个点 可以通过中断读取VS和CLK来依次获取每个点。

在这里插入图片描述

  1. DMA模块+外部中断结合,自动读取摄像头数据

    unsigned char image[4800];//图像数组
    

2.双峰法二值化

  1. 这个算法是通过统计4800个点中不同灰度的数量 获取在第一高峰和第二高峰的峰谷灰度来作为阈值进行二值化

    如图上的120就是通过该算法获取的阈值

在这里插入图片描述

  1. 统计直方图
int i;
unsigned char YUZHI;//阈值
unsigned int huidu[256] = {0};//灰度直方图数组

for(i=0;i<256;i++)
{
    huidu[image[i]]++;//统计灰度直方图 
}
  1. 寻找第一和第二高峰以及阈值
/*第一高峰*/
unsigned int H1 = 0;//第一高峰海拔值
unsigned char D1;   //第一高峰位置

for(i=0;i<255;i++)
{
    if(huidu[i]>H1)
    {
        H1 = huidu[i];//记录海拔
        D1 = i;       //记录位置
    }
}
/*第二高峰*/
unsigned int H2 = 0;//第二高峰海拔值
unsigned char D2;   //第二高峰位置

for(i=0;i<255;i++)
{
    if(i==D1) continue;//跳过第一高峰
    if(huidu[i]==H1) continue;//排除第一高峰有相同的可能性(是平的)
    if(huidu[i]>H1)
    {
        H2 = huidu[i];//记录海拔
        D2 = i;       //记录位置
    }
}
/*找山谷*/
unsigned int H3 = 4800;//山谷海拔值
unsigned char D3;   //山谷位置

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;
  1. 图像二值化
unsigned char image1[60][80];//二维图像临时处理数组1
unsigned char image2[60][80];//二维图像临时处理数组2

for(i=0;i<4800;i++)
{
    image1[i/80][i%80] = image[i]>YUZHI?1:0;//1表示黑色 0表示白色
}

3.找中线

  1. 主要算法思路是每一行中分别从中间向左向右找上升沿 然后将左右的值相加除于2所得的到的值 作为该行的中线

在这里插入图片描述

  1. 程序找中线
unsigned char ZHONGJIAN[60] = {39};//中线位置
unsigned char ZUO;
unsigned char YOU;

for(i=59;i>=0;i--)
{
    for(j=39;j>0;j++)//从中间向左找
    {
        if(image1[i][j-1]-image1[i][j]==1)//找到上升沿
            ZUO = j;
    }
    for(j=39;j<79;j++)//从中间向右找
    {
        if(image1[i][j+1]-image1[i][j]==1)//找到上升沿
            YOU = j;
    }
    ZHONGJIAN[i] = (ZUO + YOU) / 2;
}

4.求车身偏差

  1. 前瞻偏差:由于在求车身的偏差时没必要比较太远的值 只需要根据真实情况设计一个前瞻 通过选取不同倍前瞻的三个点作为参考来得到车身的偏差

在这里插入图片描述

可以分析这三个点的坐标 来找到由这三点构成的园的曲率(具体实现方式为连接近中和远中两条线段 可以分别获得该两条线段两条垂直平分线 则焦点即是圆心 就由圆心坐标和其中一点坐标得到园的半径即可得到曲率)程序较为复杂 下面可作为一个参考程序

  1. 由于理想情况下 车本身应该沿着中线走 所以可以根据此来推出车本身的横向偏差 例如当车在现实中间线左侧 从摄像头图像算出的中间线应该相对于真正的中间线右偏,车在右侧同理左偏。
unsigned char QIANZHAN = 15;//摄像头前瞻
unsigned char YUAN,ZHONG,JIN;

char ERR_QIAN;//前瞻偏差
char ERR_CHE;//车横向偏差

JIN = ZHONGJIN[59];
ZHONG = ZHONGJIN[59-QIANZHAN];
YUAN = ZHONGJIN[59-QIANZHAN*2];
if((YUAN<ZHONG&&ZHONG>=JIN)||(YUAN>=ZHONG&&ZHONG<JIN))
{
    ERR_QIAN = JIN - ZHONG;
}
else
{
    ERR_QIAN = ((ZHONG - YUAN) + (JIN - ZHONG)) / 2;
}

ERR_CHE = JIN - 39;//获取车身横向偏差

5.方向PD控制

#define DUOJI_ZHONGZHI 2250 //前轮舵机正方向占空比
float KP_QIAN = 1.0;//方向前瞻控制比例系数
float KD_QIAN = 1.0;//方向前瞻控制微分系数
float KP_CHE = 1.0;//方向横向控制比例系数
float GYRO_Z;//车身Z轴角加速度
unsigned int DUOJI_PWM;

GYRO_Z = GET_GYRO(Z);//获取Z轴角加速度 函数未定义
DUOJI_PWM = DUOJI_ZHONGZHI + KP_QIAN * ERR_QIAN + KD_QIAN * GYRO_Z + KP_CHE * ERR_CHE;//参数计算
PWM_OUT(DUOJI_PWM);
  

原视频连接

  • 16
    点赞
  • 118
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值