基于Sipeed M1s Dock实现的网络相机
基于Sipeed M1s Dock平台的网络相机,能够定时拍摄图片上传到电脑端程序,电脑端将拍摄图片合成为一个视频并保存下来。
标签
2022寒假在家练
Sipeed M1s Dock
网络相机
我就是我
更新2023-03-28
北京邮电大学
419

内容介绍

一、项目描述

(一)项目介绍

该项目目标是完成一个基于Sipeed M1s Dock 的网络相机,相机端定时完成拍摄,将拍摄图片通过wifi传到电脑或服务器中,并在电脑或服务器上编写上位机程序,实现接收图片并合成一个视频。

(二)设计思路

  1.  M1S端设计思路

以例程camera_streaming_through_wifi和camera_bypass_lcd为基础,实现通过网络传输摄像头拍摄的图片。设计思路为:在c906芯片上编写初始化相机和WiFi的程序(之后又增加了屏幕显示功能,需初始化屏幕串口),将wifi名称、密码等信息使用IPC功能通过xram传递给e907芯片;e907芯片连接wifi,向指定ip和端口定时发送实时拍摄图片,同时可以接收电脑端程序发送的定时时间,做为下一次图片发送的间隔。

      2.  电脑端上位机设计思路

电脑端程序基于python语言开发,使用socket库创建tcp服务端连接,监听发来的信息;使用cv2库解析mjpeg图片、展示图片、合成视频并保存;使用thread库创建多线程,使程序能够同时维持openCV的运行和接收信息,也为之后拓展连接多个设备的开发做准备;使用time库获取时间,作为图片接收时间记录的依据和计算图片间隔时间的依据,用于辅助调试。

(三)软件流程

M1S开发流程图

BL808网络摄像机流程图

电脑上位机接收软件开发流程图

BL808电脑端流程图

二、硬件介绍

Sipeed M1s Dock模块包含BL808主芯片、触摸屏、摄像头、wifi蓝牙芯片等硬件设施。BL808主芯片包含M0,D0,LP三个处理器,M0是32位处理器,主要负责处理网络数据流和外设访问功能;D0是64位处理器,主要负责多媒体数据的计算和处理;LP负责低功耗模式下的相关功能。

本项目使用M0处理器(e907)进行WiFi连接和图片推流;使用D0处理器(c906)进行图片实时拍摄和屏幕显示。

三、功能展示

(一)实物

微信图片_20230314152523

(二)电脑端

微信截图_20230314152055

(三)最终输出视频

微信截图_20230314152212微信截图_20230314153158

四、代码片段说明

(一)相机读取、屏幕输出

//读取相机缓存内容
    while(1){
        while (0 != bl_cam_mjpeg_get(&pic, &len)) {
            vTaskDelay(1);
        }
        while (0 != bl_cam_mipi_rgb565_frame_get((uint8_t **)&picture, &length)) {
            vTaskDelay(1);
        }
        printf("[%8u]get mipi rgb565 frame 0x%08x size %ubytes cost %fms ", loop_cnt, (uint32_t)picture, length, (float)(CPU_Get_MTimer_US() - curr_cnt) / 1000);
        BilinearInterpolation_RGB565(picture, 400, 300, draw_buf, 280, 240);    //改变尺寸
        curr_cnt = CPU_Get_MTimer_US();
        //写入屏幕
        for (int i = 0; i < 280 * 240; i++) {
            draw_buf[i] = __builtin_bswap16(draw_buf[i]);
        }
        st7789v_spi_draw_picture_nonblocking(0, 0, 279, 239, draw_buf);
        printf("and lcd_flush cost %fms\r\n", (float)(CPU_Get_MTimer_US() - curr_cnt) / 1000);
        //更新相机缓存
        bl_cam_mipi_rgb565_frame_pop();
        bl_cam_mjpeg_pop();
        loop_cnt++;
        vTaskDelay(100);
    }

循环运行,分别读取mjpeg和rgb565两种图片,mjpeg格式用于输出800*600大小图片推流到电脑端,rgb565用于屏幕显示,之后使用对应pop函数清除缓存。

(二)Wifi推流(components\sipeed\e907\m1s_e907_xram\src\m1s_e907_xram_wifi.c)

while (1) {
            if((CPU_Get_MTimer_MS()>time_delay)&&flush){
                ret = bl_cam_mjpeg_get(&pic, &len);
                csi_dcache_invalid_range((void *)pic, len);
                if (ret == 0) {
                    if (((uint32_t)(uintptr_t)pic + len) > (mjpeg_start_addr + mjpeg_buffer_size)) {
                        /* if mjpeg store edge loop to start*/
                        first_len = mjpeg_start_addr + mjpeg_buffer_size - (uint32_t)(uintptr_t)pic;
                        second_len = len - first_len;
                        csi_dcache_invalid_range((void *)pic, first_len);
                        memcpy(private.stream_buff, pic, first_len);
                        csi_dcache_invalid_range((void *)mjpeg_start_addr, second_len);
                        memcpy(private.stream_buff + first_len, (void *)mjpeg_start_addr, second_len);
                        usb_ptr = private.stream_buff;
                    } else {
                        /*mjpeg data not cut*/
                        usb_ptr = pic;
                        csi_dcache_invalid_range((void *)usb_ptr, len);
                    }

                    uint32_t recv;
_retry2:
                    printf("send jpg len(%d):%ld\r\n", sizeof(len), len);
                    if (write(sock, &len, sizeof(len)) < 0) break;
                    if (read(sock, &recv, sizeof(recv)) < 0) {
                        vTaskDelay(50);
                        goto _retry2;
                    }
                    delay=recv;
                    #define PACK_LEN    (1000)
                    int remain_len = len;
                    if (write(sock, usb_ptr, remain_len) < 0) break;
                    if (read(sock, &recv, sizeof(recv)) < 0) break;
                    if (recv==0) continue;
                    if(delay<1000){
                        if(recv>200)vTaskDelay(recv-300);
                        flush=true;
                    }else{
                        flush=false;
                        if((uint32_t)err>delay) err=0;
                        time_delay=time+(uint64_t)((int)delay-err);
                        //printf("%lld\n",time);
                        //printf("%lld\n",time_delay);
                    }
                    if(flush){
                        bl_cam_mjpeg_pop();
                    }
                }
            }else{
                uint64_t now=CPU_Get_MTimer_MS();
                if(time_delay>(now+2000)) {
                        vTaskDelay(2000);
                        uint32_t send=1;
                    if (write(sock, &send, sizeof(send)) < 0) break;
                }else{
                    now=CPU_Get_MTimer_MS();
                    if(time_delay>now){
                        vTaskDelay(time_delay-now);
                        continue;
                    }
                    int temp=(int)((now-time)-delay);
                    if(temp<500) err+=temp;
                    printf("delay:%lld;+/-:%i\n\n",now-time,err);
                    time=now;
                    flush=true;
                }
            }
        }

图片推流程序代码,循环处理。当达到发送间隔时间,且未发送成功时,持续读取相机图片,发送图片,发送成功后收到电脑端回应发送间隔,根据发送间隔计算下一次发送时间,未到时间持续循环等待,不发送。

五、主要难题与解决方案

(一)无法连接到WiFi

库文件中components\sipeed\e907\m1s_e907_xram\src\m1s_e907_xram_wifi.c文件存在问题,wifi的ip和端口被写死,无法与C906主函数中填写的wifi配置一致,更改后即可。

(二)图片推流问题

无法确定推流图片电脑端是否完整接收,导致有时解码不出来,程序出现问题,同时BL808部分不会重传。

解决办法为接收到信息后验证信息,回复是否接收完整。BL808接收到回复信息后完成下一步操作,接收到的代码为不成功时进行重传。后又增加了更改间隔时间功能,若接收成功,电脑端回复间隔时间,BL808根据新的间隔时间发送图片。

(三)无法同时推流和屏幕显示

屏幕显示rgb565格式,推流mjpeg格式,且图片尺寸不同。mjpeg对图片进行压缩,适合网络传输,rgb565有合适的尺寸大小转换函数且可以直接写入屏幕的缓存,适合各自用途,最好的解决办法为分别生成两种图片。

经过实验发现,直接初始化两种格式后,只保留最后一次的设置,之前的初始化被覆盖,所以显示有问题。解决方法为,在components\platform\hosal\bl808_hal\bl_cam.c文件中,修改其中初始化函数,在当中修改DSP2_MISC_Scaler_Input_Select (DSP2_MISC_SCALER_1_ID, DSP2_MISC_SCALER_DSP2_INPUT);和DSP2_Scaler_Set_Input (DSP2_MISC_SCALER_B, DSP2_MISC_SCALER_DSP2_INPUT);

/*change DSP2_MISC_SCALER_2_ID to DSP2_MISC_SCALER_1_ID by myself --YuHao*/
DSP2_MISC_Scaler_Input_Select(DSP2_MISC_SCALER_1_ID, DSP2_MISC_SCALER_DSP2_INPUT);
DSP2_MISC_Scaler_Init(DSP2_MISC_SCALER_1_ID, &scaler_cfg);
DSP2_MISC_Scaler_Enable(DSP2_MISC_SCALER_1_ID);
 /*change DSP2_MISC_SCALER_C to DSP2_MISC_SCALER_B by myself --YuHao*/
DSP2_Scaler_Set_Input(DSP2_MISC_SCALER_B, DSP2_MISC_SCALER_DSP2_INPUT);
DSP2_YUV2RGB_Init(DSP2_YUV2RGB_PARAM_8BIT_BT601);
DSP2_YUV2RGB_Set_Input(DSP2_YUV2RGB_A, DSP2_YUV2RGB_INPUT_SCALER_B);

六、未来计划

可以在该模块上加入AI模型,拍摄图片的同时对图片进行一些识别。例如结合项目3、4的人脸识别模块,对识别到的人脸进行拍摄上传,同时发送识别结果。也可以通过连接舵机等设备,达到人脸跟踪和人形跟踪的效果。同时调用屏幕的触摸功能,设计人机交互,可以通过此功能设置wifi、选择工作模式、增删人脸识别结果等。通过这样的一个模块,未来可以实现很多功能。

七、附件(源码)

链接:https://pan.baidu.com/s/1sr7bc4wBUzB1GqaAmvXiFQ?pwd=5po8 
提取码:5po8

团队介绍

北京邮电大学
团队成员
禹豪
北京邮电大学 电子信息工程专业

评论

0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号