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

香橙派 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芯片也一定能闯出一片自己的天地!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jenkins本地打包远程部署项目

1、 Jenkins简介 Jenkins是一款开源的持续集成工具&#xff0c;用于自动化构建、测试和部署软件项目。它可以通过插件扩展来支持各种不同的开发语言和工具。Jenkins提供了一个简单易用的Web界面&#xff0c;可以通过界面配置和管理构建任务&#xff0c;也可以通过命令行工具进…

实物资产的市场主线将逐步回归

民生证券认为&#xff0c;投资者逐渐意识到长期趋势并没有发生变化&#xff0c;这或许正是本周最大的变化。在预期博弈重回冷静期后&#xff0c;去金融化背景下实物资源占优的市场主线也将逐步回归。 1 高低切换后的冷静期 从4月下旬至上周&#xff0c;A股市场呈现出由高位资产…

【iOS】UI学习(二)

UI学习&#xff08;二&#xff09; 进度条和滑动条步进器与分栏控件警告对话框和提示等待器UITextFieldUITextField控件UITextFieldDelegate协议 UIScrollView布局子视图手动布局子视图自动布局子视图 进度条和滑动条 下面通过一个程序来讲解该内容&#xff1a; #import <…

c++函数基础总结

在给出的代码片段中&#xff0c;我们看到两部分内容&#xff1a;一个类定义和一个全局函数声明。让我们逐一分析它们&#xff1a; 类定义&#xff1a; cpp复制代码 class { public: void a(); }; 这个类定义是不完整的&#xff0c;因为它没有类名。但为了说明&#xff0c;我…

变量的作用域

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 变量的作用域是指程序代码能够访问该变量的区域&#xff0c;如果超出该区域&#xff0c;再访问时就会出现错误。在程序中&#xff0c;一般会根据变量…

HarmonyOS鸿蒙学习笔记(28)@entry和@Component的生命周期

entry和Component的生命周期 entry和Component的关系Component生命周期Entry生命周期 生命周期流程图生命周期展示示例代码参考资料 HarmonyOS的生命周期可以分为Compnent的生命周期和Entry的生命周期&#xff0c;也就是自定义组件的生命周期和页面的生命周期。 entry和Compone…

MySQL 索引使用(二)

本篇继续介绍有关索引的使用。 目录 一、SQL提示 二、单列索引和联合索引 三、覆盖索引 四、前缀索引 五、索引的使用原则 一、SQL提示 我们在使用索引来进行查询时&#xff0c;很有可能会出现一个字段中包含多个索引的情况&#xff0c;例如这里有一个name字段&#xff0c…

曾巩,散文的艺术与哲思

曾巩&#xff0c;字子固&#xff0c;世称南丰先生&#xff0c;南丰&#xff08;今江西&#xff09;人&#xff0c;生于北宋真宗天禧三年&#xff08;公元1019年&#xff09;&#xff0c;卒于北宋元丰六年&#xff08;公元1083年&#xff09;&#xff0c;享年64岁。他是中国北宋…

Unity开发——编辑器打包、3种方式加载AssetBundle资源

一、创建ab资源 &#xff08;一&#xff09;Unity资源设置ab格式 1、选中要打包成assetbundle的资源&#xff1b; 可以是图片&#xff0c;材质球&#xff0c;预制体等&#xff0c;这里方便展示用预制体打包设置展示&#xff1b; 2、AssetBundle面板说明 &#xff08;1&…

【React篇】组件错误边界处理(组件错误引起的页面白屏)

我们知道在生产环境react错误会导致整个页面崩溃&#xff0c;显示为空白页面。 比如下图的错误&#xff0c;导致了左侧页面直接白屏&#xff1a; 由于某一个组件报错导致整个页面崩溃是很严重的问题&#xff0c;那么我们应该如何去降低代码报错带来的影响呢&#xff1f; 我们…

JavaScript 动态网页实例 —— 窗口控制

除了打开和关闭窗口之外,还有很多其他控制窗口的方法。例如,可以使用 window.focus()方法使窗口获得焦点,也可以利用与其相对的window.blur 方法使窗口失去焦点。本节介绍移动窗口、改变窗口大小、窗口滚动、窗口超时操作、常用窗口事件、常用窗口扩展等窗口控制的方法和手段。…

mac电脑鼠标键盘共享软件:ShareMouse for Mac 激活版

ShareMouse 是一款跨平台的键盘和鼠标共享软件&#xff0c;它允许用户在多台计算机之间共享同一组键盘和鼠标&#xff0c;实现无缝的操作和控制。该软件适用于 Windows 和 macOS 系统&#xff0c;并且支持多种连接方式&#xff0c;包括局域网连接和无线连接。 使用 ShareMouse&…

从openstack环境中将服务器镜像导出的简单办法

1 登录openstack的页面&#xff0c;找到计划导出的主机信息。 通过实例名称&#xff0c; IP地址&#xff0c;找到对应的记录。点击实例名称&#xff0c;进入详情页。 在这里主要可以知道&#xff0c;当前主机在服务器上的文件ID&#xff0c;可以按这个ID去找对应的目录。 还可…

java读取文件内容(正则表达式匹配)

已知文件score.txt内容如下&#xff1a; 语文85分&#xff0c;数学89分&#xff0c;英语75分&#xff0c;马列95分。 要求解析出其中的成绩数据&#xff0c;并计算总成绩 import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import jav…

JDK环境配置、安装

DK环境配置&#xff08;备注&#xff1a;分32位与64位JDK&#xff0c;32位电脑只能按照32位JDK&#xff0c;64位电脑兼容32、64位JDK&#xff09; 一、检查自己电脑是否安装过JDK 1.在电脑屏幕左下角&#xff0c;输入命令提示符CMD&#xff0c;打开命令提示符应用 2.在打开界…

QT系列教程(7) QLineEdit介绍

简介 QLineEdit属于输入插件&#xff0c;用来实现单行录入。支持几种录入模式。 Normal表示正常录入,录入的信息会显示在QLineEdit上。 Password表示密码录入的方式&#xff0c;录入的信息不显示QLineEdit&#xff0c;只是通过黑色圆点显示。 NoEcho 表示不显示录入信息&am…

“开源与闭源:AI大模型发展的未来之路“

文章目录 每日一句正能量前言数据隐私开源大模型与数据隐私闭源大模型与数据隐私数据隐私保护的共同考虑结论 商业应用开源大模型的商业应用优势&#xff1a;开源大模型的商业应用劣势&#xff1a;闭源大模型的商业应用优势&#xff1a;闭源大模型的商业应用劣势&#xff1a;商…

ros DWA局部规划模块

ROS-DWA模块 主要流程DWAPlannerROS::computeVelocityCommandsDWAPlannerROS::dwaComputeVelocityCommandsDWAPlanner::findBestPathSimpleScoredSamplingPlanner::findBestTrajectory 调参技巧DWA被目标点过度吸引&#xff0c;且不听全局规划器指挥 消融实验goal_front_costs_…

Java 异步编编程——Java内置线程池(Executor 线程池)

文章目录 知道线程池是什么以及解决什么问题Java 内置线程池Java 内置线程池设计结构及执行机制ThreadPoolExecutor 中的概念生命周期核心参数阻塞队列4 种任务拒绝策略 线程池使用场景 知道线程池是什么以及解决什么问题 线程池&#xff08;Thread Pool&#xff09;是一种基于…

Kafka Java API

1、增加依赖 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>1.0.0</version> </dependency>2、三个案例 案例1&#xff1a;生产数据 import org.apache.kafka.clients.p…