摄像头基础扫线方法:
(1)每次都从屏幕中线向两侧边缘进行扫线
(2)第一次从屏幕中线开始扫线接下来从上一次中线的位置开始向两侧进行扫线(种子生长)
摄像头扫描到的数据就是一个二维的数组,我用的是逐飞的总转风,库也是逐飞的,是以左上角为原点,向下Y轴递增,向右X轴递增。(如果摄像头安装正常的话),如果安反了,那么就变成以右下角为原点,向上Y轴递增,向左X轴递增的镜像了。后期的各种处理(比如二值化,元素识别等)本质上也都是对数组的处理(可以使一维数组也可以是二维数组,主要看你自己怎么弄了)
下面插入一个大佬的摄像头图像浅谈,里面介绍的就是摄像头的基本工作原理
(26条消息) 智能车浅谈——图像篇_小向是个Der的博客-CSDN博客_智能车图像识别
作为一个刚刚学过的小趴菜,我觉得新手最重要的就是先弄懂摄像头到底是一个什么样的运行原理,后期对元素的判断多种多样,但是根本原理都是相同的,打好基础总没错。
看完上边的链接,相信大家就能明白摄像头到底是一个什么样的工作原理了,接下来直接上我写的代码,直接实战。
for (line = 100; line >= 20; line--) //纵向
{
/*0代表黑色,255代表白色,line代表Y轴上的纵坐标,list为X轴上的横坐标,两个简单的for循环,自己画个图就懂了,接下来的if是个边界的判断,在下一个if是对边界的限制。*/
for (list = old; list < 188 - 2; list++) //向右横向
{
if (mt9v03x_image1[line][list] == 255 &&
mt9v03x_image1[line][list + 1] == 0 &&
mt9v03x_image1[line][list + 2] == 0)
{
rightline[line] = list;
right_flag[line] =1;
break;
}
}
if (list == 188 - 2)
{
right_flag[line] =0;
rightline[line] = 187;//右侧边缘位默认为187,即数组最大位
}
/*与上边的同理*/
for (list = old; list >= 2; list--) //向左横向
{
if (mt9v03x_image1[line][list] == 255 &&
mt9v03x_image1[line][list - 1] == 0 &&
mt9v03x_image1[line][list - 2] == 0)
{
leftline[line] = list;
left_flag[line] = 1
break;
}
}
if (list == 1)
{
left_flag[line] = 0;
leftline[line] = list;
}
road_width[line] = leftline[line] - rightline[line];计算赛道宽度,存放在一个一维数组中
centerline[line] = (rightline[line] + leftline[line]) / 2;,计算中线的位置,存放在一维数组中,,centerline[line] :在第Y=line上中线的X坐标。
old = centerline[line];将上一次的中线位置记入进变量old,下次以其为点进行寻找。
我是从下向上进行扫描,也就是原理原点的那端开始扫描,我的摄像头是120*188的,以20和100位扫线的Y轴界限是为了刨除前20行里可能出现的车头,和后20里可能出现的背景导致的扫线错误,这个值是可以随便改的,根据自己情况定。
我在每一次的向侧边扫线都用了两侧if判断:第一次是判断是否为边界,因为我用了二值化,mt9v03x_image1[][]这个二维数组就是我储存二值化后图像的二维数组。逐飞的库里有一个摄像头采集完成的标志位,采集完成后标志位会置1,采完在进行二值化,搞完你想搞的记得把标志位清零!!!
(26条消息) 【智能车】图像二值化算法--大津法OTSU_Ethan-Code的博客-CSDN博客_大津法二值化
二值化后除了赛道其他的图像都是黑色,只有赛道是白色。
举例:判断赛道左侧边缘
mt9v03x_image1[line][list] == 255 白
mt9v03x_image1[line][list + 1] == 0 黑(向左一位为黑)
mt9v03x_image1[line][list + 2] == 0 黑(向左两位也为黑)
那么我就判断mt9v03x_image1[line][list]这一点为赛道左侧边界
第二个if判断是如果扫不到线就用摄像头的边界值作为边缘线,毕竟不能空着嘛。
摄像头四轮车