完美体育·(中国)手机网页版科技提醒您:您的浏览器版本过低或者使用了兼容模式,为了获得更好的浏览体验,建议使用IE10以上的浏览器或使用极速模式。 请升级浏览器以获得更好的体验!

完美体育·(中国)手机网页版 > 评测报告 > 【完美体育·(中国)手机网页版MYD-YT507开发板】使用mjpeg_streamer建立摄像头图传

【完美体育·(中国)手机网页版MYD-YT507开发板】使用mjpeg_streamer建立摄像头图传

文章来源: 发布日期:2022.12.28 浏览次数:1998 次

由评测者“HonestQiao”提供。


在之前的研究中,已经实现了完美体育·(中国)手机网页版MYD-YT507开发板接入海康威视USB摄像头,并进行摄像头数据的获取,具体可查看:USB摄像头使用从入门到放弃

在此基础上,进一步实现了完美体育·(中国)手机网页版MYD-YT507开发提供MJPEG推流,矽速M2 Dock读取该MJPEG推流,并显示到屏幕上,其逻辑如下:

M2Dock推流数据获取逻辑.png


最终的效果,可以查看:M2 Dock获取MJPEG推流数据

这篇文章,分享的就是 完美体育·(中国)手机网页版MYD-YT507开发板 实现MJPEG推流的部分。

最开始,我尝试了使用nginx + nginx-rtmp-module模块,来实现rtmp视频推流。

具体操作如下:

  1. 安装nginx,及nginx-rtmp-module模块:
# Ubuntu18.04操作系统 # 安装pcre sudo apt install libpcre3 libpcre3-dev
sudo apt install openssl libssl-dev
sudo apt install zlib1g-dev # 安装nginx wget http://nginx.org/download/nginx-1.22.0.tar.gz git git clone https://github.com/arut/nginx-rtmp-module tar -zxvf nginx-1.22.0.tar.gz
cd nginx-1.22.0 ./configure --prefix=/usr/local/nginx  --add-module=../nginx-rtmp-module  --with-http_ssl_module
make -j4
sudo make install 
  1. 使用ffmpeg获取摄像头数据并推流:

    ffmpeg -input_format mjpeg -s:v 640x480 -framerate 30 -i /dev/video0 -f flv "rtmp://127.0.0.1:1935/live/test" 
  2. 使用支持视频流的播放器,播放流地址(注意IP修改为开发板实际的IP):rtmp://192.168.1.207:1935/live/test
    ...

在矽速M2 Dock上,使用的开发环境是MaixPy。
在Python中,对于MJPEG数据,可以很方便的获取。
于是又了解了Ubuntu系统下MJPEG推流的资料,使用mjpeg_streamer就能很方便的实现。

具体操作如下:

sudo apt install cmake libjpeg9-dev

git clone https://github.com/jacksonliam/mjpg-streamer.git cd mjpg-streamer/mjpg-streamer-experimental make all
sudo make install

mjpg_streamer -i "input_uvc.so -d /dev/video0 -n -r 320x240 -f 10" -o "output_http.so -w ./" 

执行 mjpg_streamer 后,就会启动对应的服务:

image.png


然后,通过浏览器访问 http://192.168.2.207:8080/?action=stream 即可:

image.png


提供的MJPEG服务,可以用浏览器直接播放,也可以在Python程序中调用并呈现。
可供测试的代码如下:

import numpy as np import platform if platform.uname().node == "sipeed": from io import BytesIO from PIL import Image from maix import camera, mjpg, utils, display, image else: import cv2

READ_TYPE = "socket" # url socket MJPEG_HOST = "192.168.2.207" MJPEG_PORT = 8080 MJPEG_QUERY = "/?action=stream" def img_data_show(jpg): global img_bytes global tmp_file global is_sipeed global BytesIO global Image global np global image global display if is_sipeed: if True:
            bytes_stream = BytesIO(jpg)
            pimg = Image.open(bytes_stream)
            img = image.load(pimg)
            display.show(img) else: with open(tmp_file, "wb") as binary_file:
                binary_file.write(jpg)
                img = image.open(tmp_file)
                display.show(img) else:
        img = cv2.imdecode(np.frombuffer(
            jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
        cv2.imshow('i', img) if cv2.waitKey(1) == 27:
            exit(0) def img_data_match(chunk): global img_bytes global tmp_file global is_sipeed global BytesIO global Image global np global image global display global img_data_show

    img_bytes += chunk
    a = img_bytes.find(b'\xff\xd8')
    b = img_bytes.find(b'\xff\xd9') if a != -1 and b != -1:
        jpg = img_bytes[a:b+2]
        img_bytes = img_bytes[b+2:]
        img_data_show(jpg)     


img_bytes = b'' tmp_file = "/tmp/test.jpg" is_sipeed = platform.uname().node == "sipeed" print("Connect to %s:%d with %s on %s" % (MJPEG_HOST, MJPEG_PORT, READ_TYPE, platform.uname().node)) if READ_TYPE == "url": import requests

    MJPEG_URL = "http://%s:%s%s" % (MJPEG_HOST, MJPEG_PORT, MJPEG_QUERY)

    r = requests.get(MJPEG_URL, stream=True) if(r.status_code == 200): print("connect success!") for chunk in r.iter_content(chunk_size=1024):
            img_data_match(chunk) else: print("Received unexpected status code {}".format(r.status_code)) elif READ_TYPE == "socket": import socket

    client = socket.socket() # 创建socket套接字 ret = client.connect((MJPEG_HOST, MJPEG_PORT)) # 状态位,判定是否连接成功 request_url = "GET %s HTTP/1.1\r\nHost:%s\r\nConnection:Close\r\n\r\n" % (
        MJPEG_QUERY, MJPEG_HOST) if(ret == -1): # 连接失败,退出程序 print("connet error!")
        exit(-1) else: # 连接成功 print("connect success!")

    client.send(request_url.encode()) # 发送socket请求,开始接收数据 chunk = client.recv(1024) # 第一个recv返回信息,跟图片无关 chunk = client.recv(1024) # 这个信息开始跟图片有关系,放到接收变量里 while chunk: # 判断是否还有信息 img_data_match(chunk)
        chunk = client.recv(1024) # 继续接收 

在电脑上,将上述代码保存为mjpeg_display_demo.py,并修改代码中MJPEG_HOST为实际的开发板ip地址,然后使用python mjpeg_display_demo.py运行,就能查看显示了。

如果上述代码运行在矽速M2 Dock中,那么对应的效果就是显示到屏幕上了。