Java音视频处理——JavaCV

这篇具有很好参考价值的文章主要介绍了Java音视频处理——JavaCV。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

 

简介

Maven

软件环境

JavaCV-Examples

OpenCV Cookbook Examples

概述

示例

OpenCV文档

如何使用JavaCV示例

示例代码的组织结构

示例列表

Why Scala?

学习地址

图像简单处理代码示例

1.打开保存一张图

 2.画直线

3.画圆圈

4.画折现

5.添加文字水印

6.裁剪并局部放大

7.人脸检测

视频简单处理代码示例

1.打开视频文件

2.抓取视频指定时间的帧保存为图像

3.录屏

4.给视频添加水印


简介

JavaCV使用来自JavaCPP预设库的包装器,这些库是计算机视觉领域的研究人员常用的库(OpenCV, FFmpeg, libdc1394, FlyCapture, Spinnaker, OpenKinect, librealsense, CL PS3 Eye Driver, videoInput, ARToolKitPlus, flandmark, Leptonica和Tesseract),并提供实用程序类,使其功能更容易在Java平台(包括Android)上使用。

JavaCV还具有硬件加速全屏图像显示(CanvasFrame和GLCanvasFrame),易于使用的方法在多核上并行执行代码(parallel),用户友好的相机和投影仪的几何和颜色校准(GeometricCalibrator, ProCamGeometricCalibrator, ProCamColorCalibrator),特征点的检测和匹配(ObjectFinder),一组实现投影仪-相机系统的直接图像对齐的类(主要是GNImageAligner,projectvetransformer, projvecolortransformer, ProCamTransformer和ReflectanceInitializer),一个blob分析包(Blobs),以及JavaCV类中的其他功能。其中一些类也有OpenCL和OpenGL对应的类,它们的名字以CL结尾或以GL开头,例如:JavaCVCL, GLCanvasFrame等。

要学习如何使用API,因为目前缺乏文档,请参考下面的示例用法部分以及示例程序,包括两个Android (FacePreview.java和RecordActivity.java),也可以在samples目录中找到。您还可以参考ProCamCalib和ProCamTracker的源代码,以及从OpenCV2 Cookbook和相关wiki页面移植的示例。

Maven

  <dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv-platform</artifactId>
    <version>1.5.8</version>
  </dependency>

软件环境

要使用JavaCV,首先需要下载并安装以下软件:

Java SE 7或更新版本的实现:

  • OpenJDK OpenJDK: Download and install or

  • Oracle JDK http://www.oracle.com/technetwork/java/javase/downloads/ or

  • IBM JDK http://www.ibm.com/developerworks/java/jdk/

此外,虽然并不总是必需的,JavaCV的一些功能也依赖于:

  • CL Eye Platform SDK (Windows only) CL - Downloads - Code Laboratories

    CL Eye平台SDK为开发人员提供了对相机使用和操作的完全访问和控制。为了可移植性和易用性,所提供的api作为标准的基于C的函数公开,还包括作为基线测试框架的所有示例应用程序的完整源代码。

  • Android SDK API 21 or newer http://developer.android.com/sdk/

  • JOCL and JOGL from JogAmp JogAmp.org - Java graphics, audio, media and processing libraries exposing OpenGL, OpenCL, OpenAL and OpenMAX

    JogAmp是用于3D图形、多媒体和处理的高性能Java™库的家。

    JOGL, JOCL和JOAL提供跨平台Java™语言绑定到OpenGL®,OpenCL™,OpenAL和OpenMAX api。

最后,请确保所有内容具有相同的位,32位和64位模块在任何情况下都不能混合。

JavaCV-Examples

这个项目包含使用JavaCV和其他javacpp-presets项目中的库包装器的示例。

  • OpenCV_Cookbook - Robert laganiere的书《OpenCV Computer Vision Application Programming Cookbook》中提供的示例的JavaCV版本。Cookbook中的原始示例是用c++编写的,这里它们被翻译为使用JavaCV API。

  • 使用flandmark库的示例。

  • 使用JVM包装flr /Point Grey FlyCapture SDK的示例。

  • 使用JVM包装Flir/Point Grey Spinnaker SDK的示例

OpenCV Cookbook Examples

概述

OpenCV Cookbook示例说明了OpenCV与JavaCV的使用。这些例子是从Robert laganie:1的书《OpenCV 2计算机视觉应用程序编程指南》中移植的c++代码开始的。后来更新为第四版的书“OpenCV计算机视觉应用程序编程 Cookbook第四版”。书中的示例使用OpenCV c++ API。在这里,它们被转换为使用JavaCV和JavaCPP-Presets api。

OpenCV(开源计算机视觉)是一个包含数百种算法的库,用于计算机视觉和视频分析。OpenCV可以通过两种方式在JVM上运行。首先是由OpenCV提供的Java包装器。第二种是基于JavaCPP (JVM的c++包装器引擎)的包装器,称为OpenCV JavaCPP预置。还有其他计算机视觉相关库的JavaCPP预设,如:FFmpeg, libdc1394, PGR FlyCapture, OpenKinect, videoInput, ARToolKitPlus, landmark等。JavaCV结合了JavaCPP预置中的库,并添加了一些额外的功能,使它们更容易在JVM上使用。

OpenCV Cookbook Examples项目演示了通过JavaCV和OpenCV JavaCPP预设使用OpenCV。当前的版本更新是为了匹配Robert laganie:1的书“OpenCV计算机视觉应用程序编程 Cookbook第二版”的第二版。它旨在与OpenCV .4一起使用(JavaCV 1节)。

虽然示例中的代码主要是用Scala编写的,Scala是领先的JVM语言之一。它可以很容易地转换为Java和运行在JVM上的其他语言,例如Groovy。在大多数JVM语言中,JavaCV API的使用非常相似。在Java版本中提供了一些示例。

示例

下面是一个快速预览,将原始c++示例与使用JavaCV包装器的Scala和Java代码进行比较。

下面是一个原始的c++示例,它打开一个图像(没有错误检查),创建一个窗口,在窗口中显示图像,并等待5秒后退出。

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>

int main() {
    // Read an image
    cv::Mat src = cv::imread("data/boldt.jpg");
    display(src, "Input")

	// Apply Laplacian filter
    cv::Mat dest;
    cv::Laplacian(src, dest, src.depth(), 1, 3, 0, BORDER_DEFAULT);
    display(dest, "Laplacian");

    // wait key for 5000 ms
    cv::waitKey(5000);

    return 1;
}

//---------------------------------------------------------------------------

void display(Mat image, char* caption) {
    // Create image window named "My Image"
    cv::namedWindow(caption);

    // Show image on window
    cv::imshow(caption, image);
}

上面的c++示例使用JavaCV包装器转换为Scala:

import javax.swing._
import org.bytedeco.javacv._
import org.bytedeco.opencv.global.opencv_core._
import org.bytedeco.opencv.global.opencv_imgcodecs._
import org.bytedeco.opencv.global.opencv_imgproc._
import org.bytedeco.opencv.opencv_core._

object MyFirstOpenCVApp extends App {

  // Read an image.
  val src = imread("data/boldt.jpg")
  display(src, "Input")

  // Apply Laplacian filter
  val dest = new Mat()
  Laplacian(src, dest, src.depth(), 1, 3, 0, BORDER_DEFAULT)
  display(dest, "Laplacian")

  //---------------------------------------------------------------------------

  /** Display `image` with given `caption`. */
  def display(image: Mat, caption: String): Unit = {
    // Create image window named "My Image."
    val canvas = new CanvasFrame(caption, 1)

    // Request closing of the application when the image window is closed.
    canvas.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)

    // Convert from OpenCV Mat to Java Buffered image for display
    val converter = new OpenCVFrameConverter.ToMat()
    // Show image on window
    canvas.showImage(converter.convert(image))
  }
}

现在用Java表达相同的例子。请注意,JavaCV API的使用与Scala和Java代码中的完全相同。唯一的实际区别是,在Java代码中更冗长,您必须显式地为每个变量提供类型,而在Scala中这是可选的。

import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.opencv.opencv_core.Mat;

import javax.swing.*;
import java.awt.image.BufferedImage;

import static opencv_cookbook.OpenCVUtilsJava.toBufferedImage;
import static org.bytedeco.opencv.global.opencv_core.BORDER_DEFAULT;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imread;
import static org.bytedeco.opencv.global.opencv_imgproc.Laplacian;

public class MyFirstOpenCVAppInJava {

    public static void main(String[] args) {

        // Read an image.
        final Mat src = imread("data/boldt.jpg");
        display(src, "Input");

        // Apply Laplacian filter
        final Mat dest = new Mat();
        Laplacian(src, dest, src.depth(), 1, 3, 0, BORDER_DEFAULT);
        display(dest, "Laplacian");
    }

    //---------------------------------------------------------------------------

    static void display(Mat image, String caption) {
        // Create image window named "My Image".
        final CanvasFrame canvas = new CanvasFrame(caption, 1.0);

        // Request closing of the application when the image window is closed.
        canvas.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        // Convert from OpenCV Mat to Java Buffered image for display
        final BufferedImage bi = toBufferedImage(image);

        // Show image on window.
        canvas.showImage(bi);
    }
}

OpenCV文档

如果您正在寻找一个特定的OpenCV操作,请使用OpenCV文档(OpenCV documentation index)。快速搜索框特别有用。该文档包含了C/ c++ OpenCV API可选使用方式的描述。

如何使用JavaCV示例

OpenCV Cookbook示例项目是作为Robert laganie:1的书“OpenCV计算机视觉应用程序编程Cookbook第二版”的伙伴。推荐的方法是在对如何将Cookbook的c++代码转换为JavaCV有疑问时阅读Cookbook并参考JavaCV示例。这本书解释了算法是如何工作的。JavaCV示例只提供了与JavaCV API细节相关的非常简短的注释。

使用JavaCV示例的最简单方法是在线浏览位于[src/main]中的代码。您也可以使用Git或ZIP文件将其下载到计算机上。

通过最小的设置,您可以轻松地在自己的计算机上执行示例。这是JavaCV的好处之一——它提供了在各种平台上运行OpenCV所需的所有二进制文件。在第1章的README中解释了这个设置。

示例代码的组织结构

代码被组织成与Cookbook第1版中的章节相对应的包,例如opencv_cookbook.chapter8。它与第二版非常相似。个别的例子大致对应于书中每一章的章节。

第1章描述了运行这些示例的IDE设置,给出了一个加载和显示图像的基本示例,以及一个执行基本图像处理的基本GUI示例。

示例列表

第一章:使用图像

  • Ex1MyFirstOpenCVApp -加载图像并在窗口中显示它(CanvasFrame)

  • Ex2MyFirstGUIFXApp -使用ScalaFX (JavaFX包装器)构建的简单GUI应用程序。该应用程序在左侧有两个按钮“打开图像”和“处理”。打开的图像显示在中间。当按下“处理”按钮时,图像被翻转过来,其红色和蓝色通道被交换。有关Swing版本,请参阅Ex2MyFirstGUIApp。

  • Ex2MyFirstGUIApp -使用Scala Swing构建的简单GUI应用程序。该应用程序在左侧有两个按钮“打开图像”和“处理”。打开的图像显示在中间。当按下“处理”按钮时,图像被翻转过来,其红色和蓝色通道被交换。有关JavaFX版本,请参阅Ex2MyFirstGUIFXApp。

  • Ex3LoadAndSave -读取,保存,显示和绘制图像。

第二章:操纵像素

  • Ex1Salt -设置个人,随机选择,像素到一个固定的值。使用ImageJ的ImageProcessor来访问像素。

  • Ex2ColorReduce -通过相同的方式修改所有波段的颜色值来减少图像中的颜色。

  • ex3锐化-使用内核卷积锐化图像:filter2D()。

  • Ex4BlendImages -混合两个图像使用加权加法:cvAddWeighted()。

  • ex5roillogo -使用感兴趣的区域将小图像粘贴到较大的图像中:IplROI和cvCopy()。

第三章:用类处理图像

  • Ex1ColorDetector -将RGB颜色与目标颜色进行比较,与目标颜色相似的颜色在输出图像中被分配为白色,其他像素被设置为黑色。

  • Ex2ColorDetectorSimpleApplication—第一个示例的处理过程相同,但演示了一个简单的UI。

  • ex3colordetectormvapplication—相同的处理是第一个示例,但演示了一个更详细的UI。

  • Ex4ConvertingColorSpaces -类似于第一个例子,但是颜色距离是在Lab*颜色空间中计算的。说明cvtColor函数的使用。

第四章:用直方图计算像素

  • Ex1ComputeHistogram -使用实用程序类Histogram1D计算直方图,并将值打印到屏幕上。

  • Ex2ComputeHistogramGraph -显示使用实用程序类Histogram1D创建的直方图的图形。

  • Ex3Threshold -使用OpenCV threshold()方法将图像中的像素分离为前景和背景。

  • Ex4InvertLut—通过反转其查找表来创建倒立的图像。

  • Ex5EqualizeHistogram -使用直方图均衡化增强图像。

  • Ex6ContentDetectionGrayscale -使用灰度图像中区域的直方图来创建“模板”,通过整个图像来检测与该模板相似的像素。举例说明cvCalcBackProject()方法的使用。

  • Ex7ContentDetectionColor -使用区域直方图在彩色图像中创建“模板”,通过整个图像来检测与该模板相似的像素。依赖于工具类ColorHistogram和ContentFinder。

  • Ex8MeanShiftDetector -使用彩色图像中的区域直方图来创建“模板”,使用mean shift算法在另一张图像中找到“模板”的最佳匹配位置。举例说明cvMeanShift()方法的用法。

  • 使用辅助类ImageComparator计算图像相似度度量。

  • 执行直方图和查找表操作的Helper类,对应于OpenCV Cookbook中部分c++类Histogram1D的样例代码。举例说明OpenCV方法的使用:cvLUT(), cvEqualizeHist(), cvCreateHist(), cvCalcHist(), cvQueryHistValue_1D(), cvReleaseHist()。

  • ColorHistogram -帮助类简化了彩色图像cvCalcHist()方法的使用。

  • 使用cvCalcBackProject()方法进行模板匹配的辅助类。

  • ImageComparator -使用cvCompareHist()计算图像相似度的辅助类。

第五章:用形态学操作变换图像

  • 侵蚀和扩张-形态侵蚀和扩张:cvErode()和cvDilate()。

  • Ex2OpeningAndClosing -形态学打开和关闭:cvMorphologyEx()。

  • Ex3EdgesAndCorners -使用形态学过滤器检测边缘和角落。

  • Ex4WatershedSegmentation -图像分割使用分水岭算法。

  • Ex5GrabCut -使用grabCut()从背景中分离对象。

  • MorphoFeatures -等价于同名的c++类,包含形态学角检测的方法。

  • WatershedSegmenter -“使用分水岭分割图像”一节的辅助类。

第六章:过滤图像

  • Ex1LowPassFilter -模糊与高斯滤波器。

  • Ex2MedianFilter -用中值滤波器去除噪声。

  • Ex3DirectionalFilters -使用Sobel边缘检测滤波器。

  • 使用拉普拉斯滤波器的边缘检测。

  • LaplacianZC -计算Laplacian和过零,用于Ex4Laplacian。

第七章:提取线条、轮廓和组件

  • Ex1CannyOperator -检测轮廓与Canny算子。

  • Ex2HoughLines -使用标准Hough变换方法检测线条。

  • Ex3HoughLineSegments -使用概率霍夫变换方法检测线段。

  • Ex4HoughCircles -使用霍夫变换方法检测圆。

  • Ex5ExtractContours -使用连接的组件从二值图像中提取轮廓。

  • Ex6ShapeDescriptors -计算各种形状描述符:边界框,封闭圆,近似多边形,凸壳,质心。

  • LineFinder -使用概率霍夫变换方法检测线段的辅助类,用于Ex3HoughLineSegments。

第八章:发现兴趣点

  • Ex1HarrisCornerMap -计算哈里斯角强度图像。

  • Ex2HarrisCornerDetector -使用Harris角强度图像来检测定位良好的角,用一个角取代几个位置较近的检测(模糊)。使用HarrisDetector辅助类。

  • Ex3GoodFeaturesToTrack -使用GoodFeatures跟踪检测器的例子。

  • Ex4FAST -使用FAST检测器的示例。

  • Ex5SURF -使用SURF检测器的示例。

  • Ex6SIFT -使用SIFT检测器的示例。

  • 帮助类,用于哈里斯角强度图像的检测和定位。距离较近的探测(模糊)被单个探测取代。

第九章:发现兴趣点

  • Ex2TemplateMatching -从第一个图像(模板)和第二个图像中找到一个小补丁之间的最佳匹配。

  • ex7descripbingsurf -计算SURF特征,提取它们的描述符,并在同一物体的两幅图像之间找到最佳匹配的描述符。

第十章:估计图像中的投影关系

  • Ex1FindChessboardCorners -演示了相机校准步骤之一,在校准板中检测棋盘模式。

  • Ex2CalibrateCamera -相机校准示例,展示了如何校正光学器件可能引入的几何变形。使用CameraCalibrator助手类。

  • Ex3ComputeFundamentalMatrix -使用两幅图像之间检测和匹配的特征,计算描述两幅图像之间投影关系的基本矩阵。

  • Ex4MatchingUsingSampleConsensus -说明RANSAC(随机抽样共识)策略的使用。大多数计算是由RobustMatcher helper类完成的。

  • Ex5Homography -描述两个图像中点之间关系的另一种方法,使用homography。展示了如何将一个对象的部分视图的两个图像拼接在一起的示例。大多数计算是由RobustMatcher helper类完成的。

  • 实现摄像机校准算法的助手类。

  • RobustMatcher -实现基于RANSAC的算法,例如Ex4MatchingUsingSampleConsensus和Ex5Homography。

第十一章:处理视频序列

  • Ex1ReadVideoSequence -读取并显示视频。

  • Ex2ProcessVideoFrames -使用Canny边缘检测器处理视频文件中的帧;在屏幕上显示输出视频。使用辅助类VideoProcessor。

  • Ex3WriteVideoSequence -使用Canny边缘检测器处理视频文件中的帧;将输出写入视频文件。使用辅助类VideoProcessor。

  • Ex4TrackingFeatures -跟踪视频中的移动对象,标记屏幕上显示的视频中的跟踪点。大部分的实现是在FeatureTracker helper类中完成的。

  • Ex5ForegroundSegmenter -通过背景估计检测视频中的移动对象。背景使用“简单”移动平均方法建模,实现在助手类“BGFBSegmenter”中。

  • Ex6MOGMotionDetector -一个更复杂的运动检测器,使用混合高斯方法建模背景。

  • BGFBSEgmenter -通过使用移动平均线对背景建模,将“静态”背景与“移动”前景分开。使用的例子'Ex5ForegroundSegmenter'。

  • FeatureTracker -使用光流算法跟踪移动特征,例如Ex4TrackingFeatures。

  • VideoProcessor -处理视频文件的辅助类,加载和应用处理到单独的帧,例如:Ex2ProcessVideoFrames, Ex3WriteVideoSequence, Ex4TrackingFeatures和Ex5ForegroundSegmenter。

第十五章:OpenCV高级特性

  • Ex1FaceDetection -使用预训练的深度学习神经网络模型检测图像中的人脸。

其他通用技术

  • OpenCVUtils -读取和写入图像文件,显示图像,绘制图像的特征,OpenCV图像和数据表示之间的转换。

Why Scala?

之所以选择Scala,是因为它比Java更具表现力。您可以用更少的代码获得相同的结果。更小的样板代码使示例更容易阅读和理解。编译后的Scala代码速度很快,类似于Java和c++。

与Java或c++不同,Scala支持编写脚本——无需显式编译即可执行的代码。Scala也有一个控制台,称为REPL,可以在其中输入单行代码并当场执行。这两个特性使得在Scala中构建基于opencv的程序比在Java中更容易。最后但并非最不重要的一点是,IDE对Scala的支持达到了成熟的程度,允许轻松地创建、修改和执行Scala代码。特别是,用于JetBrains IDEA的Scala插件工作得非常好。还有对Eclipse和NetBeans的Scala支持。

学习地址

https://github.com/bytedeco/javacv

Welcome to OpenCV Java Tutorials documentation! — OpenCV Java Tutorials 1.0 documentation

GitHub - bytedeco/javacv-examples: Examples of using JavaCV / OpenCV library on Java Virtual Machine

关于类、API等如果有疑问可以看考openCV、FFmpeg的方法介绍,javaCV只不过是对它们的封装,或者直接问ChatGPT吧,简单高效!

图像简单处理代码示例

图像处理的API主要集中在opencv-4.6.0-1.5.8.jar包下,该包有两个目录“bytedeco.opencv”与“opencv”,两个package下有许多同名的类与静态方法,请尽量采用“bytedeco.opencv”package下的类与方法。

1.打开保存一张图

// 打开一张图
Mat image = imread("D:\\2projects_database\\javacvdemo\\src\\main\\java\\com\\example\\img\\future_city.jpg");
// 保存图像       imwrite("D:\\2projects_database\\javacvdemo\\src\\main\\java\\com\\example\\img\\future_city_add_text.jpg", image);

 2.画直线

/**
 * 画直线
 * @param image 图片
 * @param x1 起点横坐标
 * @param y1 起点纵坐标
 * @param x2 终点横坐标
 * @param y2 终点纵坐标
 * @param color 线条颜色
 */
public static void drawLine(Mat image, int x1, int y1, int x2, int y2, Scalar color) {
    Point pt1 = new Point(x1, y1);
    Point pt2 = new Point(x2, y2);
    line(image, pt1, pt2, color);
}

3.画圆圈

/**
 * 画圆圈
 * @param image 图像
 * @param x 圆心横坐标
 * @param y 圆心纵坐标
 * @param radius 半径
 * @param color 线条颜色
 * @param thickness 线条厚度
 * @param lineType 线条类型
 * @param shift 坐标值的小数位数
 */
public static void drawCircle(Mat image, int x, int y, int radius, Scalar color, int thickness, int lineType, int shift) {
    Point center = new Point(x, y);
    circle(image, center, radius, color, thickness, lineType, shift);
}

4.画折现

/**
 * 画折现
 * @param image 图像
 * @param points 端点数组
 * @param color 线条颜色
 */
public static void drawCurve(Mat image, Point[] points, Scalar color) {
    for (int i = 0; i < points.length - 1; i++) {
        line(image, points[i], points[i+1], color);
    }
}

5.添加文字水印

/**
 * 添加文字水印
 * @param image 图像
 * @param text 文字内容
 * @param position 文字位置
 * @param fontFace 字体类型
 * @param fontScale 字体大小
 * @param color 字体颜色
 */
public static void addTextWatermark(Mat image, String text, Point position, int fontFace, double fontScale, Scalar color) {
    putText(image, text, position, fontFace, fontScale, color);
}

6.裁剪并局部放大

/**
 * 裁剪图像并局部放大
 * @param image 图像
 * @param x 起始位置横坐标
 * @param y 起始位置纵坐标
 * @param width 裁剪宽度
 * @param height 裁剪高度
 * @param zoomFactor 放大倍数
 */
public static void cropAndZoomImage(Mat image, int x, int y, int width, int height, int zoomFactor) {
    Rect roi = new Rect(x, y, width, height);
    Mat croppedImage = new Mat(image, roi);
    resize(croppedImage, croppedImage, new Size(width*zoomFactor, height*zoomFactor));
    // 保存图像
    imwrite("D:\\2projects_database\\javacvdemo\\src\\main\\java\\com\\example\\img\\cropAndZoomImage.png", croppedImage);
    System.out.println("resize rows:" + croppedImage.rows());
    System.out.println("resize cols:" + croppedImage.cols());
}

7.人脸检测

package com.example.img.code;

import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imread;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imwrite;
import static org.bytedeco.opencv.global.opencv_imgproc.LINE_8;
import static org.bytedeco.opencv.global.opencv_imgproc.rectangle;

/**
 * @Author yrz
 * @create 2023/5/12 11:22
 * @Description TODO
 */

public class FaceDetector {
    public static void main(String[] args) {
        // Load the image
        Mat image = imread("D:/2projects_database/javacvdemo/src/main/java/com/example/img/face.jpg");

        // Load the face cascade classifier
        CascadeClassifier faceCascade = new CascadeClassifier("D:/2projects_database/javacvdemo/src/main/java/com/example/img/haarcascade_frontalface_alt.xml");

        // Detect faces in the image
        RectVector faceDetections = new RectVector();
        faceCascade.detectMultiScale(image, faceDetections);

        // Draw a rectangle around each detected face
        for (Rect rect : faceDetections.get()) {
            rectangle(image, new Point(rect.x(), rect.y()), new Point(rect.x() + rect.width(), rect.y() + rect.height()),
                    new Scalar(0, 255, 0, 0), 2, LINE_8, 0);
        }
        // Save the image with the detected faces
        imwrite("D:/2projects_database/javacvdemo/src/main/java/com/example/img/face_output.jpg", image);
    }
}

javacv,后端服务开发,java,音视频,开发语言

视频简单处理代码示例

视频处理的API主要集中在javacv-1.5.8.jar包下。文章来源地址https://www.toymoban.com/news/detail-772498.html

1.打开视频文件

/**
 * 打开视频文件
 * @param filename
 */
public static void readDisplayVideo(String filename){
    FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(filename);
    // Open video video file
    try {
        grabber.start();
    } catch (FFmpegFrameGrabber.Exception e) {
        e.printStackTrace();
    }
    // Prepare window to display frames
    CanvasFrame canvasFrame = new CanvasFrame("Extracted Frame", 1);
    canvasFrame.setCanvasSize(grabber.getImageWidth(), grabber.getImageHeight());
    // Exit the example when the canvas frame is closed
    canvasFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    long delay = Math.round(1000d / grabber.getFrameRate());
    // Read frame by frame, stop early if the display window is closed
    Frame frame;
    try {
        while ((frame = grabber.grab()) != null && canvasFrame.isVisible()) {
            // Capture and show the frame
            canvasFrame.showImage(frame);
            // Delay
            Thread.sleep(delay);
        }
        // Close the video file
        grabber.release();
    } catch (FFmpegFrameGrabber.Exception e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

2.抓取视频指定时间的帧保存为图像

/**
 * 抓取视频指定时间的帧保存为图像
 * @param videoPath
 * @param imagePath
 * @param timeInSeconds
 */
public static void grabFrameAtTime(String videoPath, String imagePath, long timeInSeconds) {
    FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoPath);
    Java2DFrameConverter converter = new Java2DFrameConverter();
    try {
        grabber.start();
        grabber.setTimestamp(timeInSeconds);
        Frame grab = grabber.grabImage();
        BufferedImage bufferedImage = converter.getBufferedImage(grab, converter.getBufferedImageType(grab) ==
                BufferedImage.TYPE_CUSTOM ? 1.0 : 1.0, false, null);
        saveImage(bufferedImage, imagePath);
        grabber.stop();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public static void saveImage(BufferedImage image, String imagePath) {
    try {
        ImageIO.write(image, "jpg", new File(imagePath));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3.录屏

/**
 * 录屏
 * @param filename 文件名称
 * @param seconds 时长
 */
public static void recordScreen(String filename, int seconds) {
    final int FRAME_RATE = 30;
    final Dimension SCREEN_SIZE = Toolkit.getDefaultToolkit().getScreenSize();
    // 创建录屏对象,并设置相关属性
    FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(filename, SCREEN_SIZE.width, SCREEN_SIZE.height);
    recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
    recorder.setFormat("mp4");
    recorder.setFrameRate(FRAME_RATE);
    Java2DFrameConverter converter = new Java2DFrameConverter();
    try {
        // 初始化录屏对象
        recorder.start();
        Robot robot = new Robot();
        BufferedImage screenShot;

        // 系统当前时间
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
        // 30秒后
        LocalDateTime plus = now.plus(seconds, ChronoUnit.SECONDS);
        System.out.println(plus);

        // 开始录制
        while (true) {
            // 获取屏幕截图并写入文件
            screenShot = robot.createScreenCapture(new Rectangle(SCREEN_SIZE));
            recorder.record(converter.getFrame(screenShot));
            // 停止时间
            LocalDateTime time = LocalDateTime.now();
            if(plus.isBefore(time)){
                System.out.println(time);
                break;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // 关闭录制器
        try {
            recorder.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.给视频添加水印

/**
     * 给视频添加水印
     * @param filename
     * @param outname
     * @param picName
     * @throws Exception
     */
    public static void addWatermark (String filename, String outname, String picName) throws Exception {
        // Load the video
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(filename);
        grabber.start();
        // Create a new video recorder
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outname, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setFormat("mp4");
        recorder.setFrameRate(grabber.getFrameRate());
        // 开启录制
        recorder.start();
        // Create a new Java2DFrameConverter
        Java2DFrameConverter converter = new Java2DFrameConverter();
        // Create a new BufferedImage to hold the watermark image
        // 图片水印
        BufferedImage watermarkImage = ImageIO.read(new File(picName));
        // 自定义文字水印
//        BufferedImage watermarkImage = createWatermarkImage("Hello, world!", new Font("Arial", Font.BOLD, 50),
//                Color.WHITE, new Color(0, 0, 0, 0));
        // Loop through each frame in the video
        Frame frame;
        while ((frame = grabber.grabFrame()) != null) {
            // Convert the frame to a BufferedImage
            BufferedImage image = converter.getBufferedImage(frame);
            if(image == null){
                continue;
            }
            // Create a new Graphics2D object to draw the watermark
            Graphics2D g2d = image.createGraphics();
            // Draw the watermark on the image
            g2d.drawImage(watermarkImage, 0, 0, null);
            // Dispose of the Graphics2D object
            g2d.dispose();
            // Convert the BufferedImage back to a Frame and write it to the output video
            recorder.record(converter.convert(image));
        }
        // Stop the grabber and recorder
        grabber.stop();
        grabber.release();
        recorder.stop();
        recorder.release();
    }

    private static BufferedImage createWatermarkImage(String text, Font font, Color foreground, Color background) {
        FontRenderContext frc = new FontRenderContext(null, true, true);
        TextLayout layout = new TextLayout(text, font, frc);
        Rectangle2D bounds = layout.getBounds();

        BufferedImage image = new BufferedImage(
                (int) bounds.getWidth(), (int) bounds.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = image.createGraphics();

        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

        if (background != null) {
            g2d.setBackground(background);
            g2d.clearRect(0, 0, image.getWidth(), image.getHeight());
        }

        g2d.setFont(font);
        g2d.setColor(foreground);

        layout.draw(g2d, 0, -(float) bounds.getY());

        if (background != null) {
            ColorConvertOp colorConvert = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_sRGB),
                    null);
            colorConvert.filter(image, image);
        }

        g2d.dispose();

        return image;
    }

到了这里,关于Java音视频处理——JavaCV的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序 - 超详细 “纯前端“ 将文件上传到阿里云 OSS,最新阿里云 OSS 直传音视频、图片、word、excel、ppt、office 文档(全程无需后端,前端文件直传阿里云oss服务器)

    网上的教程乱七八糟却文件少代码(并且没注释),而且都已经很老了,对于新手来说真的无从下手。 本文站在新手小白的角度, 实现微信小程序开发中,“前端直传” 上传文件到阿里云oss对象存储的详细教程, 无需后端 (纯前端自己完成所有签名、上传),保证 100% 成

    2024年02月13日
    浏览(159)
  • [音视频处理] FFmpeg使用指北1-视频解码

    本文将详细介绍如何使用ffmpeg 4.4在C++中解码多种格式的媒体文件,这些媒体文件可以是视频、视频流、图片,或是桌面截屏或USB摄像头的实时图片。解码文件后,还将每帧图片转换为OpenCV的Mat格式以供后续使用。 目录 1 基于ffmpeg的媒体文件解码 1.1 简介 1.2 详细代码 2 ffmpeg函

    2024年02月07日
    浏览(67)
  • Python的音视频文件处理

    ffmpeg-python 是 ffmpeg 的一个包装,通过 python 调用 ffmpeg 的 API ,实现高效的音视频文件处理 开始之前 安装 ffmpeg 安装 ffmpeg-python 参考 ffmpeg官方网站 ffmpeg-python的代码库与技术文档 技术背景 音视频文件处理流程 输入文件 ⟹ 解封装 已编码的数据包 ⟹ 解码 被编码的帧 ( 可进行

    2024年02月03日
    浏览(55)
  • 【Webpack】处理字体图标和音视频资源

    打开阿里巴巴矢量图标库open in new window 选择想要的图标添加到购物车,统一下载到本地 src/fonts/iconfont.ttf src/fonts/iconfont.woff src/fonts/iconfont.woff2 src/css/iconfont.css 注意字体文件路径需要修改 src/main.js public/index.html type: \\\"asset/resource\\\" 和 type: \\\"asset\\\" 的区别: type: \\\"asset/resource\\\"  相当于

    2024年02月20日
    浏览(51)
  • FFmpeg音视频处理工具介绍及应用

    FFmpeg项目由 Fabrice Bellard在2000年创立。到目前为止,FFmpeg项目的开发者仍然与VLC、MPV、dav1d、x264等多媒体开源项目有着广泛的重叠。Ffmpeg(FastForward Mpeg)是一款遵循GPL的开源软件,在音视频处理方面表现十分优秀,几乎囊括了现存所有的视音频格式的编码,解码、转码、混合

    2024年02月08日
    浏览(77)
  • 【图像处理】音视频色彩:RGB/YUV

    目录 1.RGB  1.1介绍        1.2分类 1.2.1RGB16 1)RGB565 2)RGB555 1.2.2RGB24 1.2.3RGB222 /

    2024年02月20日
    浏览(52)
  • 微信小程序音视频格式转换及处理

    在开发微信小程序时,经常会遇到需要对音视频进行格式转换和处理的情况。为了实现这一功能,我们可以借助FFmpeg这个强大的开源多媒体处理工具。本文将介绍如何在微信小程序中使用FFmpeg进行音视频格式转换。 首先,我们需要将FFmpeg引入到微信小程序中。由于微信小程序

    2024年04月23日
    浏览(94)
  • ffmpeg系列学习——FFmpeg的音视频处理

    1.音视频的采样率、采样位深度和声道数 音频和视频的采样率、采样位深度和声道数是媒体文件中的重要参数,它们会直接影响到音视频的质量和文件大小。下面对它们进行详细解释: 采样率 采样率指音频每秒钟采样的次数,用赫兹(Hz)表示。采样率越高,音频的还原度越

    2024年02月04日
    浏览(63)
  • JavaCV与FFmpeg:音视频流处理技巧

    1. JavaCV简介 JavaCV是一个开源的Java接口,为OpenCV、FFmpeg和其他类似工具提供了封装。它允许Java开发者直接在他们的应用程序中使用这些强大的本地库,而无需深入了解复杂的本地代码。JavaCV特别适用于处理图像和视频数据,提供了一系列的功能,如图像捕获、处理和视频编解

    2024年02月04日
    浏览(61)
  • 音视频数据处理-H265/HEVC视频码流分析

    一、H265概述 H265/HEVC(Hight Efficiency Video Coding)是由ITU-T和ISO/IEC两大组织在H264/AVC的基础之上推出的新一代高效视频编码标准,主要为应对高清和超高清视频在网络传输和数据存储方面带来的挑战。上一篇文章对H264/AVC视频码流进行了详细的分析,本文继续从数据处理的角度对

    2024年02月11日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包