首页 > 其他分享 >福州大学第19届206智能车队摄像头培训 二、差比和

福州大学第19届206智能车队摄像头培训 二、差比和

时间:2024-09-03 10:08:16浏览次数:7  
标签:206 19 void uint8 MT9V03X track 差比 col

原文于2023.10.25发布于本人CSDN主页,现同步至cnblogs

1 普通二值化的缺点

当场地光线不均时,基础的固定阈值二值化无法适应光线的变化。此外,对大量与道路无关的像素点进行二值化处理会造成算力的浪费。

2 使用差比和

对于MT9V03X拍摄的画面,其由0-255级灰度的像素点组成。二值化的思路是把浅色的前景部分变为255(白色),深色的背景部分变为0(黑色),所有255与0的分界线便是提取的道路边线。
那么使用差比和,则无需对图像进行变化,而是直接辨识浅色部分与深色部分的交界处。
关于差比和的原理,可参考视频:
18届智能车软件培训之差和比扫线

可以直接使用差比和,也可以先进行其他处理后再使用差比和。
参考代码如下:

Main.c

#include "zf_common_headfile.h"
#include "camera.h"
#include "screen.h"
#include "track.h"
#pragma section all "cpu0_dsram"
#define IPS200_TYPE     (IPS200_TYPE_SPI) 

int core0_main(void)
{
    clock_init();                   // 获取时钟频率<务必保留>
    debug_init();                   // 初始化默认调试串口
    //外设初始化代码
    ips200_init(IPS200_TYPE);
    ips200_show_string(0, 0, "mt9v03x init.");
    while(1)
    {
        if(mt9v03x_init())
            ips200_show_string(0, 80, "mt9v03x reinit.");
        else
            break;
        system_delay_ms(500);                                                   // 短延时快速闪灯表示异常
    }
    ips200_show_string(0, 16, "init success.");
    //外设初始化代码
	cpu_wait_event_ready();         // 等待所有核心初始化完毕
	while (TRUE)
	{
        //循环执行的代码
        if(mt9v03x_finish_flag)
        {
            image_boundary_process();
            switch_trackline();
            show_line();
            ips200_show_uint(0, 200, leftline_num, 3);
            ips200_show_uint(0, 216, rightline_num, 3);
            ips200_displayimage03x((const uint8 *)mt9v03x_image, MT9V03X_W, MT9V03X_H);   // 显示原始图像
            //ips200_show_gray_image(0, 188, (const uint8 *)mt9v03x_image, MT9V03X_W, MT9V03X_H, 240, 180, 64);     // 显示二值化图像
            mt9v03x_finish_flag = 0;
        }
        //循环执行的代码
	}
}
#pragma section all restore

camera.c

/*
 * camera.c
 *
 *  Created on: 2023年10月24日
 *      Author: lychee
 */
#include "camera.h"
int16 centerline[MT9V03X_H];
int16 leftline[MT9V03X_H];
int16 rightline[MT9V03X_H];
uint8 leftline_num;//左线点数量
uint8 rightline_num;//右线点数量
int16 sar_thre = 17;//差比和阈值
uint8 pix_per_meter = 20;//每米的像素数

//逐行寻找边界点
void image_boundary_process(void){
    uint8 row;//行
    //uint8 col = MT9V03X_W/2;//列
    uint8 start_col = MT9V03X_W / 2;//各行起点的列坐标,默认为MT9V03X_W / 2
    //清零之前的计数
    leftline_num = 0;
    rightline_num = 0;

    for(row = MT9V03X_H - 1; row >= 1; row--){
        //选用上一行的中点作为下一行计算起始点,节省速度,同时防止弯道的左右两边均出现与画面一侧
        if(row != MT9V03X_H - 1){
            start_col = (uint8)(0.4 * centerline[row] + 0.3 * start_col + 0.1 * MT9V03X_W);//一阶低通滤波,防止出现噪点影响下一行的起始点
        }
        else if(row == MT9V03X_H - 1){
            start_col = MT9V03X_W / 2;
        }
        //逐行作差比和
        difsum_left(row,start_col);
        difsum_right(row,start_col);
        centerline[row] = 0.5 * (rightline[row] + leftline[row]);
    }
}
//差比和寻找左侧边界点
void difsum_left(uint8 y,uint8 x){
    float sum,dif,sar;//和,差,比
    uint8 col;//列
    uint8 mov = 2;//每次作差后的移动量,默认为2,可以根据画面分辨率调整
    //计算第x行的左边界
    leftline[y] = 0;//未找到左边界时输出为0
    for(col = x; col >= mov + 1; col -= mov){
        dif = (float)((mt9v03x_image[y][col] - mt9v03x_image[y][col - mov - 1])<<8);//左移8位即乘256,可避免浮点数乘,加快速度
        sum = (float)((mt9v03x_image[y][col] + mt9v03x_image[y][col - mov - 1]));
        sar = fabs(dif / sum);//求取差比和
        if(sar > sar_thre){//差比和大于阈值代表深浅色突变
            leftline[y] = (int16)(col - mov);
            leftline_num ++;//左线点计数+
            break;//找到边界后退出
        }
    }
}
//差比和寻找右侧边界点
void difsum_right(uint8 y,uint8 x){
    float sum,dif,sar;//和,差,比
    uint8 col;//列
    uint8 mov = 2;//每次作差后的移动量,默认为2,可以根据画面分辨率调整
    //计算第x行的左边界
    rightline[y] = MT9V03X_W - 1;//未找到右边界时输出为187
    for(col = x; col <= MT9V03X_W - mov - 1; col += mov){
        dif = (float)((mt9v03x_image[y][col] - mt9v03x_image[y][col + mov + 1])<<8);//左移8位即乘256,可避免浮点数乘,加快速度
        sum = (float)((mt9v03x_image[y][col] + mt9v03x_image[y][col + mov + 1]));
        sar = fabs(dif / sum);//求取差比和
        if(sar > sar_thre){//差比和大于阈值代表深浅色突变
            rightline[y] = (int16)(col + mov);
            rightline_num ++;//右线点计数+
            break;//找到边界后退出
        }
    }
}

camera.h

/*
 * camera.h
 *
 *  Created on: 2023年10月24日
 *      Author: lychee
 */

#ifndef CODE_CAMERA_H_
#define CODE_CAMERA_H_
#include "zf_common_headfile.h"
#include "track.h"

extern int16 centerline[MT9V03X_H];
extern int16 leftline[MT9V03X_H];
extern int16 rightline[MT9V03X_H];
extern uint8 leftline_num;//左线点数量
extern uint8 rightline_num;//右线点数量
extern int16 sar_thre;//差比和阈值
extern uint8 pix_per_meter;//每米的像素数

void image_boundary_process(void);
void difsum_left(uint8 y,uint8 x);
void difsum_right(uint8 y,uint8 x);
#endif /* CODE_CAMERA_H_ */

track.c

/*
 * track.c
 *  Created on: 2023年10月24日
 *      Author: lychee
 */
#include "track.h"

int16 trackline[MT9V03X_H];//跟踪线
enum track_type_e track_type = TRACK_MID;//默认循中线
//将边线赋值给循迹跟踪线
void switch_trackline(void){
    if(track_type == TRACK_MID){
        for(int i = 0; i < MT9V03X_H;i ++){
            trackline[i] = centerline[i];//循中线
        }
    }
    if(track_type == TRACK_LEFT){
        for(int i = 0; i < MT9V03X_H;i ++){
            trackline[i] = (leftline[i] + pix_per_meter) > 187 ? 187 : (int16)(leftline[i] + 0.2 * pix_per_meter);//循左线,左线应向右侧偏移道路宽度一半,即0.2米对应的像素数
        }
    }
    if(track_type == TRACK_RIGHT){
        for(int i = 0; i < MT9V03X_H;i ++){
            trackline[i] = ((rightline[i]) - pix_per_meter) < 0 ? 0 : (int16)(rightline[i] - 0.2 * pix_per_meter);//循左线,右线应向左侧偏移
        }
    }
}
//选择如何循线,大家可以自由发挥
void choose_tracktype(void){
    //track_type = TRACK_LEFT;
}

track.h

/*
 * track.h
 *
 *  Created on: 2023年10月24日
 *      Author: lychee
 */

#ifndef CODE_TRACK_H_
#define CODE_TRACK_H_
#include "zf_common_headfile.h"
#include "camera.h"

extern int16 trackline[MT9V03X_H];
//定义巡线模式枚举类型
enum track_type_e {
    TRACK_LEFT,//沿左边线
    TRACK_RIGHT,//沿右边线
    TRACK_MID,//沿中线
};
//定义当前循线模式
extern enum track_type_e track_type;

void switch_trackline(void);
void choose_tracktype(void);

#endif /* CODE_TRACK_H_ */

screen.c

/*
 * screen.c
 *
 *  Created on: 2023年10月24日
 *      Author: lychee
 */
#include "screen.h"

void show_line(void){
    for(uint16 i = 0; i < MT9V03X_H; i = i + 2){
        ips200_draw_point((uint16)trackline[i], i, RGB565_BLACK);//黑色跟踪
    }
    for(uint16 i = 0; i < MT9V03X_H; i ++){
        ips200_draw_point((uint16)leftline[i], i, RGB565_RED);//红色左线
        ips200_draw_point((uint16)rightline[i], i, RGB565_BLUE);//蓝色右线
        ips200_draw_point((uint16)centerline[i], i, RGB565_PURPLE);//紫色中线
    }
}

screen.h

/*
 * screen.h
 *
 *  Created on: 2023年10月24日
 *      Author: lychee
 */

#ifndef CODE_SCREEN_H_
#define CODE_SCREEN_H_

#include "zf_common_headfile.h"
#include "camera.h"
#include "track.h"

void show_line(void);

#endif /* CODE_SCREEN_H_ */

在这里插入图片描述
测试效果如上图,可见在左右两侧亮度相差较大的情况下,仍可正常寻线。

3 差比和的优缺点

差和比的计算只与灰度值的对比度有关,无关灰度值本身的大小,在不同光线情况下的适应能力更强。计算至边界点时退出循环,可避免在背景像素中浪费时间进行计算。
差比和仍需对每个前景像素进行计算,仍会造成一定浪费,寻线策略有待进一步优化。

标签:206,19,void,uint8,MT9V03X,track,差比,col
From: https://www.cnblogs.com/DiscreteWind/p/18393972

相关文章

  • 福州大学第19届206智能车队摄像头培训 一、MT9V03X使用
    原文于2023.10.23发布于本人CSDN账号,现同步至博客园1 选择合适的镜头与摄像头安装方式镜头焦距:上图为16mm等效焦距镜头(110°视场角)画面,下图为25mm等效焦距镜头(75°视场角)画面。镜头的视场角越大,可看见的道路范围越大,但画面中也会产生更多的干扰。镜头的视场角越小,画面干扰......
  • 洛谷 P4819 杀人游戏
    洛谷P4819杀人游戏题意有\(n\)个人,他们之中有一个杀手。每个人都有可能是杀手,并且概率相等。你可以询问若干人。若询问的人是杀手,你会被干掉。若询问的人是平民,你会知道他认识的所有人的身份。给出一张有向图表示这\(n\)个人的关系。求出你活着知道杀手是谁的概率。......
  • 力扣第198题 打家劫舍
    前言记录一下刷题历程力扣第198题打家劫舍打家劫舍原题目:你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个......
  • CF 1994 C. Hungry Games (*1600) 思维+二分
    CF1994C.HungryGames(*1600)思维+二分题目链接题意:给你一个长度为\(n\)的关卡,和一个正整数\(x\),初始分数为\(0\),通过每个关卡就会获得对应的分数。但是分数如果超过\(x\),就会清零。现在让你求出满足最终得分不为零的所有子区间数量。思路:正难则反,改求最终得分为......
  • CF1948D
    CF1948D链接:Problem-1948D-Codeforces题目大意:给你一个字符串,字符串由小写字母和?组成,?可以变成任何数,问你重复子字符串的最大长度定义重复子字符串为,任意i都满足s[i]=s[i+len]的子字符串思路:枚举长度,然后对于每个长度,写一个f表表示是否可以喝i+len处对......
  • 【办公类-19-01-04】统计孩子中2班名字的同音字(读音、汉字)
    背景需求:开学第一天,听搭档和阿姨叫孩子的名字,感觉孩子中间有很多同音字。为了更好的掌握重复率,我用以前做的几个代码,再次检索班级幼儿的姓氏字同字率、姓氏字同音率,名字同字率、名字同音率。【办公类-19-01-03】办公中的思考——Python,统计孩子名字的同音字(拼音)_python......
  • 《黑神话:悟空》193+MOD整合包,画质、性能、武器、人物替换、CT表、存档等
    全网收集整理了如下整合包内容,包含《黑神话:悟空》全成就解锁存档锐化补丁、低性能卡顿、画质补丁Xbox手柄图标替换为NsPro图标物品掉落MOD大地图MOD等。下载地址:点击进入如图所示: 以下应该是全网最全《黑神话:悟空》MOD了,一个99+,我罗列一下吧荒野大镖客2斧头替换金......
  • CF1998E2 Eliminating Balls With Merging (Hard Version)
    原题链接考虑对于每个\(i\),算出向左扩展到\(1\)时向右至少和至多扩展到哪里,记为\(minr\)和\(maxr\)。那么也就是说每个\(i\)会对\(minr\simmaxr\)做出贡献,差分一下就可以了。重点是怎么计算这两个东西。先说\(maxr\)。如果暴力跳,过程是:先向左扩展直到不能扩展,然后......
  • 【Oracle点滴积累】Oracle 19c安装Critical Patch Update for January 2024
    广告位招租!知识无价,人有情,无偿分享知识,希望本条信息对你有用!今天和大家分享如何为Oracle19c(未启用RMAN的单实例)安装CriticalPatchUpdate(PatchNumber:35943157),本指引不包含RollBack部分,本文仅供参考,谢谢!cd/home/oracle/NewVersion_Opatch/OPatch/./opatchversio......
  • P3193 [HNOI2008] GT考试 解题报告
    题目传送门题目大意:给定一个长度为\(m\)且只含\(0\sim9\)的字符串\(s\),求出所有长度为\(n\)的,只含\(0\sim9\)且不含\(s\)字符串的数量,结果对\(mod\)取模。数据范围:\(n\le10^9,m\le20,k\le1000\)。思路:不难发现和这道题很像,只是\(n\)的数据范围被扩大到......