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

发布于:2024-06-04 ⋅ 阅读:(239) ⋅ 点赞:(0)

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


网站公告

今日签到

点亮在社区的每一天
去签到