èªç©ºæ©ãå¶åŸ¡ããéã«ãããã€ã¹ããå°äžãžã®ãããªäŒéãé »ç¹ã«äœ¿çšãããããšã¯åšç¥ã®äºå®ã§ãã éåžžããã®æ©äŒã¯UAVã®è£œé æ¥è
èªèº«ã«ãã£ãŠæäŸãããŸãã ãããããããŒã³ãèªåã®æã§çµã¿ç«ãŠããããã©ãããŸããïŒ
ç§ãã¡ãšHelvetisã®ã¹ã€ã¹ã®ããŒãããŒã«ãšã£ãŠã®èª²é¡ã¯ããããŒã³ã®äœé»åçµã¿èŸŒã¿ããã€ã¹ããWiFiçµç±ã§Windowsã¿ãã¬ããã«Webã«ã¡ã©ãããªã¢ã«ã¿ã€ã ãããªããããŒããã£ã¹ãããããšã§ããã çæ³çã«ã¯ïŒ
- é
延<0.3s;
- çµã¿èŸŒã¿ã·ã¹ãã ã®CPUè² è·ãäœãïŒã³ã¢ããã10ïŒ
æªæºïŒ;
- å°ãªããšã480pã®è§£å床ïŒ720p以äžïŒã
äœãããŸããããªãããã«æããŸããïŒ
ããã§ã次ã®æ©åšãªã¹ãã«æ±ºããŸããã
- Minnowboard 2ã³ã¢ãAtom E3826 @ 1.4 GHzãOSïŒUbuntu 16.04
- ããã€ãã®åœ¢åŒïŒYUVãMJPEGãH264ïŒããµããŒãããELP USB100W04HãŠã§ãã«ã¡ã©
- ASUS VivoTab Note 8 Windowsã¿ãã¬ãã
æšæºãœãªã¥ãŒã·ã§ã³ã§ããŸããã£ãŠããè©Šã¿
Python + OpenCVã䜿çšããã·ã³ãã«ãªãœãªã¥ãŒã·ã§ã³
æåã«ãOpenCVã䜿çšããŠã«ã¡ã©ãããã¬ãŒã ãåä¿¡ããJPEGã䜿çšããŠå§çž®ããHTTPãä»ããŠã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ã«éä¿¡ãã
åçŽãªPythonã¹ã¯ãªããã䜿çšããããšããŸããã
Pythonã§ã®HTTP MJPGã¹ããªãŒãã³ã°from flask import Flask, render_template, Response import cv2 class VideoCamera(object): def __init__(self): self.video = cv2.VideoCapture(0) def __del__(self): self.video.release() def get_frame(self): success, image = self.video.read() ret, jpeg = cv2.imencode('.jpg', image) return jpeg.tobytes() app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') def gen(camera): while True: frame = camera.get_frame() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n') @app.route('/video_feed') def video_feed(): return Response(gen(VideoCamera()), mimetype='multipart/x-mixed-replace; boundary=frame') if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)
ãã®ã¢ãããŒãã¯ïŒã»ãŒïŒåäœããããšã蚌æãããŠããŸãã 衚瀺çšã®ã¢ããªã±ãŒã·ã§ã³ãšããŠãä»»æã®Webãã©ãŠã¶ãŒã䜿çšã§ããŸãã ãããããã¬ãŒã ã¬ãŒããäºæ³ãããäœããMinnowboardã®CPUè² è·ãåžžã«100ïŒ
ã§ããããšãããã«ããããŸããã çµã¿èŸŒã¿ããã€ã¹ã¯ããªã¢ã«ã¿ã€ã ãã¬ãŒã ãšã³ã³ãŒãã£ã³ã°ã«å¯Ÿå¿ã§ããŸããã§ããã ãã®ãœãªã¥ãŒã·ã§ã³ã®å©ç¹ã®ãã¡ã1ç§ããã10ãã¬ãŒã 以äžã®åšæ³¢æ°ã§480pãããªãéä¿¡ããéã®éåžžã«å°ããªé
延ã«æ³šç®ãã䟡å€ããããŸãã
æ€çŽ¢äžã«ãéå§çž®ã®YUVãã¬ãŒã ã«å ããŠãMJPEG圢åŒã®ãã¬ãŒã ãçæã§ããWebã«ã¡ã©ãèŠã€ãããŸããã ãã®ãããªäŸ¿å©ãªæ©èœã䜿çšããŠãCPUã®è² è·ã軜æžãããã©ã³ã¹ã³ãŒãã£ã³ã°ãªãã§ãããªã転éããæ¹æ³ãèŠã€ããããšã決å®ãããŸããã
ffmpeg / vlc
ãŸããã¿ããªã®ãæ°ã«å
¥ãã®ãªãŒãã³ãœãŒã¹ffmpegã³ã³ãã€ã³ãè©ŠããŠã¿ãŸãããããã«ããããšããããUVCããã€ã¹ãããããªã¹ããªãŒã ãèªã¿åãããšã³ã³ãŒãããŠéä¿¡ããããšãã§ããŸãã ããã¥ã¢ã«ã«å°ã浞ã£ãåŸãã³ãã³ãã©ã€ã³ããŒãèŠã€ããããã©ã³ã¹ã³ãŒãããã«å§çž®ãããMJPEGãããªã¹ããªãŒã ãéåä¿¡ã§ããããã«ãªããŸããã
ffmpeg -f v4l2 -s 640x480 -input_format mjpeg -i /dev/video0 -c:v copy -f mjpeg udp://ip:port
CPUè² è·ãäœãã£ãã åãã§ãffplayãã¬ãŒã€ãŒã§ã¹ããªãŒã ãç±å¿ã«ãªãŒãã³ããŸãã...æ®å¿µãªããšã«ããããªã®é
延ã¬ãã«ã¯ãŸã£ããåãå
¥ããããŸããã§ããïŒçŽ2ã3ç§ïŒã
ãããããã¹ãŠãè©Šããã€ã³ã¿ãŒãããããã©ãŠãžã³ã°ããŠããè¯å®çãªçµæãåŸãããšãã§ãããffmpegãæŸæ£ããããšã«ããŸããã
ffmpegã§é害ãçºçããåŸãVLCã¡ãã£ã¢ãã¬ãŒã€ãŒãç»å ŽããŸãããããã¯ãcvlcã³ã³ãœãŒã«ãŠãŒãã£ãªãã£ã§ãã ããã©ã«ãã§ã¯ãVLCã¯äžé£ã®ãããã¡ãŒã䜿çšããŸããããã¯ãäžæ¹ã§ã¯æ»ãããªç»åãå®çŸããã®ã«åœ¹ç«ã¡ãŸãããä»æ¹ã§ã¯æ°ç§ã®æ·±å»ãªé
延ããããããŸãã ããªãèŠãããããã®ã§ãã¹ããªãŒãã³ã°ãããªã蚱容ã§ãããšæããããã©ã¡ãŒã¿ãŒãéžã³ãŸããã é
延ã¯ããã»ã©å€§ãããªãïŒçŽ0.5ç§ïŒããã©ã³ã¹ã³ãŒãã£ã³ã°ã¯ãªããã¯ã©ã€ã¢ã³ãã¯ãããªãéåžžã«ã¹ã ãŒãºã«è¡šç€ºããŸããïŒãã ããã¯ã©ã€ã¢ã³ãã«150ããªç§ã®å°ããªãããã¡ãŒãæ®ãå¿
èŠããããŸããïŒã
ããã¯ãcvlcã®æçµè¡ã§ãã
cvlc -v v4l2:///dev/video0:chroma="MJPG":width=640:height=480:fps=30 --sout="#rtp{sdp=rtsp://:port/live,caching=0}" --rtsp-timeout=-1 --sout-udp-caching=0 --network-caching=0 --live-caching=0
æ®å¿µãªããããããªã¯éåžžã«å®å®ããŠåäœããã0.5ç§ã®é
延ã¯åãå
¥ããããŸããã§ããã
MJPG-ã¹ããªãŒããŒ
å®éã«ç§ãã¡ã®ã¿ã¹ã¯
ã«é¢ããèšäºãèŠã€ããã®ã§ãmjpg-streamerãè©Šãããšã«ããŸããã ãããè©ŠããŠã¿ãŸãããããã奜ãïŒ å€æŽãªãã§ã480pã®è§£å床ã§ãããªã倧å¹
ã«é
延ãããããšãªããmjpg-streamerãå¿
èŠã«å¿ããŠäœ¿çšããããšãã§ããŸããã
以åã®å€±æãèæ¯ã«ãç§ãã¡ã¯é·ãé幞ãã§ãããããããããã£ãšæ¬²ããã£ãã®ã§ãã ã€ãŸãããã£ãã«ã®ç®è©°ãŸããå°ãå°ãªããªãããããªå質ã720pã«åäžããŸãã
H264ã¹ããªãŒãã³ã°
ãã£ã³ãã«ã®è² è·ã軜æžããããã«ã䜿çšããã³ãŒããã¯ãh264ã«å€æŽããããšã«ããŸããïŒã€ã³ãã³ããªã§é©åãªWebã«ã¡ã©ãèŠã€ããïŒã Mjpg-streamerã¯h264ããµããŒãããŠããªãã£ããããå€æŽããããšã決å®ãããŸããã éçºæã«ã¯ãLogitechãšELPã補é ãããçµ±åãããh264ã³ãŒããã¯ãåãã2å°ã®ã«ã¡ã©ã䜿çšããŸããã çµå±ã®ãšããããããã®ã«ã¡ã©ã®h264ã¹ããªãŒã ã®å
容ã¯å€§ããç°ãªããŸããã
ã«ã¡ã©ãšã¹ããªãŒã æ§é
h264ã¹ããªãŒã ã¯ãããã€ãã®ã¿ã€ãã®NALïŒãããã¯ãŒã¯ã¢ãã¹ãã©ã¯ã·ã§ã³ã¬ã€ã€ãŒïŒãã±ããã§æ§æãããŠããŸãã ã«ã¡ã©ã¯5çš®é¡ã®ããã±ãŒãžãçæããŸããã
- ãã¯ãã£ãã©ã¡ãŒã¿ã»ããïŒPPSïŒ
- ã·ãŒã±ã³ã¹ãã©ã¡ãŒã¿ãŒã»ããïŒSPSïŒ
- ããŒãã£ã·ã§ã³åãããŠããªãã³ãŒãåã¹ã©ã€ã¹ã¬ã€ã€ãŒãIDRç»å
- ããŒãã£ã·ã§ã³åãããŠããªãã³ãŒãåãããã¹ã©ã€ã¹ã¬ã€ã€ãŒãéIDRç»å
- ã³ãŒãåã¹ã©ã€ã¹ããŒã¿ããŒãã£ã·ã§ã³
IDRïŒã€ã³ã¹ã¿ã³ããã³ãŒãã£ã³ã°ãªãã¬ãã·ã¥ïŒ-ãšã³ã³ãŒããããã€ã¡ãŒãžãå«ãããã±ãŒãžã ãã®å Žåãã€ã¡ãŒãžã®ãã³ãŒãã«å¿
èŠãªãã¹ãŠã®ããŒã¿ã¯ãã®ããã±ãŒãžã«å«ãŸããŠããŸãã ãã®ããã±ãŒãžã¯ããã³ãŒããã€ã¡ãŒãžã®åœ¢æãéå§ããããã«å¿
èŠã§ãã éåžžãh264å§çž®ãããªã®æåã®ãã¬ãŒã ã¯IDRç»åã§ãã
éIDR-ä»ã®ãã¬ãŒã ãžã®ãªã³ã¯ãå«ããšã³ã³ãŒããããç»åãå«ãããã±ãŒãžã ãã³ãŒããŒã¯ãä»ã®ãã±ãããååšããªããšã1ã€ã®éIDRãã¬ãŒã ã§ã€ã¡ãŒãžã埩å
ã§ããŸããã
IDRãã¬ãŒã ã«å ããŠããã³ãŒããŒã¯ç»åããã³ãŒãããããã«PPSããã³SPSãã±ãããå¿
èŠãšããŸãã ãããã®ãã±ããã«ã¯ãç»åãšãã¬ãŒã ã¹ããªãŒã ã«é¢ããã¡ã¿ããŒã¿ãå«ãŸããŠããŸãã
mjpg-streamerã³ãŒãã«åºã¥ããŠãV4L2ïŒvideo4linux2ïŒAPIã䜿çšããŠã«ã¡ã©ããããŒã¿ãèªã¿åããŸããã çµå±ã®ãšããããããªã®1ã€ã®ããã¬ãŒã ãã«ã¯ããã€ãã®NALãã±ãããå«ãŸããŠããŸããã
ã«ã¡ã©éã§å€§ããªéããèŠãããã®ã¯ãããã¬ãŒã ãã®å
容ã§ããã
h264bitstreamã©ã€ãã©ãªã䜿çšããŠãã¹ããªãŒã ã解æããŸããã ã¹ããªãŒã ã®ã³ã³ãã³ãã衚瀺ãã
ã¹ã¿ã³ãã¢ãã³ãŠãŒãã£ãªãã£ããããŸãã
Logitechã®ã«ã¡ã©ãã¬ãŒã ã¹ããªãŒã ã¯ãäž»ã«éIDRãã¬ãŒã ã§æ§æãããããã€ãã®ããŒã¿ããŒãã£ã·ã§ã³ã«åå²ãããŠããŸããã 30ç§ã«1åãã«ã¡ã©ã¯IDRç»åãSPSãPPSãå«ããã±ãããçæããŸããã ãã³ãŒããŒã¯ãããªã®ãã³ãŒããéå§ããããã«IDRããã±ãŒãžãå¿
èŠãšããããããã®ç¶æ³ã¯ããã«ã¯é©ããŠããŸããã§ããã æ®å¿µãªãããã«ã¡ã©ãIDRãã±ãããçæããæéãèšå®ããé©åãªæ¹æ³ããªãããšãå€æããŸããã ãããã£ãŠããã®ã«ã¡ã©ã®äœ¿çšãæŸæ£ããå¿
èŠããããŸããã
ELPã«ã¡ã©ã®æ¹ãã¯ããã«äŸ¿å©ã§ããããšãããããŸããã åä¿¡ããåãã¬ãŒã ã«ã¯ãPPSããã³SPSãã±ãããå«ãŸããŠããŸããã ããã«ãã«ã¡ã©ã¯30ãã¬ãŒã ããšã«IDRãã±ãããçæããŸããïŒæéã1ç§ïŒã ããã¯ç§ãã¡ã«ãšãŠãããåã£ãŠããŠããã®ã«ã¡ã©ãéžã³ãŸããã
mjpg-streamerã«åºã¥ããããŒããã£ã¹ããµãŒããŒã®å®è£
ãµãŒããŒéšåã®åºç€ãšããŠãåè¿°ã®mjpg-streamerã䜿çšããããšã決å®ãããŸããã ãã®ã¢ãŒããã¯ãã£ã«ãããæ°ããå
¥åºåãã©ã°ã€ã³ãç°¡åã«è¿œå ã§ããŸããã ãŸããããã€ã¹ããh264ã¹ããªãŒã ãèªã¿åããã©ã°ã€ã³ãè¿œå ããŸããã åºåãã©ã°ã€ã³ãšããŠãæ¢åã®httpãã©ã°ã€ã³ãéžæããŸããã
V4L2ã§ã¯ãh264ã¹ããªãŒã ã®åä¿¡ãéå§ããããã«V4L2_PIX_FMT_H264圢åŒã®ãã¬ãŒã ãåä¿¡ããããã«æå®ããã ãã§ååã§ãããã¹ããªãŒã ã®ãã³ãŒãã«ã¯IDRãã¬ãŒã ãå¿
èŠãªã®ã§ãã¹ããªãŒã ã解æããIDRãã¬ãŒã ãäºæããŸããã ã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ã«ã¯ããã®ãã¬ãŒã ããã¹ããªãŒã ãHTTPçµç±ã§éä¿¡ãããŸããã
ã¯ã©ã€ã¢ã³ãåŽã§ã¯ãffmpegãããžã§ã¯ãã®libavformatãšlibavcodecã䜿çšããŠãh264ã¹ããªãŒã ã®èªã¿åããšãã³ãŒããè¡ãããšã«ããŸããã æåã®ãã¹ããããã¿ã€ãã§ã¯ããããã¯ãŒã¯çµç±ã§ã¹ããªãŒã ãåä¿¡ããããããã¬ãŒã ã«åå²ãããã³ãŒããffmpegã«å²ãåœãŠãçµæã®ãã³ãŒããããç»åãNV12圢åŒããRGBã«å€æããOpenCVã«è¡šç€ºãå®è£
ããŸããã
æåã®ãã¹ãã§ã¯ããããªããããŒããã£ã¹ããããã®æ¹æ³ã¯å®è¡å¯èœã§ããããšã瀺ãããŸãããã倧å¹
ãªé
延ïŒçŽ1ç§ïŒããããŸãã ç§ãã¡ã®çãã¯httpãããã³ã«ã«ããã£ãŠãããããUDPã䜿çšããŠãã±ãããéä¿¡ããããšã«ããŸããã
RTPã®ãããªæ¢åã®ãããã³ã«ããµããŒãããå¿
èŠããªããããh264ã¹ããªãŒã ã®NALãã±ãããUDPããŒã¿ã°ã©ã å
ã§éä¿¡ãããæãåçŽãª
èªè»¢è»ãããã³ã«ãå®è£
ããŸããã åä¿¡åŽã®éšåãå°ãæ¹è¯ããåŸããã¹ã¯ãããPCã®ãããªã®äœé
延ã«é©ããŸããã ãã ããã¢ãã€ã«ããã€ã¹ã§ã®æåã®ãã¹ãã§ã¯ãh264ãœãããŠã§ã¢ã®ãã³ãŒãã¯ã¢ãã€ã«ããã»ããµã®è¶£å³ã§ã¯ãªãããšã瀺ãããŸããã ã¿ãã¬ããã«ã¯ããã¬ãŒã ããªã¢ã«ã¿ã€ã ã§åŠçããæéããããŸããã§ããã
ã¿ãã¬ããã§äœ¿çšãããŠããAtom Z3740ããã»ããµã¯Quick Sync VideoïŒQSVïŒãã¯ãããžãŒããµããŒãããŠãããããlibavcodecã®QSV h264ãã³ãŒããŒã䜿çšããŠã¿ãŸããã é©ããããšã«ã圌ã¯ç¶æ³ãæ¹åããã ãã§ãªãã匷åãªãã¹ã¯ãããPCã§ãé
延ã1.5ç§ã«å¢ãããŸããïŒ ãã ãããã®ã¢ãããŒãã¯CPUã®è² è·ã倧å¹
ã«åæžããŸããã
ffmpegã§ãã³ãŒãã®ããŸããŸãªæ§æãªãã·ã§ã³ãè©ŠããåŸãlibavcodecãæŸæ£ããŠ
Intel Media SDKãçŽæ¥äœ¿çšããããšã決å®ãããŸããã
ç§ãã¡ã«ãšã£ãŠæåã®é©ãã¯ãMedia SDKã䜿çšããŠéçºããããšã決ãã人ãæ¥ãã§èªããããšããææã§ããã éçºè
ã«æäŸãããå
¬åŒã®
äŸã¯ããã¹ãŠãå®è¡ã§ãã匷åãªçµã¿åããã§ããããããææ¡ããã®ã¯å°é£ã§ãã 幞ããªããšã«ã
Intelãã©ãŒã©ã ã§ããã®äŸã«ãäžæºãæ±ããŠããå¿ãåãããã人ã
ãèŠã€ããŸããã 圌ãã¯å€ããããæ¶åãããã
ãã¥ãŒããªã¢ã«ãèŠã€ããŸããã simple_2_decodeã®äŸã«åºã¥ããŠã次ã®ã³ãŒããååŸããŸããã
Intel Media SDKã«ããã¹ããªãŒã ãã³ãŒã mfxStatus sts = MFX_ERR_NONE;
Media SDKã䜿çšããŠãããªãã³ãŒããå®è£
ããåŸãåæ§ã®ç¶æ³ã«çŽé¢ããŸãã-ãããªé
延ã¯1.5ç§ã§ããã å¿
æ»ã«ããã©ãŒã©ã ã«ç®ãåãããšããããªã®ãã³ãŒãã®é
延ãæžããããã®ãã³ããèŠã€ãããŸããã
Media SDK h264ãã³ãŒããŒã¯ããã³ãŒããããã€ã¡ãŒãžãçºè¡ããåã«ãã¬ãŒã ãèç©ããŸãã ãã¹ããªãŒã ã®çµäºããã©ã°ããã³ãŒããŒã«éä¿¡ãããããŒã¿ã®æ§é ïŒmfxBitstreamïŒã«èšå®ãããŠããå Žåãé
延ã¯çŽ0.5ç§ã«æžå°ããããšãããããŸããã
mfx_bitstream.DataFlag = MFX_BITSTREAM_EOS;
ããã«ãã¹ããªãŒã ã®çµããã®ãã©ã°ãèšå®ãããŠããå Žåã§ãããã³ãŒããŒã¯ãã¥ãŒã«5ã€ã®ãã¬ãŒã ãä¿æããããšãå®éšçã«ããã£ãŠããŸãã ãã®çµæããã¹ããªãŒã ã®æåŸããã·ãã¥ã¬ãŒããããã³ãŒããŒã«ãã®ãã¥ãŒãããã¬ãŒã ãåºåãããã³ãŒããè¿œå ããå¿
èŠããããŸããã
if( no_frames_in_queue ) sts = mfx_dec->DecodeFrameAsync(mfx_bitstream, pmfxSurfaces[nIndex], &pmfxOutSurface, &syncp); else sts = mfx_dec->DecodeFrameAsync(0, pmfxSurfaces[nIndex], &pmfxOutSurface, &syncp); if (sts == MFX_ERR_MORE_DATA) { no_frames_in_queue = true; }
ãã®åŸãé
延ã¬ãã«ã¯èš±å®¹å¯èœãªã¬ãã«ãŸã§äœäžããŸããã ç®ã«èŠããªãèŠç·ã
çµè«
ãããªããªã¢ã«ã¿ã€ã ã§ãããŒããã£ã¹ãããã¿ã¹ã¯ãéå§ããæ¢åã®ãœãªã¥ãŒã·ã§ã³ã䜿çšããèªè»¢è»ãªãã§å®è¡ããããšãéåžžã«æåŸ
ããŠããŸããã
ç§ãã¡ã®äž»ãªåžæã¯ãFFmpegãVLCãªã©ã®ãããªãžã£ã€ã¢ã³ãã§ããã 圌ãã¯ç§ãã¡ãå¿
èŠãšããããšïŒãã©ã³ã¹ã³ãŒãã£ã³ã°ãªãã§ãããªãéä¿¡ããïŒãã§ããããã«èŠãããšããäºå®ã«ããããããããããªéä¿¡ã«èµ·å ããé
延ãåãé€ãããšãã§ããŸããã§ããã
mjpg-streamerãããžã§ã¯ãã«ã»ãšãã©ã€ãŸãããã®ã§ãMJPG圢åŒã§ãããªãæŸéãããã®ã·ã³ãã«ããšæ£ç¢ºãªäœæ¥ã«é
äºãããŸããã ãã®ç¹å®ã®åœ¢åŒãçªç¶è»¢éããå¿
èŠãããå Žåã¯ã䜿çšããããšã匷ããå§ãããŸãã ãœãªã¥ãŒã·ã§ã³ãå®è£
ããã®ããã®æ ¹æ ã«ãã£ãããšã¯å¶ç¶ã§ã¯ãããŸããã
éçºã®çµæããããªãé
延ãªãéä¿¡ããããã®ããªã軜éãªãœãªã¥ãŒã·ã§ã³ãåŸãããŸãããéä¿¡åŽãŸãã¯åä¿¡åŽã®ãªãœãŒã¹ãå¿
èŠãšããŸããã Intel Media SDKã©ã€ãã©ãªã¯ããããã¡ãªã³ã°ããã«ãã¬ãŒã ãã¬ã³ããªã³ã°ããããã«å°ãåãå
¥ããªããã°ãªããªãã£ãã«ããããããããããªãã³ãŒãã¿ã¹ã¯ã§éåžžã«åœ¹ç«ã¡ãŸããã