香橙派 AIpro上手体验并验证车道线识别算法

news2024/11/18 16:08:14

香橙派 AIpro上手体验并验证车道线识别算法

1.前言

最近入手了一块香橙派AIpro,体验了一下,感觉还不错,在这里分享给大家,大家可以做个参考。

2.开箱

img

整套产品包含一块主板、一个电源插头和一条双端Type-C的数据线,打开盒子可以看到主板,主板前后都有海绵保护,包装得还可以:

img

主板上已经装好了散热器,焊好了天线,这里注意下上电时天线上的导电胶带不要和板子接触,以免造成板子元器件短路:

img

主板侧面有一个Typc-C供电口,两个HDMI显示输出口,中间有个音频接口,再右边是一个Type-C接口,这个Type-C接口只支持USB3.0的设备,也就是说USB2.0和1.0的鼠标或键盘等设备是不能接到这个这个接口的,鼠标和键盘要用右边的两个USB接口。但这个Type-C接口可以接USB3.0的移动硬盘之类设备。最右边还有一个千兆以太网口。

img

板子另一侧有一排40pin的GPIO,两个Key,一个是关机键,一个是重启键。还有两个LED指示灯,靠近关机键的那个LED是电源指示灯,接上电源就亮,左边那个LED可以用程序控制,默认是Linux内核跑起来之后会点亮,系统关闭后熄灭。

img

40pin GPIO的定义如下,包含一路SPI、一路IIC、三路UART和一路PWM输出,其余引脚已经默认配置为GPIO模式,可以直接使用,有复用功能的引脚需要修改 DTS 配置才能作为GPIO使用。

img

下图是主机背面的样子,来的时候带了一张32G内存卡,此外还可以看到两个拨码开关,可以用来选择启动方式,支持SSD、EMMC和SD三种启动方式。

img

其他的还有MIPI摄像头等接口,这里就不一一列举了,需要的话可以再使用手册中查找相关说明。

3.开机

插上电源后自动开机,注意显示器要插到HDMI0接口,也就是靠近USB的那个,目前只有HDMI0支持显示系统桌面。出厂默认安装Ubuntu系统,支持Xface桌面,这默认用户名是HwHiAiUser,默认密码是Mind@123:

img

登录之后,先试一下联网,有线网直接插上就可以自动识别连接,WIFI也可以正常连接,ping一下看是否能正常联网:

img

4.系统自带算法模型

出产时预装的系统中,自带了几个常见的算法模型样例,有目标识别、语音识别等等,是基于JupyterLab做的,具体怎么使用样例可以参考用户手册,这里就不详细展开讲了,我们这里来测试一下第一个目标识别算法样例,首先测试一下图片,图片是样例自带的,结果如下:

img

我们再去网上随便找一张图片试试效果:

img

5.车道线识别算法测试

我们再自己做个小算法测试一下。车道线检测是自动驾驶或辅助驾驶中的一个基本算法,检测到车道线后才可能实现车道偏离预警、车道保持辅助以及更高级别的领航辅助等功能。算法的原理和实现网上都能找到不少资料,这里不再赘述。测试使用的算法代码如下:


blur_ksize = 5  # 高斯模糊核大小
canny_lthreshold = 50  # Canny边缘检测低阈值
canny_hthreshold = 150  # Canny边缘检测高阈值
# 霍夫变换参数
rho = 1     #rho的步长,即直线到图像原点(0,0)点的距离
theta = np.pi / 180     #theta的范围
threshold = 15      #累加器中的值高于它时才认为是一条直线
min_line_length = 40    #线的最短长度,比这个短的都被忽略
max_line_gap = 20      #两条直线之间的最大间隔,小于此值,认为是一条直线

#img是输入的图像,verticess是兴趣区的四个点的坐标(三维的数组)
def roi_mask(img, vertices):
    mask = np.zeros_like(img)   #生成与输入图像相同大小的图像,并使用0填充,图像为黑色
    mask_color = 255
    cv2.fillPoly(mask, vertices, mask_color)    #使用白色填充多边形,形成蒙板
    masked_img = cv2.bitwise_and(img, mask) #img&mask,经过此操作后,兴趣区域以外的部分被蒙住了,只留下兴趣区域的图像
    return masked_img
# 对图像进行画线
def draw_lines(img, lines, color=[255, 255, 0], thickness=2):
    for line in lines:
        for x1, y1, x2, y2 in line:
            cv2.line(img, (x1, y1), (x2, y2), color, thickness)
def hough_lines(img, rho, theta, threshold,
                min_line_len, max_line_gap):
    lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]),
                            minLineLength=min_line_len,
                            maxLineGap=max_line_gap)
    line_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8) #生成绘制直线的绘图板,黑底
    # draw_lines(line_img, lines)
    draw_lanes(line_img, lines)
    return line_img
def draw_lanes(img, lines, color=[255, 255, 0], thickness=8):
    left_lines, right_lines = [], []    #用于存储左边和右边的直线
    for line in lines:      #对直线进行分类
        for x1, y1, x2, y2 in line:
            k = (y2 - y1) / (x2 - x1)
            if k < 0:
                left_lines.append(line)
            else:
                right_lines.append(line)
 
    if (len(left_lines) <= 0 or len(right_lines) <= 0):
        return img
    clean_lines(left_lines, 0.1)    #弹出左侧不满足斜率要求的直线
    clean_lines(right_lines, 0.1)   #弹出右侧不满足斜率要求的直线
    left_points = [(x1, y1) for line in left_lines for x1, y1, x2, y2 in line]  #提取左侧直线族中的所有的第一个点
    left_points = left_points + [(x2, y2) for line in left_lines for x1, y1, x2, y2 in line]    #提取左侧直线族中的所有的第二个点
    right_points = [(x1, y1) for line in right_lines for x1, y1, x2, y2 in line]    #提取右侧直线族中的所有的第一个点
    right_points = right_points + [(x2, y2) for line in right_lines for x1, y1, x2, y2 in line] #提取右侧侧直线族中的所有的第二个点
    left_vtx = calc_lane_vertices(left_points, 325, img.shape[0])   #拟合点集,生成直线表达式,并计算左侧直线在图像中的两个端点的坐标
    right_vtx = calc_lane_vertices(right_points, 325, img.shape[0]) #拟合点集,生成直线表达式,并计算右侧直线在图像中的两个端点的坐标
    cv2.line(img, left_vtx[0], left_vtx[1], color, thickness)   #画出左侧直线
    cv2.line(img, right_vtx[0], right_vtx[1], color, thickness) #画出右侧直线

#将不满足斜率要求的直线弹出
def clean_lines(lines, threshold):
    slope = [(y2 - y1) / (x2 - x1) for line in lines for x1, y1, x2, y2 in line]
    while len(lines) > 0:
        mean = np.mean(slope)   #计算斜率的平均值,因为后面会将直线和斜率值弹出
        diff = [abs(s - mean) for s in slope]    #计算每条直线斜率与平均值的差值
        idx = np.argmax(diff)     #计算差值的最大值的下标
        if diff[idx] > threshold:    #将差值大于阈值的直线弹出
            slope.pop(idx)  #弹出斜率
            lines.pop(idx)  #弹出直线
        else:
            break
#拟合点集,生成直线表达式,并计算直线在图像中的两个端点的坐标
def calc_lane_vertices(point_list, ymin, ymax):
    x = [p[0] for p in point_list]  #提取x
    y = [p[1] for p in point_list]  #提取y
    fit = np.polyfit(y, x, 1)   #用一次多项式x=a*y+b拟合这些点,fit是(a,b)
    fit_fn = np.poly1d(fit) #生成多项式对象a*y+b
    xmin = int(fit_fn(ymin))    #计算这条直线在图像中最左侧的横坐标
    xmax = int(fit_fn(ymax))     #计算这条直线在图像中最右侧的横坐标
    return [(xmin, ymin), (xmax, ymax)]
    
cap = cv2.VideoCapture('lane.jpg')

if (cap.isOpened()):  # 打开成功
    flag = 1
else:
    flag = 0
num = 0
if (flag):
    while (True):
        ret,frame = cap.read() 
        if ret == False:
            break
        plt.imshow(frame)
        gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)  #图像转换为灰度图
        blur_gray = cv2.GaussianBlur(gray, (blur_ksize, blur_ksize), 0, 0)  #使用高斯模糊去噪声
        edges = cv2.Canny(blur_gray, canny_lthreshold, canny_hthreshold)    #使用Canny进行边缘检测
        roi_vtx = np.array([[(0, frame.shape[0]), (460, 325),
                             (520, 325), (frame.shape[1], frame.shape[0])]]) ##目标区域的四个点坐标,roi_vtx是一个三维的数组
        roi_edges = roi_mask(edges, roi_vtx)    #对边缘检测的图像生成图像蒙板,去掉不感兴趣的区域,保留兴趣区
        line_img = hough_lines(roi_edges, rho, theta, threshold,
                               min_line_length, max_line_gap)   #使用霍夫直线检测,并且绘制直线
        res_img = cv2.addWeighted(frame, 0.8, line_img, 1, 0)   #将处理后的图像与原图做融合
        plt.imshow(res_img)

测试使用的输入图片如下:

img

运行后的结果如下图所示,我们可以看到车道线被用黄色线标记了出来:

img

当前只是实现了图片中的车道线检测,后续会继续实现视频中的车道线检测,因为时间的原因目前只能测试这么多,后面会实现更多的算法来进行测试。

6.总结

我其实主业是做MCU的,SOC之前用的并不多,所以这次体验地也比较粗浅,但仍然能感觉到这块开发板对于我这种小白来说是非常容易上手的,拿到手之后就已经给装好了系统,开机即用,官方提供的使用手册也很详细,按照手册很快就能在板子上验证自己的算法。板载接口也很丰富,两个HDMI接口、Type-C、有线网口、无线天线等等一应俱全,可以满足日常使用的绝大部分需求。美中不足的可能是官方系统目前还不能支持双屏桌面输出,期待日后够完善。之前买过一块树莓派,对比下来感觉香橙派AIpro更“亲民”,不只是在价格,更是在一些小的细节上,比如板载的两个标准HDMI接口就比树莓派的两个Mini HDMI更符合我们日常的使用习惯,省去了转接头的麻烦。虽然说目前网上能找到的各种资料还是树莓派相对多一些,但毕竟他们起步早,我们现在也有昇腾社区和论坛,相信在不久的将来国产AI芯片也一定能闯出一片自己的天地!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1720910.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【会议征稿】2024年无人驾驶与智能传感技术国际学术会议(ADIST 2024)

2024年无人驾驶与智能传感技术国际学术会议&#xff08;ADIST 2024&#xff09;将于2024年6月28-30日在珠海召开。ADIST 2024旨在搭建学术资源共享平台&#xff0c;加强中外学术合作&#xff0c;促进自动驾驶和智能传感技术的发展&#xff0c;促进全球研究人员、开发人员、工程…

LTspice仿真中设置电阻随时间变化的方法

背景&#xff1a; 笔者找了很多资料都没有看到如何设置电阻、电容等参数随时间变化。但在实际模拟中&#xff0c;总会遇到需要模拟这些量的变化。故撰写此文&#xff0c;供大家参考。 除了模拟随时间变化外&#xff0c;同样的思路也可以模拟随其他变量变化 效果展示 设置电…

【网络研究观】-20240531

战争揭开美国武器优势的面纱 随着俄军在哈尔科夫地区稳步推进&#xff0c;乌克兰战争对美国国防机器而言是一场灾难&#xff0c;这一点越来越明显&#xff0c;这不仅是因为我们的援助未能挽救乌克兰的撤退和可能的失败。更重要的是&#xff0c;这场战争无情地暴露了我们国防体…

内网不能访问域名怎么办?

在网络应用中&#xff0c;我们常常遇到内网不能访问域名的问题。这是由于内网环境限制导致的&#xff0c;内网无法直接连接到公网&#xff0c;因而无法访问互联网上的域名。我们可以利用一些特殊技术和工具来解决这个问题。 天联组网技术的应用 天联组网是一种非常受欢迎的解决…

JS数组怎么去重?| JavaScript中数组去重的14种方法

目录 一、利用for循环嵌套去重 二、利用splice() for循环嵌套&#xff08;ES5中最常用&#xff09; 三、利用indexOf() for循环去重 四、利用sort() for循环去重 五、利用includes() for循环去重&#xff08;ES7&#xff09; 六、利用Object键值对及其hasOwnProperty…

在phpstorm2024版里如何使用Jetbrains ai assistant 插件 ?

ai assistant激活成功后&#xff0c;如图 ai assistant渠道&#xff1a;https://web.52shizhan.cn/activity/ai-assistant 在去年五月份的 Google I/O 2023 上&#xff0c;Google 为 Android Studio 推出了 Studio Bot 功能&#xff0c;使用了谷歌编码基础模型 Codey,Codey 是…

解锁 JavaScript ES6:函数与对象的高级扩展功能

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;JavaScript 精粹 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; ES5、ES6介绍 文章目录 ES6函数扩展1 默认参数1.1 之前写法1.2 ES6 写法1.3 注意点 2 …

python实现——综合类型数据挖掘任务(无监督的分类任务)

综合类型数据挖掘任务 航空公司客户价值分析。航空公司客户价值分析。航空公司客户价值分析。航空公司已积累了大量的会员档案信息和其乘坐航班记录&#xff08;air_data.csv&#xff09;&#xff0c;以2014年3月31日为结束时间抽取两年内有乘机记录的所有客户的详细数据。利用…

python多种方式 保留小数点位数(附Demo)

目录 前言1. 字符串格式2. round函数3. Decimal模块4. numpy库5. Demo 前言 在Python中&#xff0c;保留小数点后特定位数可以通过多种方式实现 以下是几种常见的方法&#xff0c;并附上相应的代码示例&#xff1a; 使用字符串格式化&#xff08;String Formatting&#xff…

Go 1.23新特性前瞻

2024年5月22日&#xff0c;Go 1.23版本[1]功能特性正式冻结&#xff0c;后续将只改bug&#xff0c;不增加新feature。 对Go团队来说&#xff0c;这意味着开始了Go 1.23rc1的冲刺&#xff0c;对我们普通Gopher而言&#xff0c;这意味着是时候对Go 1.23新增的功能做一些前瞻了&am…

ad18学习笔记20:焊盘设置Solder Mask Expansion(阻焊层延伸)

【AD18新手入门】从零开始制造自己的PCB_ad18教程-CSDN博客 Altium Designer绘制焊盘孔&#xff08;Pad孔&#xff09;封装库的技巧&#xff0c;包括原理图封装和PCB封装_哔哩哔哩_bilibili 默认的焊盘中间是有个过孔的&#xff0c;单层焊盘&#xff08;表贴烛盘&#xff09;…

ARM学习(28)NXP 双coreMCU IMX1160学习

笔者最近接触到一块IMXRT1160的双core板子&#xff0c;特依次来记录学习一下 1、IMXRT1160 板子介绍 介绍一下NXP的Demo板子&#xff0c;是一个双core的板子&#xff0c;Cortexm7和Cortexm4&#xff0c;总计1MB的RAM空间&#xff0c;256KB的ROM空间&#xff0c;提供了丰富的内…

【GD32】05 - PWM 脉冲宽度调制

PWM PWM (Pulse Width Modulation) 是一种模拟信号电平的方法&#xff0c;它通过使用数字信号&#xff08;通常是方波&#xff09;来近似地表示模拟信号。在PWM中&#xff0c;信号的占空比&#xff08;即高电平时间占整个周期的比例&#xff09;被用来控制平均输出电压或电流。…

IDEA一键启动多个微服务

我们在做微服务项目开发的时候&#xff0c;每次刚打开IDEA&#xff0c;就需要把各个服务一个个依次启动&#xff0c;特别是服务比较多时&#xff0c;逐个点击不仅麻烦还费时。下面来说一下如何一键启动多个微服务。 操作步骤 点击Edit Configurations 2.点击“”&#xff0c;…

BSD盲区检测系统性能要求及试验方法

相关术语 盲区检测(bsd,blind spot detection)试验车辆(subject vehicle)目标车辆(target vehicle)横向距离(lateral distance):试验车车身最外缘(不包含外后视镜)与目标车辆车身最外缘(不包含外后视镜)之间的横向距离。 纵向距离(longitudinal distance):试验…

用windows server backup备份文件夹到网络共享文件夹并恢复

一、备份 开始 运行windows server backup,在右边的窗格中点击“备份计划” 选择备份配置 因为我们要备份的是一个文件夹&#xff0c;所以&#xff0c;选“自定义”&#xff0c;卷即为磁盘分区。 选择要备份的项 点击添加项目&#xff0c;可依次添加多个备份项目。 勾选需要…

职场思考-阅读专业与技能同步增长(12)

我们可以发现一个人“逆袭”的关键就是先要改变自己的思想&#xff0c;而机遇、资源都是外部条件。 改变思想无非也就几个途径&#xff1a; 一是阅读换脑&#xff0c;二是遇贵人点拨&#xff0c;三是社会“碰壁”后的反思并改正 对于职场进阶而言&#xff0c;阅读更是必要手段 …

知名专业定制线缆知名智造品牌推荐-精工电联:解决水下机器人线缆行业痛点的领航者

在科技日新月异的今天&#xff0c;精工电联作为高科技智能化产品及自动化设备专用连接线束和连接器配套服务商&#xff0c;致力于为高科技行业提供高品质、高性能的集成线缆和连接器定制服务。我们不仅是高品质定制线缆供应商&#xff0c;更是水下机器人线缆行业痛点的有效解决…

Dynamics CRM 修改新建记录的CreatedOn字段值

CRM在创建新记录时&#xff0c;一些系统属性例如创建者、创建时间是取当前创建记录的人以及当前的时间&#xff0c;而有时这些属性需要更改&#xff0c;例如创建时间&#xff0c;这个场景更多的用在数据迁移的时候&#xff0c;老数据有他的原始创建时间&#xff0c;不能因为迁移…

Linux网络-使用Tcp协议进行网络通信并通过网络接口实现远端翻译

文章目录 Tcp协议Tcp协议常见API接口1. int socket(int domain, int type, int protocol);2. int bind(int socket, const struct sockaddr *address, socklen_t address_len);struct sockaddr 3. int listen(int socket, int backlog);4. int accept(int socket, struct socka…