商业支持:
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
、 ProjectiveTransformer
、 ProjectiveColorTransformer
、 ProCamTransformer
和ReflectanceInitializer
)、斑点分析包( Blobs
)以及JavaCV
类中的其他功能。其中一些类还具有 OpenCL 和 OpenGL 对应项,它们的名称以CL
结尾或以GL
开头,即: JavaCVCL
、 GLCanvasFrame
等。
要了解如何使用该 API,由于目前缺乏文档,请参阅下面的示例使用部分以及示例程序,其中包括两个适用于 Android 的程序( FacePreview.java
和RecordActivity.java
),也可以在samples
目录中找到。您可能还会发现参考 ProCamCalib 和 ProCamTracker 的源代码以及从 OpenCV2 Cookbook 和相关 wiki 页面移植的示例很有用。
请随时通知我您对代码所做的任何更新或修复,以便我可以将它们集成到下一个版本中。谢谢你!如果您在使用该软件时遇到任何问题,请随时在邮件列表或论坛上提问!我确信它远非完美......
包含 JAR 文件的存档可作为版本提供。二进制存档包含适用于 Android、iOS、Linux、Mac OS X 和 Windows 的构建。特定子模块或平台的 JAR 文件也可以从 Maven 中央存储库单独获取。
要手动安装 JAR 文件,请按照下面的手动安装部分中的说明进行操作。
我们还可以使用以下命令自动下载和安装所有内容:
pom.xml
文件内) < dependency >
< groupId >org.bytedeco</ groupId >
< artifactId >javacv-platform</ artifactId >
< version >1.5.11</ version >
</ dependency >
build.gradle.kts
或build.gradle
文件内) dependencies {
implementation( " org.bytedeco:javacv-platform:1.5.11 " )
}
project.clj
文件内) :dependencies [
[org.bytedeco/javacv-platform " 1.5.11 " ]
]
build.sbt
文件内) libraryDependencies += " org.bytedeco " % " javacv-platform " % " 1.5.11 "
这会下载所有平台的二进制文件,但要仅获取一个平台的二进制文件,我们可以将javacpp.platform
系统属性(通过-D
命令行选项)设置为android-arm
、 linux-x86_64
、 macosx-x86_64
、 windows-x86_64
等,具体请参考 JavaCPP Presets 的 README.md 文件。 Gradle 用户可以使用的另一个选项是 Gradle JavaCPP,同样,Scala 用户可以使用 SBT-JavaCV。
要使用JavaCV,您首先需要下载并安装以下软件:
此外,尽管并不总是必需的,JavaCV 的一些功能也依赖于:
最后,请确保所有内容都具有相同的位数: 32 位和 64 位模块在任何情况下都不能混合。
只需将所有所需的 JAR 文件( opencv*.jar
、 ffmpeg*.jar
等)以及javacpp.jar
和javacv.jar
放在类路径中的某个位置即可。以下是针对常见情况的一些更具体的说明:
NetBeans(Java SE 7 或更高版本):
Eclipse(Java SE 7 或更高版本):
Visual Studio Code(Java SE 7 或更高版本):
+
。IntelliJ IDEA(Android 7.0 或更高版本):
app/libs
子目录中。+
”,然后选择“2 文件依赖项”。libs
子目录中选择所有 JAR 文件。android:extractNativeLibs="true"
之后,例如 OpenCV 和 FFmpeg 的包装类可以自动访问它们的所有 C/C++ API:
类定义基本上是 C/C++ 中原始头文件到 Java 的移植,我特意决定保留尽可能多的原始语法。例如,下面是一个尝试加载图像文件、对其进行平滑并将其保存回磁盘的方法:
import org . bytedeco . opencv . opencv_core .*;
import org . bytedeco . opencv . opencv_imgproc .*;
import static org . bytedeco . opencv . global . opencv_core .*;
import static org . bytedeco . opencv . global . opencv_imgproc .*;
import static org . bytedeco . opencv . global . opencv_imgcodecs .*;
public class Smoother {
public static void smooth ( String filename ) {
Mat image = imread ( filename );
if ( image != null ) {
GaussianBlur ( image , image , new Size ( 3 , 3 ), 0 );
imwrite ( filename , image );
}
}
}
JavaCV 还在 OpenCV 和 FFmpeg 之上提供了帮助程序类和方法,以方便它们与 Java 平台的集成。这是一个小演示程序,演示了最常用的部分:
import java . io . File ;
import java . net . URL ;
import org . bytedeco . javacv .*;
import org . bytedeco . javacpp .*;
import org . bytedeco . javacpp . indexer .*;
import org . bytedeco . opencv . opencv_core .*;
import org . bytedeco . opencv . opencv_imgproc .*;
import org . bytedeco . opencv . opencv_calib3d .*;
import org . bytedeco . opencv . opencv_objdetect .*;
import static org . bytedeco . opencv . global . opencv_core .*;
import static org . bytedeco . opencv . global . opencv_imgproc .*;
import static org . bytedeco . opencv . global . opencv_calib3d .*;
import static org . bytedeco . opencv . global . opencv_objdetect .*;
public class Demo {
public static void main ( String [] args ) throws Exception {
String classifierName = null ;
if ( args . length > 0 ) {
classifierName = args [ 0 ];
} else {
URL url = new URL ( "https://raw.github.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_alt.xml" );
File file = Loader . cacheResource ( url );
classifierName = file . getAbsolutePath ();
}
// We can "cast" Pointer objects by instantiating a new object of the desired class.
CascadeClassifier classifier = new CascadeClassifier ( classifierName );
if ( classifier == null ) {
System . err . println ( "Error loading classifier file " " + classifierName + " " ." );
System . exit ( 1 );
}
// The available FrameGrabber classes include OpenCVFrameGrabber (opencv_videoio),
// DC1394FrameGrabber, FlyCapture2FrameGrabber, OpenKinectFrameGrabber, OpenKinect2FrameGrabber,
// RealSenseFrameGrabber, RealSense2FrameGrabber, PS3EyeFrameGrabber, VideoInputFrameGrabber, and FFmpegFrameGrabber.
FrameGrabber grabber = FrameGrabber . createDefault ( 0 );
grabber . start ();
// CanvasFrame, FrameGrabber, and FrameRecorder use Frame objects to communicate image data.
// We need a FrameConverter to interface with other APIs (Android, Java 2D, JavaFX, Tesseract, OpenCV, etc).
OpenCVFrameConverter . ToMat converter = new OpenCVFrameConverter . ToMat ();
// FAQ about IplImage and Mat objects from OpenCV:
// - For custom raw processing of data, createBuffer() returns an NIO direct
// buffer wrapped around the memory pointed by imageData, and under Android we can
// also use that Buffer with Bitmap.copyPixelsFromBuffer() and copyPixelsToBuffer().
// - To get a BufferedImage from an IplImage, or vice versa, we can chain calls to
// Java2DFrameConverter and OpenCVFrameConverter, one after the other.
// - Java2DFrameConverter also has static copy() methods that we can use to transfer
// data more directly between BufferedImage and IplImage or Mat via Frame objects.
Mat grabbedImage = converter . convert ( grabber . grab ());
int height = grabbedImage . rows ();
int width = grabbedImage . cols ();
// Objects allocated with `new`, clone(), or a create*() factory method are automatically released
// by the garbage collector, but may still be explicitly released by calling deallocate().
// You shall NOT call cvReleaseImage(), cvReleaseMemStorage(), etc. on objects allocated this way.
Mat grayImage = new Mat ( height , width , CV_8UC1 );
Mat rotatedImage = grabbedImage . clone ();
// The OpenCVFrameRecorder class simply uses the VideoWriter of opencv_videoio,
// but FFmpegFrameRecorder also exists as a more versatile alternative.
FrameRecorder recorder = FrameRecorder . createDefault ( "output.avi" , width , height );
recorder . start ();
// CanvasFrame is a JFrame containing a Canvas component, which is hardware accelerated.
// It can also switch into full-screen mode when called with a screenNumber.
// We should also specify the relative monitor/camera response for proper gamma correction.
CanvasFrame frame = new CanvasFrame ( "Some Title" , CanvasFrame . getDefaultGamma ()/ grabber . getGamma ());
// Let's create some random 3D rotation...
Mat randomR = new Mat ( 3 , 3 , CV_64FC1 ),
randomAxis = new Mat ( 3 , 1 , CV_64FC1 );
// We can easily and efficiently access the elements of matrices and images
// through an Indexer object with the set of get() and put() methods.
DoubleIndexer Ridx = randomR . createIndexer (),
axisIdx = randomAxis . createIndexer ();
axisIdx . put ( 0 , ( Math . random () - 0.5 ) / 4 ,
( Math . random () - 0.5 ) / 4 ,
( Math . random () - 0.5 ) / 4 );
Rodrigues ( randomAxis , randomR );
double f = ( width + height ) / 2.0 ; Ridx . put ( 0 , 2 , Ridx . get ( 0 , 2 ) * f );
Ridx . put ( 1 , 2 , Ridx . get ( 1 , 2 ) * f );
Ridx . put ( 2 , 0 , Ridx . get ( 2 , 0 ) / f ); Ridx . put ( 2 , 1 , Ridx . get ( 2 , 1 ) / f );
System . out . println ( Ridx );
// We can allocate native arrays using constructors taking an integer as argument.
Point hatPoints = new Point ( 3 );
while ( frame . isVisible () && ( grabbedImage = converter . convert ( grabber . grab ())) != null ) {
// Let's try to detect some faces! but we need a grayscale image...
cvtColor ( grabbedImage , grayImage , CV_BGR2GRAY );
RectVector faces = new RectVector ();
classifier . detectMultiScale ( grayImage , faces );
long total = faces . size ();
for ( long i = 0 ; i < total ; i ++) {
Rect r = faces . get ( i );
int x = r . x (), y = r . y (), w = r . width (), h = r . height ();
rectangle ( grabbedImage , new Point ( x , y ), new Point ( x + w , y + h ), Scalar . RED , 1 , CV_AA , 0 );
// To access or pass as argument the elements of a native array, call position() before.
hatPoints . position ( 0 ). x ( x - w / 10 ). y ( y - h / 10 );
hatPoints . position ( 1 ). x ( x + w * 11 / 10 ). y ( y - h / 10 );
hatPoints . position ( 2 ). x ( x + w / 2 ). y ( y - h / 2 );
fillConvexPoly ( grabbedImage , hatPoints . position ( 0 ), 3 , Scalar . GREEN , CV_AA , 0 );
}
// Let's find some contours! but first some thresholding...
threshold ( grayImage , grayImage , 64 , 255 , CV_THRESH_BINARY );
// To check if an output argument is null we may call either isNull() or equals(null).
MatVector contours = new MatVector ();
findContours ( grayImage , contours , CV_RETR_LIST , CV_CHAIN_APPROX_SIMPLE );
long n = contours . size ();
for ( long i = 0 ; i < n ; i ++) {
Mat contour = contours . get ( i );
Mat points = new Mat ();
approxPolyDP ( contour , points , arcLength ( contour , true ) * 0.02 , true );
drawContours ( grabbedImage , new MatVector ( points ), - 1 , Scalar . BLUE );
}
warpPerspective ( grabbedImage , rotatedImage , randomR , rotatedImage . size ());
Frame rotatedFrame = converter . convert ( rotatedImage );
frame . showImage ( rotatedFrame );
recorder . record ( rotatedFrame );
}
frame . dispose ();
recorder . stop ();
grabber . stop ();
}
}
此外,创建一个包含以下内容的pom.xml
文件后:
< project >
< modelVersion >4.0.0</ modelVersion >
< groupId >org.bytedeco.javacv</ groupId >
< artifactId >demo</ artifactId >
< version >1.5.11</ version >
< properties >
< maven .compiler.source>1.7</ maven .compiler.source>
< maven .compiler.target>1.7</ maven .compiler.target>
</ properties >
< dependencies >
< dependency >
< groupId >org.bytedeco</ groupId >
< artifactId >javacv-platform</ artifactId >
< version >1.5.11</ version >
</ dependency >
<!-- Additional dependencies required to use CUDA and cuDNN -->
< dependency >
< groupId >org.bytedeco</ groupId >
< artifactId >opencv-platform-gpu</ artifactId >
< version >4.10.0-1.5.11</ version >
</ dependency >
<!-- Optional GPL builds with (almost) everything enabled -->
< dependency >
< groupId >org.bytedeco</ groupId >
< artifactId >ffmpeg-platform-gpl</ artifactId >
< version >7.1-1.5.11</ version >
</ dependency >
</ dependencies >
< build >
< sourceDirectory >.</ sourceDirectory >
</ build >
</ project >
通过将上面的源代码放在Demo.java
中,或者类似地放在samples
中找到的其他类中,我们可以使用以下命令首先自动安装所有内容,然后由 Maven 执行:
$ mvn compile exec:java -Dexec.mainClass=Demo
注意:如果出现错误,请确保pom.xml
文件中的artifactId
读取为javacv-platform
,而不仅仅是javacv
。工件javacv-platform
添加了所有必要的二进制依赖项。
如果上面提供的二进制文件不足以满足您的需求,您可能需要从源代码重建它们。为此,创建了项目文件:
安装后,只需调用 JavaCPP、其预设和 JavaCV 的常用mvn install
命令即可。默认情况下,除了 JavaCPP 的 C++ 编译器之外,不需要其他依赖项。请参阅pom.xml
文件内的注释以了解更多详细信息。
我们可以仅针对 JavaCV 运行mvn install
并依赖 CI 构建中的快照工件,而不是手动构建本机库:
项目负责人:Samuel Audet samuel.audet at
gmail.com
开发者网站:https://github.com/bytedeco/javacv
讨论组:http://groups.google.com/group/javacv