开发者社区> 夏夜许游> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

利用java实现视频人像分割及视频背景替换

简介: 视频人像分割是将视频中的人体从原视频中分割出来,得到透明背景的人体视频。如何基于算法分割后的人像结果进行再加工。
+关注继续查看

视频人像分割是将视频中的人体从原视频中分割出来,得到透明背景的人体视频。如何基于算法分割后的人像结果进行再加工。
一、基于现有的视频人像分割API对视频进行解析,将视频中的人像区域mask(掩模)作为视频序列返回。返回的mask通道视频类似于这种。
视频人像分割结果.png

实现以上的效果是基于阿里云视觉智能开放平台的视频人像分割,平台提供有示例代码,
1、需要安装Alibaba Cloud SDK for Java:aliyun-java-sdk-core
该SDK包为阿里云Java核心库,无论使用哪个产品的SDK,都必须先安装该核心库。
2、推荐使用Maven管理Java项目,可以通过在pom.xml文件中添加Maven依赖安装Java SDK,依赖如下:

<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-videoseg</artifactId>
<version>${aliyun.videoseg.version}</version>

调用API接口的示例代码如下:

package com.aliyun.sample;

import com.aliyun.tea.*;
import com.aliyun.videoseg20200320.*;
import com.aliyun.videoseg20200320.models.*;
import com.aliyun.teaopenapi.*;
import com.aliyun.teaopenapi.models.*;
import com.aliyun.teautil.*;
import com.aliyun.teautil.models.*;

public class Sample {

/**
 * 使用AK&SK初始化账号Client
 * @param accessKeyId
 * @param accessKeySecret
 * @return Client
 * @throws Exception
 */
public static com.aliyun.videoseg20200320.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
    Config config = new Config()
            // 您的 AccessKey ID
            .setAccessKeyId(accessKeyId)
            // 您的 AccessKey Secret
            .setAccessKeySecret(accessKeySecret);
    // 访问的域名
    config.endpoint = "videoseg.cn-shanghai.aliyuncs.com";
    return new com.aliyun.videoseg20200320.Client(config);
}

public static void main(String[] args_) throws Exception {
    java.util.List<String> args = java.util.Arrays.asList(args_);
    com.aliyun.videoseg20200320.Client client = Sample.createClient("accessKeyId", "accessKeySecret");
    SegmentVideoBodyRequest segmentVideoBodyRequest = new SegmentVideoBodyRequest();
    RuntimeOptions runtime = new RuntimeOptions();
    try {
        // 复制代码运行请自行打印 API 的返回值
        client.segmentVideoBodyWithOptions(segmentVideoBodyRequest, runtime);
    } catch (TeaException error) {
        // 如有需要,请打印 error
        com.aliyun.teautil.Common.assertAsString(error.message);
    } catch (Exception _error) {
        TeaException error = new TeaException(_error.getMessage(), _error);
        // 如有需要,请打印 error
        com.aliyun.teautil.Common.assertAsString(error.message);
    }        
}

}

二、对算法输出的视频Mask通道进行覆盖,先让原视频生成背景透明的视频流,采用视频中的一帧看下输出的结果如下:
invi_humansegmenter_016595069223121001355_oAMBDN.png

替换背景之后的效果如下:
Dingtalk_20220803141353.jpg

下面将使用java 的方法完成上面的效果,首先是将API输出的Mask通道视频和原视频进行叠加,生成新的背景透明视频,然后在背景透明的视频状态下,再替换视频的背景。视频是有一帧帧的图片序列组成的,所以本次的java方法也是针对图片序列进行操作。

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
public class NewImageUtils {

/**
 *
 * @Title: 构造图片
 * @Description: 生成水印并返回java.awt.image.BufferedImage
 * @param file
 *            源文件(图片)
 * @param waterFile
 *            水印文件(图片)
 * @param x
 *            距离右下角的X偏移量
 * @param y
 *            距离右下角的Y偏移量
 * @param alpha
 *            透明度, 选择值从0.0~1.0: 完全透明~完全不透明
 * @return BufferedImage
 * @throws IOException
 */
public static BufferedImage watermark(File file, File waterFile, int x, int y, float alpha) throws IOException {
    // 获取底图
    BufferedImage buffImg = ImageIO.read(file);
    // 获取层图
    BufferedImage waterImg = ImageIO.read(waterFile);
    // 创建Graphics2D对象,用在底图对象上绘图
    Graphics2D g2d = buffImg.createGraphics();
    int waterImgWidth = waterImg.getWidth();// 获取层图的宽度
    int waterImgHeight = waterImg.getHeight();// 获取层图的高度
    // 在图形和图像中实现混合和透明效果
    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
    // 绘制
    g2d.drawImage(waterImg, x, y, waterImgWidth, waterImgHeight, null);
    g2d.dispose();// 释放图形上下文使用的系统资源
    return buffImg;
}

/**
 * 输出水印图片
 *
 * @param buffImg
 *            图像加水印之后的BufferedImage对象
 * @param savePath
 *            图像加水印之后的保存路径
 */
private void generateWaterFile(BufferedImage buffImg, String savePath) {
    int temp = savePath.lastIndexOf(".") + 1;
    try {
        ImageIO.write(buffImg, savePath.substring(temp), new File(savePath));
    } catch (IOException e1) {
        e1.printStackTrace();
    }
}

/**
 *
 * @param args
 * @throws IOException
 *             IO异常直接抛出了
 * @author bls
 */
public static void main(String[] args) throws IOException {
    String sourceFilePath = "D://img//di.png";
    String waterFilePath = "D://img//ceng.png";
    String saveFilePath = "D://img//new.png";
    NewImageUtils newImageUtils = new NewImageUtils();
    // 构建叠加层
    BufferedImage buffImg = NewImageUtils.watermark(new File(sourceFilePath), new File(waterFilePath), 0, 0, 1.0f);
    // 输出水印图片
    newImageUtils.generateWaterFile(buffImg, saveFilePath);
}

}

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
java对web视频的简单处理流程
java对web视频的简单处理流程
221 0
【设计数据结构】使用一个数组实现三个栈|Java 刷题打卡
【设计数据结构】使用一个数组实现三个栈|Java 刷题打卡
34 0
借这个问题来实现一个「可删除/计数」的 Trie 树 |Java 刷题打卡
借这个问题来实现一个「可删除/计数」的 Trie 树 |Java 刷题打卡
18 0
【图解 Trie】两种实现 Tire 的方式及其优缺点对比分析|Java 刷题打卡
【图解 Trie】两种实现 Tire 的方式及其优缺点对比分析|Java 刷题打卡
44 0
Java实现3DES加解密算法(2)
Java实现3DES加解密算法(2)
81 0
Java实现3DES加解密算法(1)
Java实现3DES加解密算法(1)
405 0
【Java数据结构及算法实战】系列009:Java队列03——数组实现的阻塞队列ArrayBlockingQueue
顾名思义,ArrayBlockingQueue是基于数组实现的有界阻塞队列。该队列对元素进行FIFO排序。队列的首元素是在该队列中驻留时间最长的元素。队列的尾部是在该队列中停留时间最短的元素。新的元素被插入到队列的尾部,队列检索操作获取队列头部的元素。
42 0
java实现文件对比
基于java实现类似于svn的文件对比功能及效果,该对比适用于html,js,css,text等
1413 0
JAVA通过Gearman实现MySQL到Redis的数据同步(异步复制)
无论MySQL还是Redis,自身都带有数据同步的机制,像比较常用的 MySQL的Master/Slave模式 ,就是由Slave端分析Master的binlog来实现的,这样的数据复制其实还是一个异步过程,只不过当服务器都在同一内网时,异步的延迟几乎可以忽略。
114 0
java实现时间转UTC格式
java实现时间转UTC格式
610 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
快速变化背景下,组织如何保持过程的稳定性
立即下载
数据智能时代,语音交互将是第一爆发领域
立即下载
JAVA反射原理以及一些常见的应用
立即下载