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

相关文章

使用Python实现一个简易计算器的新手指南

《使用Python实现一个简易计算器的新手指南》计算器是编程入门的经典项目,它涵盖了变量、输入输出、条件判断等核心编程概念,通过这个小项目,可以快速掌握Python的基础语法,并为后续更复杂的项目打下... 目录准备工作基础概念解析分步实现计算器第一步:获取用户输入第二步:实现基本运算第三步:显示计算结果进

Python利用PySpark和Kafka实现流处理引擎构建指南

《Python利用PySpark和Kafka实现流处理引擎构建指南》本文将深入解剖基于Python的实时处理黄金组合:Kafka(分布式消息队列)与PySpark(分布式计算引擎)的化学反应,并构建一... 目录引言:数据洪流时代的生存法则第一章 Kafka:数据世界的中央神经系统消息引擎核心设计哲学高吞吐

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

Python中yield的用法和实际应用示例

《Python中yield的用法和实际应用示例》在Python中,yield关键字主要用于生成器函数(generatorfunctions)中,其目的是使函数能够像迭代器一样工作,即可以被遍历,但不会... 目录python中yield的用法详解一、引言二、yield的基本用法1、yield与生成器2、yi

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

MyBatis-Plus 与 Spring Boot 集成原理实战示例

《MyBatis-Plus与SpringBoot集成原理实战示例》MyBatis-Plus通过自动配置与核心组件集成SpringBoot实现零配置,提供分页、逻辑删除等插件化功能,增强MyBa... 目录 一、MyBATis-Plus 简介 二、集成方式(Spring Boot)1. 引入依赖 三、核心机制

MySQL设置密码复杂度策略的完整步骤(附代码示例)

《MySQL设置密码复杂度策略的完整步骤(附代码示例)》MySQL密码策略还可能包括密码复杂度的检查,如是否要求密码包含大写字母、小写字母、数字和特殊字符等,:本文主要介绍MySQL设置密码复杂度... 目录前言1. 使用 validate_password 插件1.1 启用 validate_passwo

Java高效实现Word转PDF的完整指南

《Java高效实现Word转PDF的完整指南》这篇文章主要为大家详细介绍了如何用Spire.DocforJava库实现Word到PDF文档的快速转换,并解析其转换选项的灵活配置技巧,希望对大家有所帮助... 目录方法一:三步实现核心功能方法二:高级选项配置性能优化建议方法补充ASPose 实现方案Libre

springboot整合mqtt的步骤示例详解

《springboot整合mqtt的步骤示例详解》MQTT(MessageQueuingTelemetryTransport)是一种轻量级的消息传输协议,适用于物联网设备之间的通信,本文介绍Sprin... 目录1、引入依赖包2、yml配置3、创建配置4、自定义注解6、使用示例使用场景:mqtt可用于消息发