上一個教程: 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 示例應用程式,因此您可以開始自己的工作了。祝您好運,生活愉快!