智能车双车组——后车识别

        后车规定采用红外摄像头追踪前车红外灯板(两个横置红外光源,左边一个,右边一个),本文旨在为基础识别提供思路和介绍,用于个人复盘,代码仅供参考,参考逐飞和龙邱思路,可关注两家微信公众号。

偏差的计算 

        采用获取图像中所有白色像素点平均坐标的方法。具体来说,先统计出这些白色像素的平均坐标值,然后将该平均坐标的 x 轴数值与图像中点的 x 轴坐标值进行差值运算,所得结果即为后车相对于前车的横向偏差。 

距离的计算

         对于后车与前车之间距离的计算,借助图像中所有白色像素点的方差来实现。实际情况中,车辆间距的变化会直接影响到前车 LED 灯光斑在图像中的呈现效果。当两车距离较远时,光斑在图像中显示较小,同时两个光斑之间的间距也更近,这种情况下图像中白色像素点的分布更为集中,进而导致方差较小;反之同理。通过对白色像素点方差的计算与分析,能够有效获取两车之间的距离信息。

分析左边光源,得出左上角和右下角坐标;分析右边光源,得出左下角和右上角坐标。取平均得左右光源中心位置。。。。。

备注:采用逐飞mt9v03x库,和龙邱神眼摄像头,

#define LIMIT  0

uint8_t threshold_value =80;                        //黑白区分阈值
uint8_t image_deal[MT9V03X_H][MT9V03X_W];           //MT9V03X摄像头读取图像范围

uint8_t point1[2][2], point2[2][2],  centre[2][2];  //存储光源1,2和图像中心坐标值

uint8_t point1_flag = 0;
// 0: 未发现第一个点的左上角
// 1: 发现第一个点的左上角
// 2: 发下第一个点的右下角
uint8_t point2_flag = 0;
// 0: 未发现第二个点的左下角
// 1: 发现第二个点的左下角
// 2: 发下第二个点的右上角
extern uint8_t protect_flag;    //保护标志,1为开启保护,0为关闭保护
uint8_t Deal_succeed_count = 0; //对正确处理图像计数 当正确处理图像超100次时退出该状态

void Image_process_calculate(float *x_error,float *y_reeor)
{
    Image_filter(threshold_value);
    uint8_t Y =0,X=0;
    float value1 = 0,value2 = 0;
    if( (point1_flag == 0 && point2_flag == 1) || 
        (point1_flag == 0 && point2_flag == 0) || 
        (point1_flag == 1 && point2_flag == 0))       //寻找点1的左上角和点2的左下角
    { for(Y =0;Y< MT9V03X_H  ;Y++)
      { for(X = 0;X< MT9V03X_W  ;X++)
        {   if(point1_flag == 0)//寻找第一个点的左上角
            { 
              value1 = Image_process_deal_point1(X,Y);
              if(value1 > LIMIT ){ point1[0][0] = X; point1[0][1] = Y; point1_flag  = 1;}
            }
            if(point2_flag == 0)//寻找第二个点的左下角
            { 
              value2 = Image_process_deal_point2(X,Y);
              if(value2 > LIMIT )
              { 
                  point2[0][0] = X;  point2[0][1] =  MT9V03X_H - Y - 1; point2_flag  = 1; 
              }
            }
            if(point1_flag == 1 &&  point2_flag == 1) break;
         }
            if(point1_flag == 1 &&  point2_flag == 1) break;
      }
    }
    if( (point1_flag == 1 && point2_flag == 1) || 
        (point1_flag == 1 && point2_flag == 2) || 
        (point1_flag == 2 && point2_flag == 1))//寻找点1的右下角和点2的右上角
    {
       for(Y = ( point2[0][1] +  point1[0][1])/2 ; Y< MT9V03X_H   ; Y++)
       {
           for( X = MT9V03X_W-1; X>0 ;X-- )
           {
               if(point1_flag == 1)
               { value1 = Image_process_deal_point1_right(X,Y);
                 if(value1 > LIMIT ){ 
                    point1[1][0] = X; 
                    point1[1][1] = ( point2[0][1] +  point1[0][1]) - Y; 
                    point1_flag  = 2;}
               }
               if(point2_flag  == 1)
               { 
                 value2 = Image_process_deal_point2_right(X,Y);
                 if(value2 > LIMIT ){ point2[1][0] = X; 
                 point2[1][1] = Y; point2_flag  = 2; }
               }
               if(point1_flag == 2 &&  point2_flag == 2) break;
           }
               if(point1_flag == 2 &&  point2_flag == 2) break;
       }
    }

    if(point1_flag == 2 &&  point2_flag == 2)
    {
         Square_centre(point1,&centre[0][0],&centre[0][1]);
         Square_centre(point2,&centre[1][0],&centre[1][1]);
         *y_reeor =  centre[1][1] - centre[0][1];
         *x_error = (centre[0][0] + centre[1][0])/2.0;
         point1_flag = 0;
         point2_flag = 0;
         Deal_succeed_count ++;
         if(Deal_succeed_count > 100)
         {
             if(protect_flag == 1)//退出保护状态
             {
                 protect_flag = 0;
             }
             Deal_succeed_count = 0;
         }
    }else
    {
        protect_flag  = 1;
    }
    //图像识别保护 若经过上述两个过程后
    //point1_flag和 point2_flag 两个都不为2则证明图像丢失这时开启保护位

}

// function : 传入图像的两个对角坐标(x1,y1) (x2,y2),计算中心点坐标(centre_x,centre_y)
// parameter: 两个对角坐标(x1,y1) (x2,y2) 中心点坐标(centre_x,centre_y)指针
// return   : NULL
void Square_centre(uint8_t point[2][2],uint8_t * center_x,uint8_t*centre_y)
{
    *center_x = (point[0][0]*1.0 + point[1][0]*1.0)/2;
    *centre_y = (point[0][1]*1.0 + point[1][1]*1.0)/2;
}


// function : 取绝对值
// parameter: value值
// return   : value的绝对值
float  absolute(float value)
{
    if(value <0)
    {
        value = -value;
    }
    return value;
}

// function : 从图像左上到右下寻找第一个亮点的左上角
// parameter:
// return   :
//    ----------------
//   | ->   **        |
//   |      **        |
//   |                |
//   |                |
//    ----------------
float  Image_process_deal_point1(uint8_t x,uint8_t y)
{
    float value = 0;
    if (x < MT9V03X_W - 1)//防止数组越界
    {
      value = ( image_deal[y][x+1]*1.0 - image_deal[y][x])/
              ( image_deal[y][x+1]*1.0 + image_deal[y][x]);
    }                       //计算相邻两个点的差比和
    value = absolute(value);//取绝对值保障都是正数
    return value;
}

// function : 从图像左下到右上寻找第二个亮点的左下角
// parameter:
// return   :
//    ---------------
//   |                |
//   |      **        |
//   |      **        |
//   | ->             |
//    ---------------
float  Image_process_deal_point2(uint8_t x,uint8_t y)
{
    float value = 0;
    y  = MT9V03X_H - y - 1;
    if (x < MT9V03X_W - 1)//防止数组越界
    {
      value = ( image_deal[y][x+1]*1.0 - image_deal[y][x])/
              ( image_deal[y][x+1]*1.0 + image_deal[y][x]);
    }                       //计算相邻两个点的差比和
    value = absolute(value);//取绝对值保障都是正数
    return value;
}


// function : 从图像左上到右下寻找第一个亮点的右下角
// parameter:
// return   :
//    ----------------
//   |      **        |
//   |      **      <-|
//   |                |
//   |                |
//    ----------------
float  Image_process_deal_point1_right(uint8_t x,uint8_t y)
{
    float value = 0;
    y  = ( point2[0][1] +  point1[0][1]) - y;
    if (x > 0)//防止数组越界
    {
      value = ( image_deal[y][x-1]*1.0 - image_deal[y][x])/
              ( image_deal[y][x-1]*1.0 + image_deal[y][x]);
    }                       //计算相邻两个点的差比和
    value = absolute(value);//取绝对值保障都是正数
    return value;
}

// function : 从图像左下到右上寻找第二个亮点的右上角
// parameter:
// return   :
//    ---------------
//   |               |
//   |               |
//   |      **     <-|
//   |      **       |
//    ---------------
float  Image_process_deal_point2_right(uint8_t x,uint8_t y)
{
    float value = 0;
    if (x > 0)//防止数组越界
    {
      value = ( image_deal[y][x-1]*1.0 - image_deal[y][x])/
              ( image_deal[y][x-1]*1.0 + image_deal[y][x]);
    }                       //计算相邻两个点的差比和
    value = absolute(value);//取绝对值保障都是正数
    return value;
}

// function : 将图像预处理,将外界小光斑滤掉(小于阈值的点的灰度值赋1)
// parameter:  threshold 阈值
// return   :
void Image_filter(uint8_t threshold)
{
      for (uint8_t y = 0; y < MT9V03X_H; y++)
      {
          for (uint8_t x = 0; x < MT9V03X_W; x++)
          {
              if (mt9v03x_image[y][x] >= threshold)
                  image_deal[y][x] = mt9v03x_image[y][x] ;
              else
                  image_deal[y][x] = 1;
          }
      }
}

float cauclate_variance(float average,float num)
{
    float out = 0;
    out = (num - average)*(num - average);
    return out;
}


// function :  将图像预处理,计算图片中所有白色光斑的横坐标的均值和方差
// parameter:  threshold 阈值   Image_x_average 横坐标的均值    variance  横坐标的方差
// return   :
void LQ_Deal_Image(float *Image_x_average, float *variance,uint8_t threshold)
{
    uint16_t  point_x_record[800] = {0}; //存储所有白色光斑点的横向坐标
    uint16_t i = 0,j = 0,point_count = 0;
    float x_sum = 0,variance_sum = 0;
    for(i= 0 ;i < MT9V03X_H;i++)
    {
        for(j= 0 ;j < MT9V03X_W;j++)
        {
               if (mt9v03x_image[i][j] >= threshold )
               {
                   x_sum += j;
                   point_x_record[point_count] = j;
                   point_count ++;
                   if(point_count >= 800)
                   {
                       ips200_show_string(100,120,"ERROR");
                   }
               }
        }
    }

    if(point_count != 0)        //图像中残存的有亮点
    {
        if( protect_flag  == 1) //保护状态机
        {
            Deal_succeed_count ++;
            if(Deal_succeed_count > 50)
            {
                Deal_succeed_count =0;
                protect_flag = 0;
            }
        }
        *Image_x_average= x_sum/point_count;
         for (uint8_t k = 0 ;k < point_count;k++)
         {
            variance_sum += cauclate_variance(*Image_x_average,point_x_record[k]);
         }
         *variance = variance_sum/ point_count;
    }else if(point_count == 0)    //图像光电丢失
    {
        *variance = 0;
        *Image_x_average = 0;
         protect_flag  = 1; //开启保护
    }
}

内容概要:本文档详细介绍了基于直驱永磁同步发电机(PMSG)的1.5MW风力发电系统在Simulink环境下的建模与仿真全过程,涵盖了风力机空气动力学模型、PMSG电磁特性建模、不可控整流与逆变电路、直流环节、空间矢量脉宽调制(SVPWM)技术以及核心控制策略的设计。重点实现了最大功率点跟踪(MPPT)控制以提升风能捕获效率,并构建了电压外环与电流内环协同工作的闭环控制系统,通过仿真验证了系统在不同风速条件下稳定运行的能力及动态响应性能。; 适合人群:适用于具备电力系统、电机控制理论基础及Simulink仿真操作经验的研究生、科研人员和从事新能源发电系统开发的工程技术人员;特别适合正在进行风电系统建模、控制算法研究或完成相关毕业设计的专业人士。; 使用场景及目标:①深入理解直驱式PMSG风力发电系统的整体架构与工作机理;②掌握从物理部件建模到控制策略实现的完整Simulink仿真流程;③学习并复现MPPT控制、闭环控制等关键技术方案;④为后续开展低电压穿越、并网稳定性分析、故障诊断等高级课题提供可靠的仿真平台支撑。; 阅读建议:建议结合Matlab/Simulink软件动手实践,逐模块搭建模型,重点关注各控制环节的参数设计与调试方法,同时可参照文中提供的其他风电相关资源进行拓展学习与对比分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值