使用 Intel® 硬件和软件开发视觉零售解决方案
零售工作坊:使用基于 Intel® 的零售解决方案进行实践学习。
动手实践实验室
了解用于构建高级、高性能视频播放、高级远程管理和视频分析的基于英特尔®的软件和硬件工具/SDK。
章节概述和目标
在本节中,我们将探讨完成本课程中实验室所需的硬件和软件列表。
学完本模块后,您应该能够
- 了解所需的硬件和软件
- 安装 Ubuntu* 16.04
- 安装英特尔®媒体服务器工作室
- 安装支持 Python* 的 OpenCV
硬件要求
- 搭载第五代英特尔®酷睿™处理器的英特尔® NUC 套件
- 确保您的设备支持英特尔®博锐™技术。本课程材料在 英特尔® NUC 套件 NUC5i5MYHE 上进行了测试。
软件和操作系统要求
- Ubuntu 16.04
- 英特尔®媒体服务器工作室
- 支持 Python 的 OpenCV
建议在运行英特尔®媒体服务器工作室和 OpenCV 安装时使用开放网络,因为公司代理规则和防火墙设置可能会阻止下载必要的文件。
- 从 http://old-releases.ubuntu.com/releases/16.04.1/ubuntu-16.04-desktop-amd64.iso 安装 Ubuntu 16.04
- 更新 Ubuntu 软件包。警告:不要选择升级选项。
$sudo apt-get update
注意:如果在更新过程中遇到核心转储,请运行以下命令,然后运行 apt-get update
$sudo apt-get purge libappstream3
-
从 https://software.intel.com/en-us/intel-media-server-studio 下载适用于 Linux 的英特尔®媒体服务器工作室
- 按照 入门指南 - Linux* 安装 中记录的最新安装过程进行操作。您应该使用安装文档中的“通用”安装步骤在 Ubuntu 上安装。
- 重启系统。
- 从 https://opencv.ac.cn/releases.html 安装支持 Python 的 OpenCV
- 重启系统。
-
系统分析器:系统分析器工具是一个 Python 脚本,可从以下位置下载:https://software.intel.com/en-us/articles/mss-sys-analyzer-linux。
-
通过创建适当的目录结构,将 sys_analyzer_linux.py python 脚本复制到 /home/intel/workshop 文件夹。
-
从 https://github.com/Intel-Media-SDK/samples 下载示例
将示例解压到 /home/intel/Documents/workshop/msdk_samples/
英特尔®媒体服务器工作室安装
- 执行
$vainfo
并确保没有错误 - Execute
$cd /opt/intel/mediasdk/samples/_bin/x64 $./sample_decode h264 -i ../content/test_stream.264 -hw -vaapi -r
- 查看终端。您应该看到硬件 IMPL 为“hw(hardware)”,vaapi 为解码帧的内存。
OpenCV 安装
- 从终端运行 python。
$python
- 键入:
import cv2
应该没有错误。 - 键入:
print cv2.__version__
。它应该显示 cv2 版本
<!-- 实验室总结 -->
阅读下一个实验室
恭喜!您已成功设置您的开发机器以进行实验室。
概述
这些实验室演示了使用英特尔®工具和技术增强视频性能。
为什么要增强视频性能?
视频处理管道充满了计算密集型任务,例如解码、预处理、后处理、编码等。为了提高整体视频处理性能,各个子系统必须利用底层硬件和相关软件的完整计算能力。为此,英特尔开发了硬件和软件优化。例如,我们将在视觉零售用例中使用 英特尔®媒体服务器工作室。
英特尔®媒体服务器工作室是一套库、工具、头文件和示例代码文件,它们定义了用于在英特尔®平台上开发消费级和专业级媒体应用程序的跨平台 API。它提供对英特尔®快速同步视频(使用英特尔®处理器显卡进行硬件加速编解码器)的访问。这些允许应用程序开发人员加速视频播放、编码、处理和媒体转换。适用于 Windows 的英特尔®媒体服务器工作室有助于交付桌面应用程序,例如视频播放器、编辑器和视频会议客户端。其对应的适用于嵌入式 Linux 的英特尔®媒体服务器工作室支持数字安全和监控系统的开发,并允许联网汽车制造商提供智能摄像头、信息娱乐和集群显示解决方案。
Linux 中的硬件加速由视频加速 API (VA API) 支持。VA API 及其免费开源库 (libVA) 均免版税,并根据 MIT 许可证分发。VA API 允许终端用户软件(例如 VLC 媒体播放器或 GStreamer)访问可用的视频加速硬件,例如 PureVideo(通过 libva-vdpau 驱动程序,它根据 VDPAU 实现 VA API)或统一视频解码器。该 API 启用并提供对硬件加速视频处理的访问,使用图形处理单元 (GPU) 等硬件通过将处理从中央处理单元 (CPU) 卸载来加速视频编码和解码。VA API 规范最初由英特尔为其 GMA(图形媒体加速器)系列 GPU 硬件设计,其特定目的是最终取代 XvMC 标准作为 Microsoft Windows* DirectX 视频加速 (DxVA) API 的默认 Unix* 多平台等效项,但今天该 API 不再仅限于英特尔®硬件或 GPU。其他硬件和制造商可以自由使用此开放标准 API,以便在自己的硬件上进行硬件加速视频处理,而无需支付版税。
本节探讨安装在您计算机上的英特尔®媒体服务器工作室相关软件包。它还涵盖了相关的定制应用程序,例如安装包中捆绑的示例解码器。
通过利用英特尔®媒体服务器工作室的强大功能,您将学习将视频相关负载卸载到 GPU,从而释放大约 60-70% 的 CPU 利用率。这些 CPU 周期现在可以用于运行其他应用程序或视频分析。事实上,我们将在另一节中介绍视频分析。
探索
- 本节首先探索和理解安装在您计算机上的英特尔®媒体服务器工作室相关软件包。它还涵盖了相关的定制应用程序,例如安装包中捆绑的示例解码器。
- 了解基于硬件和软件的编码/解码之间的性能差异。
观察
- 使用系统性能监控工具观察各种英特尔®媒体 SDK 操作之间的性能差异。
- 观察软件和硬件加速模式下 GPU 和 CPU 的利用率。
学习成果
学完本模块后,您应该对英特尔®媒体服务器工作室、安装结构以及所选应用程序的性能增强有基本了解。
机器上安装的软件包
- 英特尔®媒体服务器工作室
默认安装位置:/opt/intel/mediasdk/
- 英特尔®媒体服务器工作室示例应用程序
64 位架构的预构建示例位于 /opt/intel/mediasdk/samples/
- 英特尔®媒体服务器工作室文档:/opt/intel/mediasdk/doc/
Commands
$ls /opt/intel/mediasdk/ $ls /opt/intel/mediasdk/samples/ $ls /opt/intel/mediasdk/doc/
系统分析器
系统分析器工具报告有关 CPU、GPU 和英特尔®媒体服务器工作室组件的以下信息。
- 平台就绪情况:检查处理器是否具有必要的 GPU 组件
- 操作系统就绪情况:检查操作系统是否能看到 GPU,以及它是否具有所需的 glibc/gcc 级别
- 检查英特尔®媒体服务器工作室/英特尔® OpenCL™ 应用程序 SDK 组件是否成功安装
- 运行冒烟测试程序并验证英特尔®媒体服务器工作室和 OpenCL™
Run
$cd /home/intel/workshop $python sys_analyzer_linux.py
性能监控
在继续使用英特尔®媒体服务器工作室示例程序之前,我们需要一些性能监控工具。
打开性能监控工具,如图所示
此工具用于比较英特尔®媒体服务器工作室中软件和硬件解码处理的 CPU 性能。
注意:如果您在下面的解码程序旁边运行任何其他程序,它们的进程将被添加到 CPU、GPU 和内存利用率结果中。
因此,这可能会给出不正确的结果。在运行此测试之前关闭所有其他程序。然后,从系统监控工具观察 sample_decode 进程性能。
解码原始视频
英特尔®媒体服务器工作室附带了一些演示各种功能的基本示例。这里我们使用一个控制台应用程序,它将基本压缩视频流解码为原始帧。
在运行这些示例时,请务必查看性能参数。这可以说明软件和硬件加速模式之间的差异。
打开新终端并更改目录
$cd /opt/intel/mediasdk/samples/
案例 1:执行以下命令进行软件实现
在此示例中,-sw 代表基于软件的加速,-r 代表渲染输出。
$./sample_decode h264 -i ../content/test_stream.264 -sw -r
注意:这些是非常小的视频片段,它们可能会在您注意到之前关闭。尝试下载更大的 H264 文件并尝试此应用程序。
案例 2:执行以下命令进行硬件加速
在此示例中,我们指示应用程序使用 vaapi 内存类型。如果您不指定,则应用程序将默认使用系统内存。-hw 代表硬件加速。
$./sample_decode h264 -i ../content/test_stream.264 -vaapi -hw -r
如果您希望查看所有可用的解码选项,请键入 ./sample_decode
编码原始视频帧
sample_encode 是另一个控制台应用程序,它将原始视频帧编码为基本压缩流。
案例 1:执行以下命令进行软件实现
我们正在传递一个输入原始视频流并将其转换为 h264 格式的基本流。
我们为此转换指定宽度、高度和帧率。您可以通过在终端键入 ./sample_encode 来查看所有可用的开关。
$./sample_encode h264 -nv12 -i /home/intel/Videos/test_stream.yuv -o /home/intel/Videos/sw_out.h264 -w 176 -h 96 -f 60 -sw
从系统监视器观察 CPU 利用率。
案例 2:执行以下命令进行硬件加速
$./sample_encode h264 -nv12 -i /home/intel/Videos/test_stream.yuv -o /home/intel/Videos/hw_out.h264 -w 176 -h 96 -f 60 -hw
要查看转换后的 h264 文件,请按如下方式运行解码示例
$./sample_decode h264 -i /home/intel/Videos/hw_out.h264 -vaapi -hw -r
经验教训
- 探索了英特尔®媒体服务器工作室示例应用程序。
- 视频解码和编码过程的性能监控。
目标
引言
在此实验室中,我们将构建一个自定义控制台应用程序,该应用程序解码基本压缩视频流并将其渲染到屏幕上
视频解码过程
- 设置参数以解码管道。
- 初始化解码器。
- 逐帧解码。
- 一旦到达流的末尾,释放所有内存分配。
观察
传递与“sInputParams”参数关联的不同参数并观察差异。
学习成果
学完本模块后,您应该对如何使用英特尔®媒体服务器工作室构建视频解码解决方案有基本了解。
构建新样本
我们将修改现有的英特尔®媒体服务器工作室解码示例,以避免 cmake 步骤。
导航到 workshop/msdk_samples/samples 目录
$cd /home/[user]/Documents/workshop/msdk_samples/samples
复制并粘贴 sample_decode 文件夹,并将其重命名为 custom_decode。
$sudo cp -R sample_decode custom_decode
删除此 custom_decode 项目中的 sample_decode.cpp 和 CMakeLists.txt 文件。
$cd custom_decode $cd src $sudo rm -rf sample_decode.cpp CMakeLists.txt
创建新的 custom_decode.cpp 文件以输入您的自定义解码程序。
$sudo gedit custom_decode.cpp
。您也可以在这里使用任何您喜欢的文本编辑器。
使用 Ctrl+S 保存此 custom_decode.cpp。
头文件包含
打开 custom_decode.cpp 文件,按照以下步骤中的代码完成操作
包含 pipeline_decode.h 和 sstream 头文件。pipeline_decode 具有 CDecodingPipeline
类,该类执行与解码过程相关的所有关键任务。
#include "pipeline_decode.h" #include <sstream>
输入处理
定义一个接受 sInputParams
结构作为参数的方法 InputSetup()
。
此方法首先检查输入结构的完整性。
然后您可以设置视频类型、内存类型、硬件加速、异步深度因子、模式等。
代码块中注释了其他可能的参数值。尝试通过更改参数值来使用不同的选项。
它还将输入 h264 文件路径写入参数列表。
mfxStatus InputSetup(sInputParams* pParams) { //Check the pParams pointer MSDK_CHECK_POINTER(pParams, MFX_ERR_NULL_PTR); //Set the Video type: //MFX_CODEC_AVC for H264 codec //MFX_CODEC_JPEG for JPEG codec pParams->videoType = MFX_CODEC_AVC; msdk_opt_read(MSDK_STRING("/opt/intel/mediasdk/samples/content/test_stream.h264"), pParams->strSrcFile); //Set the memory type: //D3D11_MEMORY for Directx11 //D3D9_MEMORY for Directx9 //SYSTEM_MEMORY for System Memory pParams->memType = D3D9_MEMORY; //For VAAPI //set hardware implementation as default //Software implementation can be tried by setting this to false. pParams->bUseHWLib = true; //Depth of asynchronous pipeline, this number can be tuned to achieve better performance. pParams->nAsyncDepth = 4; //Set the eWorkMode from: //MODE_PERFORMANCE = enable performance mode, //MODE_RENDERING = Render output on the display, //MODE_FILE_DUMP = Dump the output to a file. pParams->mode = MODE_RENDERING; pParams->libvaBackend = MFX_LIBVA_X11; //Some other parameters which can be explored further are: /*bIsMVC ; // true if Multi-View Codec is in use bLowLat; // true if low latency mode needs to be enabled nMaxFPS; //maximum of frames per second that can be rendered */ return MFX_ERR_NONE; }
初始化 CDecodingPipeline
变量,该变量主要负责初始化 Media SDK 上下文、读取输入文件、解码等。
然后设置输入参数并执行错误检查。
int main() { // input parameters sInputParams Params; // pipeline for decoding, includes input file reader, decoder and output file writer CDecodingPipeline Pipeline; // return value check mfxStatus sts = MFX_ERR_NONE; //Setup your input parameters. sts = InputSetup(&Params); MSDK_CHECK_PARSE_RESULT(sts, MFX_ERR_NONE, 1);
解码管道
初始化解码管道并检查错误状态。
继续在主函数中编码
//Initialise the Decode pipeline sts = Pipeline.Init(&Params); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, 1); //print stream info Pipeline.PrintInfo(); msdk_printf(MSDK_STRING("Decoding started\n"));
主解码循环
现在让我们循环遍历视频中的所有帧,使用 Pipeline.RunDecoding()
对它们进行解码
MSS 中的每个方法都会返回一个状态。这些状态可能是不兼容的视频参数、丢失的设备、失败的设备等。
您根据每个函数执行的返回消息进行操作。如果它要求更多表面,则提供更多表面;如果它要求更多帧,则提供更多帧。
在出现硬件错误时使用 Pipeline.ResetDevice
重置设备。
如果没有错误,它将把标志设置为 MFX_ERR_NONE
最后,清除所有解码缓冲区并使用 Pipeline.ResetDecoder(&Params);
移动到下一帧
继续在主函数中进行以下编码
for (;;) { //Decode frame by frame sts = Pipeline.RunDecoding(); if (MFX_ERR_INCOMPATIBLE_VIDEO_PARAM == sts || MFX_ERR_DEVICE_LOST == sts || MFX_ERR_DEVICE_FAILED == sts) { if (MFX_ERR_INCOMPATIBLE_VIDEO_PARAM == sts) { msdk_printf(MSDK_STRING("\nERROR: Incompatible video parameters detected. Recovering...\n")); } else { msdk_printf(MSDK_STRING("\nERROR: Hardware device was lost or returned unexpected error. Recovering...\n")); //Reset device in case of hardware error sts = Pipeline.ResetDevice(); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, 1); } //Clear all decode buffer and move to next frame. sts = Pipeline.ResetDecoder(&Params); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, 1); continue; } else { MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, 1); break; } } msdk_printf(MSDK_STRING("\nDecoding finished\n")); return 0; }// End of main
使用 CTRL+S 保存文件。
配置并生成解决方案
导航到 custom_decode 目录并创建 CMakeLists 文件
$cd /home/[user]/Documents/workshop/msdk_samples/samples/custom_decode $sudo gedit CMakeLists.txt
确保您的 CMakeLists.txt 文件内容与以下内容匹配
include_directories ( ${CMAKE_CURRENT_SOURCE_DIR}/../sample_common/include ${CMAKE_CURRENT_SOURCE_DIR}/../sample_misc/wayland/include ${CMAKE_CURRENT_SOURCE_DIR}/include ) list( APPEND LIBS_VARIANT sample_common ) set(DEPENDENCIES libmfx dl pthread) make_executable( shortname universal "nosafestring" ) install( TARGETS ${target} RUNTIME DESTINATION ${MFX_SAMPLES_INSTALL_BIN_DIR} )
按如下方式使用 build.pl 脚本生成、清理和构建项目
cd /home/[user]/Documents/workshop/msdk_samples/samples/ $perl build.pl --cmake=intel64.make.debug --build --clean $make -j4 -C __cmake/intel64.make.debug
最终结果应该显示 state: ok
名为 __cmake 的新文件夹将包含可执行文件。按如下方式导航到该文件夹
$cd __cmake/intel64.make.debug/__bin/debug/
执行 custom_decode
$./custom_decode
它应该显示屏幕上渲染的视频,并启用自定义解码中的设置。
概述
远程管理部分旨在演示英特尔®博锐™技术的扩展功能,英特尔®博锐™技术是英特尔用于大量计算机硬件技术的营销术语,包括超线程、英特尔®睿频加速 Max 技术 3.0、用于 IA-32 的英特尔®虚拟化技术 (Intel® VT)、英特尔® 64 和英特尔®架构 (Intel® VT-x)、用于定向 I/O 的英特尔®虚拟化技术 (Intel® VT-d)、英特尔®可信执行技术 (Intel® TXT) 和英特尔®主动管理技术。
为什么选择使用英特尔®博锐™技术进行远程管理?
英特尔®博锐™平台由硬件、BIOS 扩展和应用程序组成,为强大可靠的零售应用程序提供解决方案。
本节将为您提供亲身体验,了解如何启用英特尔® AMT、浏览英特尔®博锐™平台和模式,并解释如何使用英特尔® Mesh Commander 等桌面工具管理远程系统。它还演示了如何使用 Mesh Central 等开源基于云的解决方案来存储数据。
目标
本指南旨在作为在您的环境中测试英特尔®博锐™技术系统的起点。
它将指导您完成使用自己的网络环境设置“沙盒”测试环境的过程,以便您可以在英特尔®博锐™技术上测试您的特定用例,最终降低总体支持成本和昂贵的服务/卡车派遣费用。
启用英特尔®主动管理技术的第一步是安装英特尔® AMT 代理。在本节中,<!--我们将创建一个 USB 驱动器,它将把英特尔® AMT 代理安装到主机系统上。--> 我们将手动从英特尔®管理引擎 BIOS 扩展 (Intel® MEBX) 配置 AMT。然后我们将通过访问 Web 浏览器并访问基于英特尔® AMT 固件的 Web 配置控制台来验证代理是否已正确安装/启用。
配置英特尔® AMT
首先在支持英特尔®博锐™技术的设备上执行以下操作。
在开机期间,英特尔® AMT 平台会显示 BIOS 启动屏幕,然后处理英特尔® MEBx。在此过程中,您可以访问英特尔® MEBx;但是,方法取决于 BIOS 供应商。这里讨论了一些方法。
- 大多数 BIOS 供应商通过一次性启动菜单将条目添加到 CSME。选择相应的键(通常是 Ctrl+P)并按照提示操作。
- 一些 OEM 平台会在 POST 后提示您按 <Ctrl+P>。当您按 <Ctrl+P> 时,控制权会传递给英特尔® MEBx (CSME) 主菜单。
- 一些 OEM 将 CSME 配置集成到 BIOS 中(不常见)。
- 一些 OEM 在 BIOS 中有一个选项可以显示/隐藏 <Ctrl+P> 提示,因此如果一次性启动菜单中没有该提示,请检查 BIOS 以激活 CTRL+P。
输入 CSME 默认密码 admin
- 更改默认密码(继续操作所需)。
- 新值必须是强密码。
- 它应该至少包含一个大写字母、一个小写字母、一个数字和一个特殊字符,并且至少八个字符。
- 管理控制台应用程序可以更改英特尔® AMT 密码,而无需修改 CSME 密码。
记住您的密码。如果忘记,则必须通过短接 CMOS 电池来重置密码。这是一项繁琐的任务。
- 使用 Esc 键返回上一个菜单
- 选择英特尔® AMT 配置。
- 选择/验证管理功能选择是否启用。
- 在英特尔® MEBX 网络设置菜单下,选择“TCP/IP 设置”并按 Enter。
- 英特尔网络设置菜单更改为 TCP/IP 设置页面。
- 转到有线 LAN IPV4 配置。在 TCP/IP 设置下,选择“有线 LAN IPV4 配置”并按 Enter。
- 启用 DHCP。
- 启用网络访问选项。
- 按 Esc 键转到退出屏幕。
- 选择“Y”以确认激活接口。
- 退出 CSME。
使用 Web 浏览器连接到英特尔®主动管理技术 Web 界面
要使用英特尔®主动管理技术 Web 界面,请打开浏览器并访问英特尔® NUC 的 IP 地址(或使用 localhost)。端口号是16992
当提示输入用户名/密码时,输入 admin
作为用户名,输入 <您的密码>
作为密码
您现在已连接。请探索不同的部分。
概述
Mesh Commander 是一款提供使用英特尔®主动管理技术界面的应用程序。其目的是使通过 Internet 进行硬件配置变得容易。
MeshCommander 主要用于设备的点对点远程管理。目前支持的功能包括
- 硬件 KVM 查看器
- 通过 LAN 串行终端
- IDE-R 支持
- 电源控制
- 事件查看器
- 审计日志查看器
- 硬件资产
- 账户管理
- 网络设置
- Wi-Fi 管理
- 用户同意和控制
- 证书和 TLS 管理
- CIRA(客户端发起远程访问)和环境检测
- WSMAN 浏览器
MeshCommander 实用程序应安装在任何其他 Windows* 机器上,例如您的个人笔记本电脑。
下载链接:meshcommander.msi
转到屏幕左下角的 Windows 启动栏图标,键入 Mesh Commander
。
- 首先,通过单击计算机将计算机添加到 MeshCommander。如果没有已知的计算机,请通过添加计算机开始。
- 之后,您可以指定一个 友好名称,它只是一个字符串,允许您轻松识别系统。
- 您可以使用 标签,它允许您将多个系统归类到可识别的类别中。
- 您需要输入计算机的 主机名 或 IP 地址。
- 根据您配置远程机器的方式,您应该选择 身份验证。最常见的方法是 Digest/None。
- 最后,用户名和密码 与您在上一节中配置的用户名和密码相同。
添加到网格指挥器中的每台计算机旁边都有一个标记为 连接 的按钮。
单击 连接 按钮开始与您的远程机器通信。
连接到系统后,您将在屏幕上看到系统信息,例如电源状态、唯一标识符、英特尔® ME 版本、英特尔® AMT 激活模式和远程机器的基本设置。花点时间浏览一下,看看可用的各种信息。
要查看远程计算机系统的屏幕,请执行以下步骤
- 单击左侧边栏中的 远程桌面 链接。
- 然后单击图像中所示的 连接 按钮。
- 如果启用了用户同意,它将在英特尔® NUC 中显示一个代码,必须在 Mesh Commander 界面中输入该代码才能继续操作。
- 在管理控制模式下,单击 连接 将直接授予远程访问权限。
您现在将看到远程系统的屏幕。
由于英特尔® AMT 是远程设备的带外控制,因此即使远程计算机正在重新启动、在 BIOS 中或处于崩溃状态,您也能够看到远程系统的屏幕。
请注意标有 电源操作 的按钮。此按钮将显示一个对话框,允许您更改系统电源的状态。您可以启动、停止、重新启动或从其他支持的电源状态中选择。
英特尔® AMT 是一种带外服务,也就是说,它低于操作系统的级别。因此,即使在查看 BIOS 时,也可以远程查看显示器。
IDE-重定向
- 导航到远程桌面。
- 单击 IDE-R,这将打开存储重定向。
- 选择任何 .iso 文件和 .img 文件。
- 顶部将显示“IDE-R Session, Connected, 0 in, 0 out”消息。
- 单击 电源操作 并选择“重置为 IDE-R CDROM”。
- 现在观察顶行,显示消息“IDE-R Session, Connected, 0 in, ###### out”的变化,显示发出的数据包数量。
- 使用此技术,可以在英特尔® NUC 上远程刷新任何图像。
- 将显示 CDROM 图像内容。
- 您的操作系统图像将在此处加载。
- 单击远程桌面中的断开连接按钮。
- 单击停止 IDE-R 会话。
- 转到电源操作,然后单击重置选项以完成会话。
探索 MeshCommander
Mesh commander 网站有许多代码示例、文档和非常好的视频教程,介绍 MeshCommander 的每个功能。我们建议您通过 http://www.meshcommander.com/meshcommander/tutorials 了解更多信息。
目标
Meshcentral 是一种开源的点对点技术,具有广泛的用例,包括实现计算机和设备远程监控和管理的 Web 服务。用户可以从单个网站管理所有设备,无论计算机的位置如何,或者它们是否在代理后面。
在本节中,我们将探讨以下内容
- 如何创建设备网格?
- 如何远程共享远程机器的桌面?
- 如何探索远程机器上的文件系统?
- 如何通过命令行登录?
您可以参考 http://www.meshcommander.com/meshcentral2/tutorials 获取有关 meshcentral 各种功能的详细视频教程。
创建 meshcentral 帐户
您有两个选择。
- 按照此 http://www.meshcommander.com/meshcentral2/installation 指南安装 meshcentral。
- 直接在 meshcentral.com 网站上创建帐户。
本节我们将使用第二种选项。
- 在 www.meshcentral.com 上创建一个方便的用户名和密码的帐户。
- 使用上述凭据登录 meshcentral。
创建网格代理
- 转到 我的帐户选项卡 > 管理网格 > 新建。
- 在“创建新网格”弹出窗口中,提供网格名称和密码。
- 选中所有选项,然后单击 创建网格。
测试并安装创建的网格
- 转到“我的帐户”选项卡并单击新创建的网格。
- 查看 Web 授权。
- 单击 安装。
- 选择 Linux/x86-64 (Ubuntu) Mesh Agent。
在 Linux 终端中运行其中给出的命令以安装 Mesh Agent。
Web 设备刷新
转到 我的设备选项卡 并单击新连接的设备。
这将带您进入设备信息页面,该页面显示有关 Mesh 代理版本、目标操作系统、关联网格名称和接口 IP 地址的信息。
您可以使用英特尔®主动管理技术远程配置此页面,如之前的实验室中所讨论。单击适当的链接和图标以了解有关这些配置的更多信息。
您可以参考 http://www.meshcommander.com/meshcentral2/tutorials 获取有关 meshcentral 各种功能的详细视频教程。
步骤 5:探索文件系统
此方法允许访问客户端文件系统。
可以使用文件系统浏览器执行各种文件操作。您可以使用此界面复制、上传、删除文件。
探索终端
此方法允许访问终端,通过该终端可以执行系统支持的命令。您需要按 CTRL+C 才能启动命令提示符。
远程桌面共享
此方法使用 Web 套接字访问客户端桌面。
在此示例中,我们正在从机器共享桌面,因此您会看到桌面的无限循环。然而,在实时场景中,您将从千里之外的另一台机器连接到您的远程机器。
概述
视频分析部分提供了使用 OpenCV 执行一些基本的、特定于零售的视频分析场景的简单教程。
在视频性能部分,我们看到了通过使用英特尔®媒体服务器工作室和英特尔®集成显卡实现的性能增强。通过将视频播放转移到 GPU,我们能够释放 60-70% 的 CPU,我们可以利用它来执行本节中解释的视频分析示例。在视觉零售中,有一些常见的视频分析用例。它们是运动检测和人脸检测/跟踪。我们将使用 OpenCV 探索这两种技术,以计算数字标牌前的人数。我们将这些用作起点,但肯定有改进准确性的空间。
引言
OpenCV(开源计算机视觉库)在 BSD 许可证下发布,因此学术和商业用途均免费。它具有 C++、C、Python* 和 Java* 接口,并支持 Windows*、Linux*、Mac OS*、iOS* 和 Android*。OpenCV 专为计算效率和对实时应用程序的强烈关注而设计。该库用优化的 C/C++ 编写,可以利用多核处理。通过 OpenCL™ 启用,它可以利用底层异构计算平台的硬件加速。
查看 OpenCV 主页。
完成 McAfee® 嵌入式控制练习
学习如何使用 OpenCV 和 Python 从相机捕获视频。
- 确保您已将网络摄像头连接到您的英特尔® NUC 或 PC。
- 将相机安装在某个位置,以便在捕获视频时可以看到您的脸。
导航到 OpenCV Python 目录
要在此实验室中创建 Python 程序,我们将使用 Linux 中的终端和 gedit 编辑器。
- 使用 Ctrl + Alt + t 打开终端。
- 现在按如下方式创建并导航到新目录
$sudo mkdir python_samples $sudo chmod 777 python_samples $cd python_samples/
按照以下步骤创建新文件并将其保存为 camera.py
import numpy as np import cv2
- 发出命令:
$sudo gedit camera.py
- 打开一个空白文件。
- 使用 Ctrl + S 保存文件。
- 首先导入 numpy 和 opencv 包,如下所示。
视频捕获和显示
- 使用 cv2.VideoCapture 捕获视频。
- 视频捕获方法接受一个参数。此参数是您要使用的摄像机的索引号。如果您只使用一台摄像机,则此值为零。
- 创建一个
namedWindow
来渲染输出。 - 使用
imshow
方法在此namedWindow
上显示输出。 - 复制以下代码,将其放入您的文件并运行您的应用程序。
- 按 Esc 退出。
-
cap = cv2.VideoCapture(0) while(True): # Capture frame-by-frame ret, frame = cap.read() #Set full screen cv2.namedWindow("Target", cv2.WND_PROP_FULLSCREEN) cv2.setWindowProperty("Target",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN) # Display the resulting frame cv2.imshow('Target',frame) if cv2.waitKey(1) & 0xFF == 27: break # When everything done, release the capture cap.release() cv2.destroyAllWindows()
- 按 CTRL + S 保存文件。
- 关闭文件并返回终端。将摄像机连接到计算机并执行
$python camera.py
下载最终解决方案
如果出现错误,请复制完成的应用程序
import numpy as np import cv2 cap = cv2.VideoCapture(0) while(True): # Capture frame-by-frame ret, frame = cap.read() #Set full screen cv2.namedWindow("Target", cv2.WND_PROP_FULLSCREEN) cv2.setWindowProperty("Target",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN) # Display the resulting frame cv2.imshow('Target',frame) if cv2.waitKey(1) & 0xFF == 27: break # When everything done, release the capture cap.release() cv2.destroyAllWindows()
参考文献
目标
实验室概览
我们的运动检测器将观察连续帧之间的差异;当此差异很大时,我们可以假定检测到运动。为了防止误报,我们将观察帧的标准差。当检测到大小合适的物体的运动时,标准差会上升,从而使我们能够触发运动事件。
我们的程序将按以下方式布局
- 导入 OpenCV 及其依赖项。
- 初始化值。
- 启动视频循环。
- 计算帧之间的距离。
- 移动帧。
- 对距离映射应用高斯模糊。
- 应用阈值处理。
- 计算标准差。
- 如果检测到的运动高于阈值,则打印一条消息。
- 显示视频。
- 释放资源。
使用 OpenCV 进行运动检测
要在本节中创建 Python* 程序,我们将使用 Linux* 中的终端和 gedit 编辑器。
- 使用 Ctrl + Alt + t 打开终端。
- 现在按如下方式导航到新目录
$cd python_samples
按照以下步骤创建新文件并将其保存为 motion_detect.py
- 发出命令:
$sudo gedit motion_detect.py
- 打开一个空白文件。
- 使用 Ctrl + s 保存文件。
- 首先导入 numpy 和 opencv 包。
-
import numpy as np import cv2
- 按 CTRL + s 保存文件。
设置全局变量和函数
我们需要用于设置运动级别阈值和显示字体的变量。
sdThresh
用于运动级别阈值。- font 用于设置视频上文本显示的字体。
distMap 函数为我们提供 2 帧的三个 BGR 层之间的勾股距离。
sdThresh = 10
font = cv2.FONT_HERSHEY_SIMPLEX
#TODO: Face Detection 1
def distMap(frame1, frame2):
"""outputs pythagorean distance between two frames"""
frame1_32 = np.float32(frame1)
frame2_32 = np.float32(frame2)
diff32 = frame1_32 - frame2_32
norm32 = np.sqrt(diff32[:,:,0]**2 + diff32[:,:,1]**2 + diff32[:,:,2]**2)/np.sqrt(255**2 + 255**2 + 255**2)
dist = np.uint8(norm32*255)
return dist
设置视频捕获和显示
让我们为显示我们的运动图像和实际 RGB 图像进行必要的设置,然后我们将开始捕获帧。
cv2.namedWindow('frame')
cv2.namedWindow('dist')
#capture video stream from camera source. 0 refers to first camera, 1 referes to 2nd and so on.
cap = cv2.VideoCapture(0)
_, frame1 = cap.read()
_, frame2 = cap.read()
程序主体
开始主视频循环
-
while (True): _, frame3 = cap.read()
- 获取 frame3 的列和行矩阵。
-
rows, cols, _ = np.shape(frame3)
- 接下来,我们程序中的关键步骤是计算两帧之间的差异;我们通过使用我们创建的
distMap
函数来完成此操作。dist = distMap(frame1, frame3)
- 完成此操作后,我们可以移动我们的帧
frame1 = frame2 frame2 = frame3
- 接下来,我们应用高斯平滑以平滑我们的距离映射
mod = cv2.GaussianBlur(dist, (9,9), 0)
- 并对此结果进行阈值处理,以检索运动发生位置的二进制映射。
_, thresh = cv2.threshold(mod, 100, 255, 0)
- 此时,我们有一个二进制数组,指示运动发生的位置和未发生的位置。现在,我们将使用标准差来计算运动是否足够显著以触发警报。
- 使用以下方法计算标准差
_, stDev = cv2.meanStdDev(mod)
- 让我们展示一下我们通过标准差发现的内容,并将该值显示在视频上。
cv2.imshow('dist', mod) cv2.putText(frame2, "Standard Deviation - {}".format(round(stDev[0][0],0)), (70, 70), font, 1, (255, 0, 255), 1, cv2.LINE_AA)
- 如果标准差大于我们的阈值,则打印一条消息。
if stDev > sdThresh: print("Motion detected.. Do something!!!");
- 显示 BGR 彩色视频。
- 等待按下 Esc 按钮退出。
这是完整的主程序。
facecount = 0
while(True):
_, frame3 = cap.read()
rows, cols, _ = np.shape(frame3)
cv2.imshow('dist', frame3)
dist = distMap(frame1, frame3)
frame1 = frame2
frame2 = frame3
# apply Gaussian smoothing
mod = cv2.GaussianBlur(dist, (9,9), 0)
# apply thresholding
_, thresh = cv2.threshold(mod, 100, 255, 0)
# calculate st dev test
_, stDev = cv2.meanStdDev(mod)
cv2.imshow('dist', mod)
cv2.putText(frame2, "Standard Deviation - {}".format(round(stDev[0][0],0)), (70, 70), font, 1, (255, 0, 255), 1, cv2.LINE_AA)
if stDev > sdThresh:
print("Motion detected.. Do something!!!");
#TODO: Face Detection 2
cv2.imshow('frame', frame2)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
- 保存文件
- 按 F5
这是最终的代码库。
保留这些 TODO。我们将在人脸检测期间重复使用此程序。
import numpy as np
import cv2
sdThresh = 10
font = cv2.FONT_HERSHEY_SIMPLEX
#TODO: Face Detection 1
def distMap(frame1, frame2):
"""outputs pythagorean distance between two frames"""
frame1_32 = np.float32(frame1)
frame2_32 = np.float32(frame2)
diff32 = frame1_32 - frame2_32
norm32 = np.sqrt(diff32[:,:,0]**2 + diff32[:,:,1]**2 + diff32[:,:,2]**2)/np.sqrt(255**2 + 255**2 + 255**2)
dist = np.uint8(norm32*255)
return dist
cv2.namedWindow('frame')
cv2.namedWindow('dist')
#capture video stream from camera source. 0 refers to first camera, 1 referes to 2nd and so on.
cap = cv2.VideoCapture(0)
_, frame1 = cap.read()
_, frame2 = cap.read()
facecount = 0
while(True):
_, frame3 = cap.read()
rows, cols, _ = np.shape(frame3)
cv2.imshow('dist', frame3)
dist = distMap(frame1, frame3)
frame1 = frame2
frame2 = frame3
# apply Gaussian smoothing
mod = cv2.GaussianBlur(dist, (9,9), 0)
# apply thresholding
_, thresh = cv2.threshold(mod, 100, 255, 0)
# calculate st dev test
_, stDev = cv2.meanStdDev(mod)
cv2.imshow('dist', mod)
cv2.putText(frame2, "Standard Deviation - {}".format(round(stDev[0][0],0)), (70, 70), font, 1, (255, 0, 255), 1, cv2.LINE_AA)
if stDev > sdThresh:
print("Motion detected.. Do something!!!");
#TODO: Face Detection 2
cv2.imshow('frame', frame2)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
参考文献
目标
实验室概览
我们在之前的模块中介绍了运动检测。在此实验室中,当触发运动检测时,我们将计算存在的人脸数量。我们将
- 实例化人脸的级联分类器。
- 我们将使用 Haar 级联方法识别人脸。
- 最后,我们将计算帧中的人脸数量。
- 显示视频。
- 释放资源。
人脸识别示例概览
第一步是加载 Haar 状特征分类器级联文件,该文件是通过机器学习创建的,以包含人脸的基本特征。在 OpenCV 中,您可以通过更改分类器文件来检测不同类型的对象。
下载名为 haarcascade_frontalface_default.xml 的 haar 级联文件,并将其保存到与您的 Python* 脚本相同的目录中。
创建一个名为 face_detect.py 的新 Python 文件
粘贴以下行
import cv2
您需要打开分类器文件并连接到摄像机。
# Create a Haar-like feature cascade classifier object
faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
# Set the camera to the first camera detected by the NUC
cap = cv2.VideoCapture(0)
人脸检测器的主循环
此代码执行多个步骤
- 它捕获当前帧。
- 将其转换为灰度以进行更快比较。
- 将灰度帧发送到人脸识别检测器。
- 检测器返回一个包含 (x,y,w,h) 的框的坐标数组。
- 在人脸周围绘制一个矩形。
- 显示帧。
- 如果用户按下 Esc 键,程序将退出。
while True:
# Capture frame-by-frame
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# begin face cascade
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.25,
minNeighbors=5,
minSize=(30, 30),
)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
# Display the resulting frame
cv2.imshow('Video', frame)
# If the user presses the 'q' key then quit the program
if cv2.waitKey(1) & 0xFF == 27:
break
这是最终的解决方案
这是包括我们之前完成的运动检测示例在内的人脸计数最终代码。在这里,我们首先检测运动,然后尝试在场景中找到人脸。
import cv2
cv2.namedWindow('frame')
cv2.namedWindow('dist')
# the classifier that will be used in the cascade
faceCascade = cv2.CascadeClassifier('haar_face.xml')
#capture video stream from camera source. 0 refers to first camera, 1 referes to 2nd and so on.
cap = cv2.VideoCapture(0)
triggered = False
sdThresh = 10
font = cv2.FONT_HERSHEY_SIMPLEX
def distMap(frame1, frame2):
"""outputs pythagorean distance between two frames"""
frame1_32 = np.float32(frame1)
frame2_32 = np.float32(frame2)
diff32 = frame1_32 - frame2_32
norm32 = np.sqrt(diff32[:,:,0]**2 + diff32[:,:,1]**2 + diff32[:,:,2]**2)/np.sqrt(255**2 + 255**2 + 255**2)
dist = np.uint8(norm32*255)
return dist
_, frame1 = cap.read()
_, frame2 = cap.read()
facecount = 0
while(True):
_, frame3 = cap.read()
rows, cols, _ = np.shape(frame3)
cv2.imshow('dist', frame3)
dist = distMap(frame1, frame3)
frame1 = frame2
frame2 = frame3
# apply Gaussian smoothing
mod = cv2.GaussianBlur(dist, (9,9), 0)
# apply thresholding
_, thresh = cv2.threshold(mod, 100, 255, 0)
# calculate st dev test
_, stDev = cv2.meanStdDev(mod)
cv2.imshow('dist', mod)
cv2.putText(frame2, "Standard Deviation - {}".format(round(stDev[0][0],0)), (70, 70), font, 1, (255, 0, 255), 1, cv2.LINE_AA)
if stDev > sdThresh:
# the cascade is implemented in grayscale mode
gray = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# begin face cascade
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=2,
minSize=(20, 20)
)
facecount = 0
# draw a rectangle over detected faces
for (x, y, w, h) in faces:
facecount = facecount + 1
cv2.rectangle(frame2, (x, y), (x+w, y+h), (0, 255, 0), 1)
cv2.putText(frame2, "No of faces {}".format(facecount), (50, 50), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
else:
if facecount > 0:
print("Face count:")
print(facecount)
facecount = 0
cv2.imshow('frame', frame2)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
参考文献
实验室概览
我们在之前的模块中介绍了运动和人脸检测。我们还成功计算了检测到运动时存在的人脸数量。
在本模块中,我们将设置一个本地云并将此数据发布到其中进行分析。
我们将用以下内容替换这两个 TODO
- 我们将导入一个名为“requests”的包。
- 我们将在显示人脸计数后发布人脸数量。
- 登录云并查看显示人脸数量的图表。
导入包
我们需要导入 requests 包
- 替换第一个 #TODO:云集成 1
- 粘贴以下行
import requests
将人脸数量发布到云
我们已经计算了场景中的人脸数量。我们需要将此计数器值发布到云。
注意:我们不发布视频流或屏幕图片。我们只发布人脸数量。
- 替换第二个 #TODO:云集成 2
- 请注意,当运动停止时,我们正在将数据发送到云。
- 粘贴以下行
- 将设备 ID“1234”替换为您的英特尔® NUC 上写入的设备 ID(或任何 4 位唯一数字)
- 将 <cloud server url> 替换为研讨会中提供的云 URL
- 您的云服务器 URL 将是
"http://" + window.location.hostname + ":9002";
-
else: query = 'id=1234' + '&value=' + str(facecount) resp = requests.get('http://<cloud server url>/analytics/face?'+ query) if resp.status_code != 201: # This means something went wrong. print("Unable to submit the data") else: print("Data Submitted for analysis")
这是包括云集成在内的最终代码库
import numpy as np
import cv2
import requests
cv2.namedWindow('frame')
cv2.namedWindow('dist')
# the classifier that will be used in the cascade
faceCascade = cv2.CascadeClassifier('haar_face.xml')
#capture video stream from camera source. 0 refers to first camera, 1 referes to 2nd and so on.
cap = cv2.VideoCapture(0)
triggered = False
sdThresh = 10
font = cv2.FONT_HERSHEY_SIMPLEX
def distMap(frame1, frame2):
"""outputs pythagorean distance between two frames"""
frame1_32 = np.float32(frame1)
frame2_32 = np.float32(frame2)
diff32 = frame1_32 - frame2_32
norm32 = np.sqrt(diff32[:,:,0]**2 + diff32[:,:,1]**2 + diff32[:,:,2]**2)/np.sqrt(255**2 + 255**2 + 255**2)
dist = np.uint8(norm32*255)
return dist
_, frame1 = cap.read()
_, frame2 = cap.read()
facecount = 0
while(True):
_, frame3 = cap.read()
rows, cols, _ = np.shape(frame3)
cv2.imshow('dist', frame3)
dist = distMap(frame1, frame3)
frame1 = frame2
frame2 = frame3
# apply Gaussian smoothing
mod = cv2.GaussianBlur(dist, (9,9), 0)
# apply thresholding
_, thresh = cv2.threshold(mod, 100, 255, 0)
# calculate st dev test
_, stDev = cv2.meanStdDev(mod)
cv2.imshow('dist', mod)
cv2.putText(frame2, "Standard Deviation - {}".format(round(stDev[0][0],0)), (70, 70), font, 1, (255, 0, 255), 1, cv2.LINE_AA)
if stDev > sdThresh:
# the cascade is implemented in grayscale mode
gray = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# begin face cascade
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=2,
minSize=(20, 20)
)
facecount = 0
# draw a rectangle over detected faces
for (x, y, w, h) in faces:
facecount = facecount + 1
cv2.rectangle(frame2, (x, y), (x+w, y+h), (0, 255, 0), 1)
cv2.putText(frame2, "No of faces {}".format(facecount), (50, 50), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
else:
if facecount > 0:
query = 'id=1234' + '&value=' + str(facecount)
resp = requests.get('http://<cloud server url>:9002/analytics/face?'+ query)
if resp.status_code != 201:
# This means something went wrong.
print("Unable to submit the data")
else:
print("Data Submitted for analysis")
facecount = 0
cv2.imshow('frame', frame2)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
可视化您的数据
在云端可视化您的数据
- 转到
http://< cloud server url>:9002
- 示例:
"http://" + window.location.hostname + ":9002";
- 输入您的设备 ID
- 点击绘图