本篇测评由电子发热友的良好测评者“ALSET”提供。
什么是ncnn
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER "arm-poky-linux-gnueabi-gcc")
set(CMAKE_CXX_COMPILER "arm-poky-linux-gnueabi-g++")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_C_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon --sysroot=/home/lutherluo/workspace/fsl-imx-fb/5.10-gatesgarth/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi")
set(CMAKE_CXX_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon --sysroot=/home/lutherluo/workspace/fsl-imx-fb/5.10-gatesgarth/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi")
# cache flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
板上运行测试ncnn
测试基于ncnn的使用
ncnn移植测试总结
由测评者HonestQiao提供
这篇分享,内容较长,且触及到的知识点较多,必要耐烦阅读,上面为详细内容的目次:
媒介:
假如故意检察九游MYC-J1028X中心板及开辟板的官方界面:
明天,九游就在MYC-J1028X开辟板上,搭建Node-RED情况,将开辟板变身为产业物联网控制网关。
许多人理解大概晓得Node-RED,是从智能家居大概小型物联网控制开端的,有的人以为只是一个相似的图形界面编程的东西。
实在,在产业互联网中,Node-RED可以用于数据搜集、联系关系性触发控制、仪表出现等,在低本钱投入的状况下,也能取得较好的结果。
一、安置node-red
安置node-red,可以参考官方的文档:
固然这篇文档,是针对树莓派的,但关于Debian系的体系,都是可以参考的。
-
bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
实行上述下令后,将主动下载安置剧本,启动安置历程,安置历程中的题目,一概选y即可。
安置历程大概耗时比力长,先沏一杯茶大概咖啡,等着吧:
初次安置,大概会遇到莫明其妙[mò míng qí miào]的Node-RED core没装上,中心都没装上,怎样玩?
不论,再次实行安置下令,就能好了:
假如提醒谁人shortcut有题目,先不论,不影响利用。
由于是初次安置,以是实行 node-red admin init 举行初始化:
初始化完成后,就可以实行 node-red start 启动Node-RED了。
正常启动后,就可以经过网址 http://开辟板IP:1880/ 举行拜访了:
输出初始化的时分设置的账户暗码,登录后,依照上面的设置,即可切换到中文界面:
设置完成后,必要革新页面,才干正式失效。
二、体系下令控制LED
如今,九游就可以开端在Node-RED中,开端举行外设控制了。
第一个控制逻辑,照旧点灯,能点灯,九游就乐成一泰半了。
经过检察官方的手册,可以理解到:
九游可以先利用下面的指令,测试可否控制体系的D22-LED。
-
echo 0 | sudo tee /sys/class/leds/d22/brightness
-
echo 1 | sudo tee /sys/class/leds/d22/brightness
三、LED权限设置:
经过检察Node-RED的文档材料,可以理解到,有一个Exec Node,可以用于实行体系的下令,那九游恰好可以利用其来实行下面手册中,控制D22的指令。
要使得平凡用户运转的Node-RED可以控制体系LED,必要在udev中,添加对应的权限处置规矩,不然操纵时将会提醒没有权限。
-
sudo groupadd -f -r leds
-
sudo usermod -a -G leds $USER
-
-
sudo vim /etc/udev/rules.d/99-leds.rules
-
-
SUBSYSTEM=="leds", ACTION=="add", RUN+="/bin/chgrp -R leds /sys%p", RUN+="/bin/chmod -R g=u /sys%p"
-
SUBSYSTEM=="leds", ACTION=="change", ENV{TRIGGER}!="none", RUN+="/bin/chgrp -R leds /sys%p", RUN+="/bin/chmod -R g=u /sys%p"
将下面的最初两行设置,添加到 /etc/udev/rules.d/99-leds.rules 后,必要重启体系才干失效。
友谊提示:相似在udev中举行平凡用户权限的设置,后续另有许多次,肯定要细心设置。
重启后(sudo reboot),可以测试利用平凡用户权限,来操纵LED:
-
echo 0 | tee /sys/class/leds/d22/brightness
-
echo 1 | tee /sys/class/leds/d22/brightness
四、Node-RED控制体系LED
先在Node-RED界面中,参考下图,添加两个inject node,再添加两个Exec Node。
Exec Node的下令局部,参考下图填写,记着一个为echo 0,一个为echo 1,对应熄灭和点亮LED
两个injection Node的设置,辨别如下:
下面的逻辑表现:
五、体系下令控制GPIO:
在官方手册上,有阐明怎样操纵GPIO:
联合开辟板和原理图上九游可以理解到,J18是九游可以利便利用的引脚地区:
J18上可供利用的GPIO对应干系如下:
相似体系LED,假如要在平凡用户下控制GPIO,也必要在udev中举行一些设置,详细设置如下:
-
sudo groupadd -f -r gpio
-
sudo usermod -a -G gpio $USER
-
-
sudo vim /etc/udev/rules.d/99-gpio.rules
-
-
SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", RUN+="/bin/chgrp -R gpio /sys/class/gpio/export /sys/class/gpio/unexport", RUN+="/bin/chmod -R g=u /sys/class/gpio/export /sys/class/gpio/unexport"
-
SUBSYSTEM=="gpio*", KERNEL=="gpio*", ACTION=="add", RUN+="/bin/chgrp -R gpio /sys%p", RUN+="/bin/chmod -R g=u /sys%p"
-
SUBSYSTEM=="gpio*", KERNEL=="gpio*", ACTION=="change", ENV{TRIGGER}!="none", RUN+="/bin/chgrp -R gpio /sys%p", RUN+="/bin/chmod -R g=u /sys%p"
将上述最初三行内容写入/etc/udev/rules.d/99-gpio.rules,然后重启开辟板即可失效。
重启完成后,九游就可以如今下令行下举行测试。
起首依照原理图,将可以用3.3V驱动的LED,毗连到GPIO3_9引脚上。
然后利用上面的下令举行测试:
-
echo 425 > /sys/class/gpio/export
-
echo out > /sys/class/gpio/gpio425/direction
-
-
for i in {1..100};do
-
echo $((i%2)) > /sys/class/gpio/gpio425/value
-
sleep 1
-
done
实行完下令后,毗连到GPIO3_9引脚上的LED,将每秒闪耀一次。
测试控制乐成后,九游就可以到Node-RED中举行控制了。
六、Node-RED控制GPIO
要在Node-Red中控制GPIO,可以安置OPI-GPIO插件,依照以下步调安置即可:
安置完成后,在左边组件选择栏,就会呈现Orange Pi,选择此中的output pin,然后将之前设置的injection 0和1毗连到新添加的控件上,再依照上面的步调,设置对应的GPIO端标语。
由于GPIO3_9对应425,以是pin填写425即可。但Orange Pi在填写后,再次翻开的时分,界面会酿成初始形态,以是务必细心填写。
填写完成,点击右上角的摆设,毗连到GPIO3_9上的LED,就会开端闪耀了,和板子上的D22-LED同步。
七、开辟板上的S3按键利用:
在开辟板上,有一个可供用户编程利用的按键S3:
S3按键,利用体系/dev/input/event0来监听吸收,平凡用户利用,必要做如下设置:
-
sudo usermod -a -G input $USER
-
-
sudo vim /etc/udev/rules.d/99-event.rules
-
-
KERNEL=="event[0-9]*", SUBSYSTEM=="input", TAG+="uaccess"
设置好当前,重启才干失效。
重启后,利用evtest指令测试:
S3按键后,就可以收到按键的音讯了。
为了可以更好的吸收到按键信息,九游必要利用Python去举行检测,这必要利用到python3-evdev库,先安置:
-
pip3 install evdev
然后,利用上面的python剧本举行测试:
-
from evdev import InputDevice
-
from select import select
-
dev = InputDevice('/dev/input/event0')
-
while True:
-
r,w,x=select([dev],[],[])
-
for event in dev.read():
-
print(event)
按下S3按键然后开释,就会收到信息了:
必要留意的是,S3按键利用体系Event吸收,按下去和开释,都市触发一次。
按下去对应:
开释对应:
九游可以将步伐美满一下,间接按键输入1,开释输入0:
-
from evdev import InputDevice
-
from select import select
-
dev = InputDevice('/dev/input/event0')
-
while True:
-
r,w,x=select([dev],[],[])
-
for event in dev.read():
-
if event.code == 2 and event.type == 1:
-
print("value: %d" % event.value)
-
按下S3按键然后开释,就会收到上面的信息了:
如许,九游就预备好将按键值提供应Node-RED利用了。
八、在Node-RED中利用S3按键控制LED:
要在Node-RED中,获取到Python提供的按键值,然后控制LED,必要利用上面的逻辑:
在Node-RED中的控制逻辑如下:
上面举行细致的阐明。
起首,九游再次调解下面的监控剧本,使得监控按键的逻辑,切合实践必要,即:
详细代码如下:
-
from evdev import InputDevice
-
from select import select
-
dev = InputDevice('/dev/input/event0')
-
keypress_times = 0
-
print(keypress_times % 2)
-
while True:
-
r,w,x=select([dev],[],[])
-
for event in dev.read():
-
if event.value == 1:
-
keypress_times = keypress_times + 1
-
print(keypress_times % 2)
-
-
将上述代码保管到 /home/HonestQiao/Projects/event/evdev_key.py (详细途径,请依据你的实践状况设定),然后运转测试:
要在Node-RED中,启动运转下面的监听剧本,必要利用到node-red-node-daemon插件,安置即可:
由于evdev_key.py输入的内容,为【0大概1 并附带回车】,以是Node-RED收到后,必要举行一次转换,才干利用。
依照上面的步调,添加转换控件,并设置恶化换逻辑即可:
然后,添加GPIO3_10对应426引脚控制,并与转换为数字控件举行联系关系:
然后,在添加一个debug控件,以便可以检察到两头历程的数据信息:
点击摆设后,在左边,就能看到调试输入信息了。
实验一下按键,就可以看到剧本输入的字符串信息,曾经转换为数字好的信息,而且GPIO3_10毗连的黄色LED,也可以被正常控制了。
九、Node-RED利用I2C接口读取SHT30温湿度传感器数据:
后面的局部,都是LED控制、GPIO控制、按键读取,绝对比力复杂。
上面,再来一个觉得略微进步一点点的实例,便是利用I2C接口读取SHT30温湿度传感器。
在之前看过的电路原理图中,J18接口上,就有I2C接口。
将I2C接口的SHT30,毗连到J18对应的接口上:
要在平凡用户权限下,利用i2c接口,九游又必要在udev中做一些设置:
-
sudo vim /etc/udev/rules.d/99-i2c.rules
-
-
KERNEL=="i2c-[0-9]*", GROUP="i2c"
将这行内容,写入到/etc/udev/rules.d/99-i2c.rules,然后重启失效。
重启完成后,在下令下下,测试能否可以找到SHT30:
先利用 i2cdetect -l 下令检察一下可供利用的i2c接口:
从下面可以看到,i2c-0、i2c-1可供利用。
然后,在利用 i2cdetect -y 0 和 i2cdetect -y 1 检察i2c挂载的设置装备摆设:
在i2c-1中,有一个44的设置装备摆设,这个正是 SHT30的默许i2c通讯地点。
可以实验,把SHT30连线断开,再利用 i2cdetect -y 1 检察,有什么差别。
在Node-RED中,要读取SHT3X的数据,可以利用 node-red-contrib-sht 插件:
逻辑设置完成,点击右上角的摆设后,调试地区,就会打印出来,实践读取到的温湿度信息了。
对着温湿度传感器哈哈气,就会发明读取到的数值,产生了变革。
十:Node-RED利用仪表盘表现温湿度传感器数据:
Node-RED另有一个诱人又壮大的地方,那便是它不但可以利便你用图形界面设计物联网设置装备摆设的控制交互流程,还可以很利便的利用仪表盘,提供数据检察界面。
上面,我就在上一步读取到温湿度传感器的底子上,再做一个,可以在手机界面上检察拜访的仪表盘。
起首,安置一个dashboard仪表盘控件:
然后,在SHT3X空间上,挂两个change,用于转换温湿度值:
而温湿度值,各挂一个gauge,用于表现终极的数据,其内容,参考如下设置即可:
温度gauge:
在第一次设置gauge的时分,如下面的温度gauge,要点 (4) 进入,设置group节点和Tab节点,详细如下:
颠末以上设置,就可以将温湿度值,输入到仪表盘上了。
为了结果更好,我再添加一个以后日期工夫转换,并利用文本控件表现。
先依照上面的步调,添加一个function控件,别编写转换代码:
-
function formatDate(value) {
-
var date = new Date(value);
-
var y = date.getFullYear(),
-
m = date.getMonth() + 1,
-
d = date.getDate(),
-
h = date.getHours(),
-
i = date.getMinutes(),
-
s = date.getSeconds();
-
if (m < 10) { m = '0' + m; }
-
if (d < 10) { d = '0' + d; }
-
if (h < 10) { h = '0' + h; }
-
if (i < 10) { i = '0' + i; }
-
if (s < 10) { s = '0' + s; }
-
var t = y + '-' + m + '-' + d + ' ' + h + ':' + i + ':' + s;
-
return t;
-
}
-
-
return { payload: formatDate(msg.payload) };
此中的 formatDate() 函数,便是一个js中尺度的把以后工夫戳转换为YYYY-mm-dd HH:MM:SS款式的函数。
这也是Node-RED的一个壮大之处,除了编写好的控件,还可以利用剧本举行两头历程的处置。
设置好了日期工夫转换,再在厥后挂一个text控件,用作表现即可:
所有设计完成后,点击右上角的摆设,就可以利用手机举行检察了。
在手机上,拜访网址 http://开辟板IP:1880/ui ,就能看到如下的界面了:
十一、总结:
这篇分享,基于九游MYC-J1028X开辟板,联合Node-RED,将其变身为产业控制网关。
看到这里,看似分享了不少内容,但触及到Node-RED的局部,只要Node-RED所有功效的万分之一都不到,并且都黑白常底子的利用。
关于九游MYC-J1028X开辟板的利用,也是用到了实践功效的百分之一都不到。
Node-RED另有许多许多许多壮大的功效,可以利便九游疾速的获取内部设置装备摆设的数据,并编写符合的逻辑处置流程来规整数据,并举行数据的出现,大概对内部设置装备摆设举行控制。
而这统统,并不必要分外专业的编程技艺,就可以完成。
基于九游MYC-J1028X开辟板微弱的运算才能,以及丰厚的外设接口,联合Node-RED所构建的产业控制网关,完全可以使用在实践场所中,发扬严重的作用。
将其摆设在产业现场,用于搜集、存储、处置和剖析网络边沿的数据,可以加重对云和数据中心的压力。
这套体系,可以经过机动的I/O简化通讯和控制,对数据举行自动收罗、剖析及过滤、会聚,来可视化现场数据和控制逻辑,既能利便展望性维护,又能展开及时数据处置与决议计划。
这次的板卡测试,是九游MYD-YT507H开辟板的行车记载仪测试体验。
为了又快又好的开辟行车记载仪的实践界面,以及后续举行各挪动平台的App开辟,选择了Flutter。现实证明,坑太多了。不外,跨平台特征,的确好。
# http办事器哀求处置:网页、MJPEG数据流
class CamHandler(BaseHTTPRequestHandler):
def do_GET(self):
# mjpeg推流
if self.path.endswith('.mjpg'):
self.send_response(200)
self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
self.end_headers()
while True:
if is_stop:
break
try:
# rc,img = cameraCapture.read()
rc,img = success,frame
if not rc:
continue
if True:
imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
jpg = Image.fromarray(imgRGB)
tmpFile = BytesIO()
jpg.save(tmpFile,'JPEG')
self.wfile.write(b"--jpgboundary")
self.send_header(b'Content-type','image/jpeg')
self.send_header(b'Content-length',str(tmpFile.getbuffer().nbytes))
self.end_headers()
jpg.save(self.wfile,'JPEG')
else:
img_fps = JPEG_QUALITY_VALUE
img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps]
img_str = cv2.imencode('.jpg', img, img_param)[1].tobytes() # change image to jpeg format
self.send_header('Content-type','image/jpeg')
self.end_headers()
self.wfile.write(img_str)
self.wfile.write(b"
--jpgboundary
") # end of this part
time.sleep(0.033)
except KeyboardInterrupt:
self.wfile.write(b"
--jpgboundary--
")
break
except BrokenPipeError:
continue
return
# 网页
if self.path == '/' or self.path.endswith('.html'):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write(b'
Live video ')self.wfile.write(('
' % self.headers.get('Host')).encode())
self.wfile.write(b'')
return
# websocket办事哀求处置
async def CamTransmitHandler(websocket, path):
print("Client Connected !")
try :
while True:
# rc,img = cameraCapture.read()
rc,img = success,frame
if not rc:
continue
img_fps = JPEG_QUALITY_VALUE
img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps]
encoded = cv2.imencode('.jpg', img, img_param)[1]
data = str(base64.b64encode(encoded))
data = data[2:len(data)-1]
await websocket.send(data)
# cv2.imshow("Transimission", frame)
# if cv2.waitKey(1) & 0xFF == ord('q'):
# break
# cap.release()
except EXCEPTION_CONNECTION_CLOSE as e:
print("Client Disconnected !")
# cap.release()
except:
print("Someting went Wrong !")
cameraCapture = cv2.VideoCapture(CAMERA_NO)
cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 240)
cameraCapture.set(cv2.CAP_PROP_SATURATION, 135)
fps = 30
size=(int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
success,frame = cameraCapture.read()
...
while True:
if is_stop:
success = False
break;
success,frame = cameraCapture.read()
if not success:
continue
time_now = get_current_time()
if time_now["time"] - time_record["time"] >= ROTATE_TIME:
if time_record_prev:
thubm_file = get_file_name(time_record_prev, 'thumbs', 'jpg')
print("[Info] write to thumb: %s" % thubm_file)
if not os.path.isfile(thubm_file):
cv2.imwrite(thubm_file, frame)
time_record = time_now
time_record_prev = get_current_time()
video_file = get_file_name(time_record_prev, 'videos', MEDIA_EXT)
print("[Info] write to video: %s" % video_file)
# encode = cv2.VideoWriter_fourcc(*"mp4v")
encode = cv2.VideoWriter_fourcc(*'X264')
# encode = cv2.VideoWriter_fourcc(*'AVC1')
# encode = cv2.VideoWriter_fourcc(*'XVID')
# encode = cv2.VideoWriter_fourcc(*'H264')
videoWriter=cv2.VideoWriter(video_file, encode,fps,size) # mp4
numFrameRemaining = ROTATE_TIME * fps #摄像头捕捉继续工夫
while success and numFrameRemaining > 0:
videoWriter.write(frame)
success,frame = cameraCapture.read()
numFrameRemaining -= 1
cameraCapture.release()
encode = cv2.VideoWriter_fourcc(*'X264')
,在差别的情况上面,提供的编码方法不完全相反。# -*- coding: utf-8 -*-
import signal
import cv2
import time
from PIL import Image
from threading import Thread
from http.server import BaseHTTPRequestHandler,HTTPServer
from socketserver import ThreadingMixIn
from io import BytesIO
import os
import sys
import websockets
import asyncio
import base64
import ctypes
import inspect
CAMERA_NO = 2
ROTATE_TIME = 120
MJPEG_ENABLE = 1
WEBSOCKET_ENABLE = 1
MJPEG_SERVER_PORT = 28888
WEBSOCKET_PORT = 28889
JPEG_QUALITY_VALUE = 65
STORE_DIR = "./data/" if os.uname()[0] == 'Darwin' else "/sdcard/data/"
MEDIA_EXT = "mkv"
EXCEPTION_CONNECTION_CLOSE = websockets.exceptions.ConnectionClosed if sys.version[:3] == '3.6' else websockets.ConnectionClosed
def _async_raise(tid, exctype):
"""raises the exception, performs cleanup if needed"""
try:
tid = ctypes.c_long(tid)
if not inspect.isclass(exctype):
exctype = type(exctype)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
if res == 0:
# pass
raise ValueError("invalid thread id")
elif res != 1:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
except Exception as err:
print(err)
def stop_thread(thread):
"""停止线程"""
_async_raise(thread.ident, SystemExit)
# 信号处置回调
def signal_handler(signum, frame):
# global cameraCapture
# global thread
# global server
# global is_stop
# global success
print('signal_handler: caught signal ' + str(signum))
if signum == signal.SIGINT.value:
print('stop server:')
is_stop = True
success = False
print("mjpeg server.socket.close...")
server.socket.close()
print("mjpeg server.shutdown...")
server.shutdown()
print("ws server.socket.close...")
server_ws.ws_server.close()
time.sleep(1)
# print("ws server.shutdown...")
# await server_ws.ws_server.wait_closed()
print("mjpeg thread.shutdown...")
thread_mjpeg.join()
print("ws loop.shutdown...")
# event_loop_ws.stop()
event_loop_ws.call_soon_threadsafe(event_loop_ws.stop)
time.sleep(1)
# print("ws thread.shutdown...")
# stop_thread(thread_ws)
# time.sleep(1)
# print(server)
# print(server_ws)
print(thread_mjpeg.is_alive())
print(thread_ws.is_alive())
print(event_loop_ws.is_running())
# thread_ws.join()
print("cameraCapture.release...")
cameraCapture.release()
print("quit...")
# print(server_ws)
sys.exit(0)
# http办事器哀求处置:网页、MJPEG数据流
class CamHandler(BaseHTTPRequestHandler):
def do_GET(self):
# mjpeg推流
if self.path.endswith('.mjpg'):
self.send_response(200)
self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
self.end_headers()
while True:
if is_stop:
break
try:
# rc,img = cameraCapture.read()
rc,img = success,frame
if not rc:
continue
if True:
imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
jpg = Image.fromarray(imgRGB)
tmpFile = BytesIO()
jpg.save(tmpFile,'JPEG')
self.wfile.write(b"--jpgboundary")
self.send_header(b'Content-type','image/jpeg')
self.send_header(b'Content-length',str(tmpFile.getbuffer().nbytes))
self.end_headers()
jpg.save(self.wfile,'JPEG')
else:
img_fps = JPEG_QUALITY_VALUE
img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps]
img_str = cv2.imencode('.jpg', img, img_param)[1].tobytes() # change image to jpeg format
self.send_header('Content-type','image/jpeg')
self.end_headers()
self.wfile.write(img_str)
self.wfile.write(b"
--jpgboundary
") # end of this part
time.sleep(0.033)
except KeyboardInterrupt:
self.wfile.write(b"
--jpgboundary--
")
break
except BrokenPipeError:
continue
return
# 网页
if self.path == '/' or self.path.endswith('.html'):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write(b'
Live video ')self.wfile.write(('
' % self.headers.get('Host')).encode())
self.wfile.write(b'')
return
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""Handle requests in a separate thread."""
# 启动MJPEG办事
def mjpeg_server_star():
global success
global server
global thread_mjpeg
try:
server = ThreadedHTTPServer(('0.0.0.0', MJPEG_SERVER_PORT), CamHandler)
print("mjpeg server started: http://0.0.0.0:%d" % MJPEG_SERVER_PORT)
# server.serve_forever()
thread_mjpeg = Thread(target=server.serve_forever);
thread_mjpeg.start()
except KeyboardInterrupt:
print("mjpeg server stoping...")
server.socket.close()
server.shutdown()
print("mjpeg server stoped")
# websocket办事哀求处置
async def CamTransmitHandler(websocket, path):
print("Client Connected !")
try :
while True:
# rc,img = cameraCapture.read()
rc,img = success,frame
if not rc:
continue
img_fps = JPEG_QUALITY_VALUE
img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps]
encoded = cv2.imencode('.jpg', img, img_param)[1]
data = str(base64.b64encode(encoded))
data = data[2:len(data)-1]
await websocket.send(data)
# cv2.imshow("Transimission", frame)
# if cv2.waitKey(1) & 0xFF == ord('q'):
# break
# cap.release()
except EXCEPTION_CONNECTION_CLOSE as e:
print("Client Disconnected !")
# cap.release()
except:
print("Someting went Wrong !")
# websocket办事器启动
def websocket_server_start():
global thread_ws
global server_ws
global event_loop_ws
event_loop_ws = asyncio.new_event_loop()
def run_server():
global server_ws
print("websocket server started: ws://0.0.0.0:%d" % WEBSOCKET_PORT)
server_ws = websockets.serve(CamTransmitHandler, port=WEBSOCKET_PORT, loop=event_loop_ws)
event_loop_ws.run_until_complete(server_ws)
event_loop_ws.run_forever()
thread_ws = Thread(target=run_server)
thread_ws.start()
# try:
# yield
# except e:
# print("An exception occurred")
# finally:
# event_loop.call_soon_threadsafe(event_loop.stop)
# 获取存储的文件名
def get_file_name(time_obj, path, ext):
file_name_time = "%04d-%02d-%02d_%02d-%02d-%02d" % (time_obj["year"], time_obj["month"], time_obj["day"], time_obj["hour"], time_obj["min"], 0)
return '%s/%s/%s.%s' % (STORE_DIR, path, file_name_time, ext)
# 获取以后整分工夫
def get_current_time():
time_now = time.localtime()
time_int = int(time.time())
return {
"year": time_now.tm_year,
"month": time_now.tm_mon,
"day": time_now.tm_mday,
"hour": time_now.tm_hour,
"min": time_now.tm_min,
"sec": time_now.tm_sec,
"time": time_int - time_now.tm_sec
}
# 设相信号回调
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# 捕捉摄像头
cameraCapture = cv2.VideoCapture(CAMERA_NO)
# 摄像头参数设置
cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 240)
cameraCapture.set(cv2.CAP_PROP_SATURATION, 135)
fps = 30
size=(int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
# 读取捕捉的数据
success,frame = cameraCapture.read()
if not success:
print("camera start failed.")
quit()
is_stop = False
server = None
server_ws = None
event_loop_ws = None
thread_mjpeg = None
thread_ws = None
mjpeg_server_star()
websocket_server_start()
print("record server star:")
thubm_file = None
video_file = None
time_start = int(time.time())
time_record = {"time":0}
time_record_prev = None
while True:
if is_stop:
success = False
break;
success,frame = cameraCapture.read()
if not success:
continue
time_now = get_current_time()
if time_now["time"] - time_record["time"] >= ROTATE_TIME:
if time_record_prev:
thubm_file = get_file_name(time_record_prev, 'thumbs', 'jpg')
print("[Info] write to thumb: %s" % thubm_file)
if not os.path.isfile(thubm_file):
cv2.imwrite(thubm_file, frame)
time_record = time_now
time_record_prev = get_current_time()
video_file = get_file_name(time_record_prev, 'videos', MEDIA_EXT)
print("[Info] write to video: %s" % video_file)
# encode = cv2.VideoWriter_fourcc(*"mp4v")
encode = cv2.VideoWriter_fourcc(*'X264')
# encode = cv2.VideoWriter_fourcc(*'AVC1')
# encode = cv2.VideoWriter_fourcc(*'XVID')
# encode = cv2.VideoWriter_fourcc(*'H264')
videoWriter=cv2.VideoWriter(video_file, encode,fps,size) # mp4
numFrameRemaining = ROTATE_TIME * fps #摄像头捕捉继续工夫
while success and numFrameRemaining > 0:
videoWriter.write(frame)
success,frame = cameraCapture.read()
numFrameRemaining -= 1
cameraCapture.release()
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / "static"
]
# 媒体文件寄存目次,以及缩略图和视频文件的后缀
THUMB_HOME_DIR = "%s/%s/data/thumbs/" % (BASE_DIR, STATIC_URL)
VIDEO_HOME_DIR = "%s/%s/data/videos/" % (BASE_DIR, STATIC_URL)
IMG_FILTER = [".jpg"]
MEDIA_FILTER = [ ".mkv"]
import json
from django.shortcuts import render, HttpResponse
from rest_framework.response import Response
from rest_framework.permissions import AllowAny
from rest_framework.decorators import api_view, permission_classes
import os
from django.conf import settings
THUMB_HOME_DIR = settings.THUMB_HOME_DIR
VIDEO_HOME_DIR = settings.VIDEO_HOME_DIR
IMG_FILTER = settings.IMG_FILTER
MEDIA_FILTER = settings.MEDIA_FILTER
# Create your views here.
def hello_django(request):
str = '''[
{
"id": 1,
"time": "2022-07-28 21:00",
"title": "2022-07-28 21:00",
"body": "videos/2022-07-28_2100.mp4"
},
{
"id": 2,
"time": "2022-07-28 23:00",
"title": "2022-07-28 23:00",
"body": "videos/2022-07-28_2300.mp4"
},
{
"id": 3,
"time": "2022-07-28 25:00",
"title": "2022-07-28 25:00",
"body": "videos/2022-07-28_2500.mp4"
}
]'''
_json = json.loads(str)
return HttpResponse(json.dumps(_json), content_type='application/json')
def history_list(request):
next = request.GET.get("next", '')
print(f"thumb next = {next}")
path = "/".join(request.path.split("/")[3:])
print(f"thumb request.path= {request.path}")
print(f"thumb path = {path}")
#print os.listdir(FILE_HOME_DIR+".none/")
data = {"files":[], "dirs":[]}
print(data)
child_path = THUMB_HOME_DIR+next
print(f"child_path = {child_path}")
data['cur_dir'] = path+next
print(data)
for dir in os.listdir(child_path):
if os.path.isfile(child_path+"/"+dir):
if os.path.splitext(dir)[1] in IMG_FILTER:
data['files'].append(dir)
else:
data['dirs'].append(dir)
print(data)
data['files']=sorted(data['files'])
data['files'].reverse()
data['infos'] = []
for i in range(0,len(data['files'])):
thumb_name = data['files'][i]
video_name = thumb_name.replace('.jpg', MEDIA_FILTER[0])
file_time = thumb_name.replace('.jpg', '').replace('_', ' ')
data['infos'].append(
{
"id": i,
"time": file_time,
"title": file_time,
"body": thumb_name,
'thumb': thumb_name,
'video': video_name
}
)
return Response(data['infos'], status = 200)
hello_django
是最开端学习利用的,前往写去世的json数据。history_list
,则是主动遍历缩略图文件夹,获取缩略图文件信息,并天生所必要的json数据款式。下载代码,进入manage.py地点的目次后,实行上面的下令即可启动:
Scaffold
来模仿手机/Pad的操纵界面,详细界面如下:
及时画面:
汗青记载列表:
fetch
is widely supported enough to use · Issue #595 · dart-lang/http (github.com)最次要的,对九游MYD-YT507开辟板有了深化的理解,举行了实践的使用。作为一款车规级处置器T507的开辟板,名不虚传!
这次的板卡测试,是九游MYD-YT507H开辟板的各项功能测试。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
从CoreMark的底子功能测试,包罗EMMC、RAM的存储功能测试,以及Qt的表现测试来看,九游MYD-YT507H开辟板的相干功能都黑白常高的,可以满意边沿盘算,人机交互,智能终端等各种高功能使用场景需求。
这次板卡的测试,是怎样在Ubuntu创建xfce桌面情况,以及怎样近程穿透拜访家中的九游MYD-YT507H开辟板。
sudo apt update
sudo apt upgrade
2.安置locales:
# 安置
sudo apt install locales
# 设置:安置历程中,依照提醒,选择 488. zh_CN.UTF-8 UTF-8、3. zh_CN.UTF-8
sudo dpkg-reconfigure locales
# 设置体系全局locale,依照如下信息举行设置
sudo vim /etc/environment
LANGUAGE="zh_CN.UTF-8:zh:en_US.UTF-8:en"
LANG="zh_CN.UTF-8"
# 设置以后用户locale,依照如下信息举行设置
vim ~/.bashrc
export LC_ALL="zh_CN.UTF-8"
export LANG="zh_CN.UTF-8"
export LANGUAGE="zh_CN.UTF-8:zh:en_US.UTF-8:en"
# 测试能否失效:设置失效后,实行data指令应前往中文
source ~/.bashrc
date
4.安置文泉驿中笔墨体:
sudo apt install -y fonts-arphic-ukai fonts-arphic-gkai00mp fonts-arphic-bkai00mp
sudo apt install -y xfonts-wqy ttf-wqy-microhei ttf-wqy-zenhei
5.安置xfce4:
# 安置历程中,依照提醒,选择:56. 汉语、1. 汉语
sudo apt install xfce4 xfce4-terminal
6.修正xorg设置装备摆设:
vim /etc/X11/Xwrapper.config
# 修正为如下行
allowed_users = anybody
7.启动xfce4:
起首将开辟板用HDMI线毗连到表现器;我没有独立的表现器,以是毗连到了电视;然后实行:
startxfce4
运转后,xfce4桌面会启动;没想到,电视辨别率太低,表现结果欠安: