上一个教程: Image Watch:在 Visual Studio 调试器中查看内存中的图像
下一个教程: 在 Eclipse 中使用 OpenCV Java
| |
| 原始作者 | Eric Christiansen 和 Andrey Pavlenko |
| 兼容性 | OpenCV >= 3.0 |
- 警告
- 本教程可能包含过时的信息。
从 OpenCV 2.4.4 版本开始,OpenCV 支持桌面 Java 开发,其接口与 Android 开发的接口几乎相同。本指南将帮助您使用 OpenCV 创建您的第一个 Java(或 Scala)应用程序。我们将使用 Apache Ant 或 Simple Build Tool (SBT) 来构建应用程序。
如果您想使用 Eclipse,请参阅在 Eclipse 中使用 OpenCV Java。阅读本指南后,如需进一步阅读,请参阅Android 开发入门教程。
本指南内容概览
在本指南中,我们将
- 获取支持桌面 Java 的 OpenCV
- 创建一个 Ant 或 SBT 项目
- 用 Java 或 Scala 编写一个简单的 OpenCV 应用程序
OpenCV 仓库的 samples/java 文件夹中的示例也是使用相同过程创建的,因此如果您遇到困难,可以查阅这些文件。
获取合适的 OpenCV
从 2.4.4 版本开始,OpenCV 包含了桌面 Java 绑定。
下载
最简单的方法是从 OpenCV SourceForge 仓库下载2.4.4 或更高版本的相应软件包。
- 注意
- Windows 用户可以在软件包内的
opencv/build/java/ 文件夹中找到 Java 开发所需的预构建文件。对于其他操作系统,需要从源代码构建 OpenCV。
获取 OpenCV 源代码的另一种选择是克隆 OpenCV Git 仓库。为了构建带有 Java 绑定的 OpenCV,您需要安装 JDK (Java Development Kit)(我们推荐 Oracle/Sun JDK 6 或 7)、Apache Ant 和 Python v2.6 或更高版本。
构建
让我们构建 OpenCV
git clone git://github.com/opencv/opencv.git
cd opencv
git checkout 2.4
mkdir build
cd build
生成 Makefile 或 MS Visual Studio* 解决方案,或您系统中用于构建可执行文件的任何内容
cmake -DBUILD_SHARED_LIBS=OFF ..
或者
cmake -DBUILD_SHARED_LIBS=OFF -G "Visual Studio 10" ..
- 注意
- 当 OpenCV 作为一组静态库构建时(-DBUILD_SHARED_LIBS=OFF 选项),Java 绑定动态库是完全自给自足的,即它不依赖于其他 OpenCV 库,但内部包含了所有 OpenCV 代码。
检查 CMake 的输出,确保 java 是“待构建”模块之一。如果不是,您很可能缺少一个依赖项。您应该通过查看 CMake 输出中任何未找到的 Java 相关工具并安装它们来解决问题。
- 注意
- 如果 CMake 无法在您的系统中找到 Java,请在运行它之前设置 JAVA_HOME 环境变量,使其指向已安装的 JDK 路径。例如:
export JAVA_HOME=/usr/lib/jvm/java-6-oracle
cmake -DBUILD_SHARED_LIBS=OFF ..
现在开始构建
或者
msbuild /m OpenCV.sln /t:Build /p:Configuration=Release /v:m
此外,所有这些操作还将创建一个包含 Java 接口的 jar 文件(bin/opencv-244.jar)以及一个包含 Java 绑定和所有 OpenCV 内容的本地动态库(分别是 lib/libopencv_java244.so 或 bin/Release/opencv_java244.dll)。我们稍后将使用这些文件。
使用 Ant 的 Java 示例
- 注意
- 所述示例随 OpenCV 库提供,位于
opencv/samples/java/ant 文件夹中。
- 创建一个文件夹,用于开发此示例应用程序。
- 在该文件夹中,使用任何文本编辑器创建包含以下内容的
build.xml 文件<project name="SimpleSample" basedir="." default="rebuild-run">
<property name="src.dir" value="src"/>
<property name="lib.dir" value="${ocvJarDir}"/>
<path id="classpath">
<fileset dir="${lib.dir}" includes="**/*.jar"/>
</path>
<property name="build.dir" value="build"/>
<property name="classes.dir" value="${build.dir}/classes"/>
<property name="jar.dir" value="${build.dir}/jar"/>
<property name="main-class" value="${ant.project.name}"/>
<target name="clean">
<delete dir="${build.dir}"/>
</target>
<target name="compile">
<mkdir dir="${classes.dir}"/>
<javac includeantruntime="false" srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
</target>
<target name="jar" depends="compile">
<mkdir dir="${jar.dir}"/>
<jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
</manifest>
</jar>
</target>
<target name="run" depends="jar">
<java fork="true" classname="${main-class}">
<sysproperty key="java.library.path" path="${ocvLibDir}"/>
<classpath>
<path refid="classpath"/>
<path location="${jar.dir}/${ant.project.name}.jar"/>
</classpath>
</java>
</target>
<target name="rebuild" depends="clean,jar"/>
<target name="rebuild-run" depends="clean,run"/>
</project>
- 注意
- 此 XML 文件可用于构建其他 Java 应用程序。它描述了第 3 - 12 行中的通用文件夹结构以及用于编译和运行应用程序的通用目标。重用此 XML 文件时,请不要忘记修改第 1 行中的项目名称,该名称也是主类的名称(第 14 行)。OpenCV jar 和 jni 库的路径预期为参数(第 5 行中的“${ocvJarDir}”和第 37 行中的“${ocvLibDir}”),但为了方便起见,您可以硬编码这些路径。有关其构建文件格式的详细说明,请参阅 Ant 文档。
- 在
build.xml 文件旁边创建一个 src 文件夹,并在其中创建一个 SimpleSample.java 文件。
- 将以下 Java 代码放入
SimpleSample.java 文件中import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.core.Scalar;
class SimpleSample {
static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }
public static void main(String[] args) {
System.out.println("Welcome to OpenCV " + Core.VERSION);
Mat m = new Mat(5, 10, CvType.CV_8UC1, new Scalar(0));
System.out.println("OpenCV Mat: " + m);
Mat mr1 = m.row(1);
mr1.setTo(new Scalar(1));
Mat mc5 = m.col(5);
mc5.setTo(new Scalar(5));
System.out.println("OpenCV Mat data:\n" + m.dump());
}
}
int main(int argc, char *argv[])
定义 highgui_qt.cpp:3
- 在包含
build.xml 的文件夹中,在控制台中运行以下命令ant -DocvJarDir=path/to/dir/containing/opencv-244.jar -DocvLibDir=path/to/dir/containing/opencv_java244/native/library
例如ant -DocvJarDir=X:\opencv-2.4.4\bin -DocvLibDir=X:\opencv-2.4.4\bin\Release
该命令应启动示例的 [重新]构建和运行。您应该在屏幕上看到类似以下内容:
用于 Java 和 Scala 的 SBT 项目
现在我们将使用 SBT 创建一个简单的 Java 应用程序。这为不熟悉此构建工具的人提供了一个简要的介绍。我们使用 SBT 是因为它特别简单且功能强大。
首先,根据 SBT 网站上的说明下载并安装 SBT。
接下来,导航到一个新目录,您希望应用程序源代码位于该目录中(在 opencv 目录之外)。我们称之为“JavaSample”并为其创建一个目录
cd <somewhere outside opencv>
mkdir JavaSample
现在我们将创建必要的文件夹和一个 SBT 项目
cd JavaSample
mkdir -p src/main/java # 这是 SBT 期望找到 Java 源代码的位置
mkdir project # 这是构建定义所在的位置
现在在您喜欢的编辑器中打开 project/build.scala 并粘贴以下内容。它定义了您的项目
import sbt._
import Keys._
object JavaSampleBuild extends Build {
def scalaSettings = Seq(
scalaVersion := "2.10.0",
scalacOptions ++= Seq(
"-optimize",
"-unchecked",
"-deprecation"
)
)
def buildSettings =
Project.defaultSettings ++
scalaSettings
lazy val root = {
val settings = buildSettings ++ Seq(name := "JavaSample")
Project(id = "JavaSample", base = file("."), settings = settings)
}
}
现在编辑 project/plugins.sbt 并粘贴以下内容。这将启用 Eclipse 项目的自动生成
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")
现在从 JavaSample 根目录运行 sbt,并在 SBT 内部运行 eclipse 以生成 Eclipse 项目
sbt # 启动 sbt 控制台
eclipse # 从 sbt 控制台内部运行“eclipse”
您应该看到类似以下内容:
您现在可以使用“导入... -> 将现有项目导入工作区”将 SBT 项目导入 Eclipse。您是否实际执行此操作对于本指南来说是可选的;我们将使用 SBT 构建项目,因此如果您选择使用 Eclipse,它将仅充当文本编辑器。
为了测试一切是否正常工作,创建一个简单的“Hello OpenCV”应用程序。通过创建文件 src/main/java/HelloOpenCV.java 并包含以下内容来完成此操作
public class HelloOpenCV {
public static void main(String[] args) {
System.out.println("Hello, OpenCV");
}
}
现在从 sbt 控制台执行 run,或者更简洁地,从命令行运行 sbt run
您应该看到类似以下内容:
运行 SBT 示例
现在我们将使用 OpenCV 创建一个简单的面部识别应用程序。
首先,创建一个 lib/ 文件夹并将 OpenCV jar 复制到其中。默认情况下,SBT 将 lib 文件夹中的 jar 添加到 Java 库搜索路径中。您可以选择重新运行 sbt eclipse 来更新您的 Eclipse 项目。
mkdir lib
cp <opencv_dir>/build/bin/opencv_<version>.jar lib/
sbt eclipse
接下来,创建目录 src/main/resources 并将此 Lena 图像下载到其中
确保它名为 "lena.png"。资源目录中的项目在运行时可供 Java 应用程序使用。
接下来,将 lbpcascade_frontalface.xml 从 opencv/data/lbpcascades/ 复制到 resources 目录中
cp <opencv_dir>/data/lbpcascades/lbpcascade_frontalface.xml src/main/resources/
现在修改 src/main/java/HelloOpenCV.java,使其包含以下 Java 代码
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.objdetect.CascadeClassifier;
class DetectFaceDemo {
public void run() {
System.out.println("\nRunning DetectFaceDemo");
CascadeClassifier faceDetector = new CascadeClassifier(getClass().getResource("/lbpcascade_frontalface.xml").getPath());
Mat image = Imgcodecs.imread(getClass().getResource("/lena.png").getPath());
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(image, faceDetections);
System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));
for (Rect rect : faceDetections.toArray()) {
Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
}
String filename = "faceDetection.png";
System.out.println(String.format("Writing %s", filename));
Imgcodecs.imwrite(filename, image);
}
}
public class HelloOpenCV {
public static void main(String[] args) {
System.out.println("Hello, OpenCV");
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
new DetectFaceDemo().run();
}
}
请注意对 System.loadLibrary(Core.NATIVE_LIBRARY_NAME) 的调用。在使用任何本地 OpenCV 方法之前,此命令必须在每个 Java 进程中精确执行一次。如果您不调用它,将会遇到 UnsatisfiedLink 错误。如果您尝试加载已加载的 OpenCV,也会出现错误。
现在使用 `sbt run` 运行人脸识别应用程序
您应该看到类似以下内容:
它还应该将以下图像写入 faceDetection.png
您已完成!现在您有了一个使用 OpenCV 的 Java 示例应用程序,因此您可以开始自己的工作了。祝您好运,生活愉快!