65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Intel® 硬件和软件开发视觉零售解决方案

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2018年4月3日

CPOL

26分钟阅读

viewsIcon

9441

零售工作坊:使用基于 Intel® 的零售解决方案进行实践学习。

动手实践实验室

了解用于构建高级、高性能视频播放、高级远程管理和视频分析的基于英特尔®的软件和硬件工具/SDK。

章节概述和目标

在本节中,我们将探讨完成本课程中实验室所需的硬件和软件列表。

学完本模块后,您应该能够

  • 了解所需的硬件和软件
  • 安装 Ubuntu* 16.04
  • 安装英特尔®媒体服务器工作室
  • 安装支持 Python* 的 OpenCV

硬件要求

  1. 搭载第五代英特尔®酷睿™处理器的英特尔® NUC 套件
  2. 确保您的设备支持英特尔®博锐™技术。本课程材料在 英特尔® NUC 套件 NUC5i5MYHE 上进行了测试。

软件和操作系统要求

  • Ubuntu 16.04
  • 英特尔®媒体服务器工作室
  • 支持 Python 的 OpenCV

建议在运行英特尔®媒体服务器工作室和 OpenCV 安装时使用开放网络,因为公司代理规则和防火墙设置可能会阻止下载必要的文件。

  1. http://old-releases.ubuntu.com/releases/16.04.1/ubuntu-16.04-desktop-amd64.iso 安装 Ubuntu 16.04
  2. 更新 Ubuntu 软件包。警告:不要选择升级选项。
    $sudo apt-get update

    注意:如果在更新过程中遇到核心转储,请运行以下命令,然后运行 apt-get update

    $sudo apt-get purge libappstream3
  3. https://software.intel.com/en-us/intel-media-server-studio 下载适用于 Linux 的英特尔®媒体服务器工作室

  4. 按照 入门指南 - Linux* 安装 中记录的最新安装过程进行操作。您应该使用安装文档中的“通用”安装步骤在 Ubuntu 上安装。
  5. 重启系统。
  6. https://opencv.ac.cn/releases.html 安装支持 Python 的 OpenCV
  7. 重启系统。
  8. 系统分析器:系统分析器工具是一个 Python 脚本,可从以下位置下载:https://software.intel.com/en-us/articles/mss-sys-analyzer-linux

  9. 通过创建适当的目录结构,将 sys_analyzer_linux.py python 脚本复制到 /home/intel/workshop 文件夹。

  10. https://github.com/Intel-Media-SDK/samples 下载示例

    将示例解压到 /home/intel/Documents/workshop/msdk_samples/

英特尔®媒体服务器工作室安装

  1. 执行 $vainfo 并确保没有错误
  2. Execute
    $cd /opt/intel/mediasdk/samples/_bin/x64
    $./sample_decode h264 -i ../content/test_stream.264 -hw -vaapi -r
                    
  3. 查看终端。您应该看到硬件 IMPL 为“hw(hardware)”,vaapi 为解码帧的内存。

OpenCV 安装

  1. 从终端运行 python。
    $python 
  2. 键入:import cv2 应该没有错误。
  3. 键入: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 帐户

您有两个选择。

  1. 按照此 http://www.meshcommander.com/meshcentral2/installation 指南安装 meshcentral。
  2. 直接在 meshcentral.com 网站上创建帐户。

本节我们将使用第二种选项。

  1. www.meshcentral.com 上创建一个方便的用户名和密码的帐户。
  2. 使用上述凭据登录 meshcentral。

创建网格代理

  1. 转到 我的帐户选项卡 > 管理网格 > 新建
  2. 在“创建新网格”弹出窗口中,提供网格名称和密码。
  3. 选中所有选项,然后单击 创建网格

测试并安装创建的网格

  1. 转到“我的帐户”选项卡并单击新创建的网格。
  2. 查看 Web 授权。
  3. 单击 安装
  4. 选择 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 编辑器。

  1. 使用 Ctrl + Alt + t 打开终端。
  2. 现在按如下方式创建并导航到新目录
$sudo mkdir python_samples
$sudo chmod 777 python_samples
$cd python_samples/

按照以下步骤创建新文件并将其保存为 camera.py

import numpy as np
import cv2
  1. 发出命令:$sudo gedit camera.py
  2. 打开一个空白文件。
  3. 使用 Ctrl + S 保存文件。
  4. 首先导入 numpy 和 opencv 包,如下所示。

视频捕获和显示

  1. 使用 cv2.VideoCapture 捕获视频。
  2. 视频捕获方法接受一个参数。此参数是您要使用的摄像机的索引号。如果您只使用一台摄像机,则此值为零。
  3. 创建一个 namedWindow 来渲染输出。
  4. 使用 imshow 方法在此 namedWindow 上显示输出。
  5. 复制以下代码,将其放入您的文件并运行您的应用程序。
  6. Esc 退出。
  7. 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()
  8. CTRL + S 保存文件。
  9. 关闭文件并返回终端。将摄像机连接到计算机并执行
$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 编辑器。

  1. 使用 Ctrl + Alt + t 打开终端。
  2. 现在按如下方式导航到新目录
$cd python_samples

按照以下步骤创建新文件并将其保存为 motion_detect.py

  1. 发出命令:$sudo gedit motion_detect.py
  2. 打开一个空白文件。
  3. 使用 Ctrl + s 保存文件。
  4. 首先导入 numpy 和 opencv 包。
  5. import numpy as np
    import cv2
  6. 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)

人脸检测器的主循环

此代码执行多个步骤

  1. 它捕获当前帧。
  2. 将其转换为灰度以进行更快比较。
  3. 将灰度帧发送到人脸识别检测器。
  4. 检测器返回一个包含 (x,y,w,h) 的框的坐标数组。
  5. 在人脸周围绘制一个矩形。
  6. 显示帧。
  7. 如果用户按下 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 包

  1. 替换第一个 #TODO:云集成 1
  2. 粘贴以下行
    import requests

将人脸数量发布到云

我们已经计算了场景中的人脸数量。我们需要将此计数器值发布到云。

注意:我们不发布视频流或屏幕图片。我们只发布人脸数量。

  1. 替换第二个 #TODO:云集成 2
  2. 请注意,当运动停止时,我们正在将数据发送到云。
  3. 粘贴以下行
  4. 将设备 ID“1234”替换为您的英特尔® NUC 上写入的设备 ID(或任何 4 位唯一数字)
  5. 将 <cloud server url> 替换为研讨会中提供的云 URL
  6. 您的云服务器 URL 将是
    "http://" + window.location.hostname + ":9002";
  7. 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
  • 点击绘图

参考文献

© . All rights reserved.