Kurento模块开发指南之二:开发示例 Pointer Detector Filter

2024-08-21 17:58

本文主要是介绍Kurento模块开发指南之二:开发示例 Pointer Detector Filter,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

17.1.2 模块教程1- Pointer Detector Filter
这个页面应用由一个带有指针跟踪滤镜组件的WebRTC视频通信回看组成。

Java 模块教程 1 - Pointer Detector Filter
这个页面应用由一个带有指针跟踪滤镜组件的WebRTC视频通信回看组成。

首先:  运行这个示例程序
首先,需要安装Kurento Media Server来运行这个示例,可以参看前面的安装指南。
另外,内建模块kms-pointerdetector-6.0 也需要被安装:
$ sudo apt-get install kms-pointerdetector-6.0

为了加载这个应用,需要从GitHub上克隆这个工程并运行,命令如下:
$ git clone https://github.com/Kurento/kurento-tutorial-java.git
$ cd kurento-tutorial-java/kurento-pointerdetector
$ mvn compile exec:java

在本机上用 (Chrome, Firefox)浏览器输入网址http://localhost:8080/即可看到这个示例应用。

Note: 
These instructions work only if Kurento Media Server is up and running in the same machine than the tutorial. However, it is possible to locate the KMS in other machine simple adding the argument kms.ws.uri to the Maven execution command, as follows:
mvn compile exec:java -Dkms.ws.uri=ws://kms_host:kms_port/kurento

理解这个示例应用
这个应用程序使用了计算机视觉和虚拟现实技术,它是基于颜色跟踪的方式检测WebRTC流中的指针。

这个应用程序(一个HTML页面)的接口由两个HTML5视频标签组成:
一个用于显示本地的视频摄像头的流;
一个用于显示远端的镜像的流。
本地视频摄像头的流被发送到KMS, 经过处理后再发回到客户端。我们需要创建的媒体管道由下列媒体组件组成:
 
Figure 17.3: WebRTC with PointerDetector filter in loopback Media Pipeline

这个示例应用的完整代码在GitHub上。
这个示例应用程序,是Magic Mirror教程的改版,它使用了PointerDetector 代替FaceOverlay 滤镜。

为了实现指针检测,它必须有一个校准阶段,即先要把指针处的颜色注册到滤镜中。为了实现这个步骤,指针需要先位于视频框的左上角,如下所示:
 
Figure 17.4: Pointer calibration stage

在这个时刻,服务端将会发送一个校准消息给客户端。
这可以通过点击页面的校准蓝色按钮实现。

在这之后,指针所指处的颜色就会被KMS实时跟踪。
PointerDetectorFilter 同样能定义屏幕上的一个区域,称之为窗口,当某些操作导致指针进入这个区域时会执行一些动作, 当指针进入时是WindowInEvent事件,退出时是WindowOutEvent事件。
服务端的代码逻辑如下:

// Media Logic (Media Pipeline and Elements)
UserSession user = new UserSession();
MediaPipeline pipeline = kurento.createMediaPipeline();
user.setMediaPipeline(pipeline);    
WebRtcEndpoint webRtcEndpoint = new WebRtcEndpoint.Builder(pipeline).build();
user.setWebRtcEndpoint(webRtcEndpoint);
users.put(session.getId(), user);


webRtcEndpoint.addOnIceCandidateListener(new EventListener<OnIceCandidateEvent>() {
@Override
    public void onEvent(OnIceCandidateEvent event) {
        JsonObject response = new JsonObject();
        response.addProperty("id", "iceCandidate");
        response.add("candidate", JsonUtils.toJsonObject(event.getCandidate()));
        try {
            synchronized (session) {
                session.sendMessage(new TextMessage(response.toString()));
            }
        } catch (IOException e) {
            log.debug(e.getMessage());
        }
    }
});


pointerDetectorFilter = new PointerDetectorFilter.Builder(pipeline,new WindowParam(5, 5, 30, 30)).build();
pointerDetectorFilter.addWindow(new PointerDetectorWindowMediaParam("window0",50, 50, 500, 150));
pointerDetectorFilter.addWindow(new PointerDetectorWindowMediaParam("window1",50, 50, 500, 250));
webRtcEndpoint.connect(pointerDetectorFilter);
pointerDetectorFilter.connect(webRtcEndpoint);
pointerDetectorFilter.addWindowInListener(new EventListener<WindowInEvent>() {
    @Override
    public void onEvent(WindowInEvent event) {
        JsonObject response = new JsonObject();
        response.addProperty("id", "windowIn");
        response.addProperty("roiId", event.getWindowId());
        try {
            session.sendMessage(new TextMessage(response.toString()));
        } catch (Throwable t) {
            sendError(session, t.getMessage());
        }
    }
});


pointerDetectorFilter.addWindowOutListener(new EventListener<WindowOutEvent>() {
    @Override
    public void onEvent(WindowOutEvent event) {
        JsonObject response = new JsonObject();
        response.addProperty("id", "windowOut");
        response.addProperty("roiId", event.getWindowId());
        try {
            session.sendMessage(new TextMessage(response.toString()));
        } catch (Throwable t) {
            sendError(session, t.getMessage());
        }
    }
});


// SDP negotiation (offer and answer)
String sdpOffer = jsonMessage.get("sdpOffer").getAsString();
String sdpAnswer = webRtcEndpoint.processOffer(sdpOffer);


// Sending response back to client
JsonObject response = new JsonObject();
response.addProperty("id", "startResponse");
response.addProperty("sdpAnswer", sdpAnswer);
synchronized (session) {
    session.sendMessage(new TextMessage(response.toString()));
}
webRtcEndpoint.gatherCandidates();


下图显示了在一个定义窗口中的指针检测:
 
Figure 17.5: Pointer tracking over a window


为了从客户端发送校准消息到服务端,这个示例程序的JavaScripte使用了下面的函数:
function calibrate() {    
    console.log("Calibrate color");
    var message = {
        id : 'calibrate'
    }
    sendMessage(message);
}


当应用程序服务端收到消息后,下面的代码被执行来进行校准:
private void calibrate(WebSocketSession session, JsonObject jsonMessage) {
    if (pointerDetectorFilter != null) {
        pointerDetectorFilter.trackColorFromCalibrationRegion();
    }
}


依赖项
Java Spring是由Maven实现,另外还需要三个依赖项:
the Kurento Client Java dependency (kurento-client), 
the JavaScript Kurento utility library (kurento-utils) for the client-side,
and the pointer detector module (pointerdetector):    


<parent>
    <groupId>org.kurento</groupId>
    <artifactId>kurento-parent-pom</artifactId>
    <version>|CLIENT_JAVA_VERSION|</version>
</parent>


<dependencies>
    <dependency>
        <groupId>org.kurento</groupId>
        <artifactId>kurento-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.kurento</groupId>
        <artifactId>kurento-utils-js</artifactId>
    </dependency>
    <dependency>
        <groupId>org.kurento.module</groupId>
        <artifactId>pointerdetector</artifactId>
    </dependency>
</dependencies>


Note: 
We are in active development. You can find the latest versions at Maven Central.

这篇关于Kurento模块开发指南之二:开发示例 Pointer Detector Filter的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1093879

相关文章

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

Python位移操作和位运算的实现示例

《Python位移操作和位运算的实现示例》本文主要介绍了Python位移操作和位运算的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 位移操作1.1 左移操作 (<<)1.2 右移操作 (>>)注意事项:2. 位运算2.1

SpringBoot整合OpenFeign的完整指南

《SpringBoot整合OpenFeign的完整指南》OpenFeign是由Netflix开发的一个声明式Web服务客户端,它使得编写HTTP客户端变得更加简单,本文为大家介绍了SpringBoot... 目录什么是OpenFeign环境准备创建 Spring Boot 项目添加依赖启用 OpenFeig

pandas中位数填充空值的实现示例

《pandas中位数填充空值的实现示例》中位数填充是一种简单而有效的方法,用于填充数据集中缺失的值,本文就来介绍一下pandas中位数填充空值的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录什么是中位数填充?为什么选择中位数填充?示例数据结果分析完整代码总结在数据分析和机器学习过程中,处理缺失数

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Pandas统计每行数据中的空值的方法示例

《Pandas统计每行数据中的空值的方法示例》处理缺失数据(NaN值)是一个非常常见的问题,本文主要介绍了Pandas统计每行数据中的空值的方法示例,具有一定的参考价值,感兴趣的可以了解一下... 目录什么是空值?为什么要统计空值?准备工作创建示例数据统计每行空值数量进一步分析www.chinasem.cn处

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指