Merge pull request #301 from emchristiansen:javasample2.4
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 500 KiB |
After Width: | Height: | Size: 606 KiB |
After Width: | Height: | Size: 248 KiB |
After Width: | Height: | Size: 195 KiB |
After Width: | Height: | Size: 258 KiB |
@ -0,0 +1,523 @@ |
|||||||
|
|
||||||
|
.. _Java_Dev_Intro: |
||||||
|
|
||||||
|
|
||||||
|
Introduction to Java Development |
||||||
|
******************************** |
||||||
|
|
||||||
|
Last updated: 12 February, 2013. |
||||||
|
|
||||||
|
As of OpenCV 2.4.4, OpenCV supports desktop Java development using nearly the same interface as for |
||||||
|
Android development. This guide will help you to create your first Java (or Scala) application using OpenCV. |
||||||
|
We will use either `Eclipse <http://eclipse.org/>`_, `Apache Ant <http://ant.apache.org/>`_ or the |
||||||
|
`Simple Build Tool (SBT) <http://www.scala-sbt.org/>`_ to build the application. |
||||||
|
|
||||||
|
For further reading after this guide, look at the :ref:`Android_Dev_Intro` tutorials. |
||||||
|
|
||||||
|
What we'll do in this guide |
||||||
|
*************************** |
||||||
|
|
||||||
|
In this guide, we will: |
||||||
|
|
||||||
|
* Get OpenCV with desktop Java support |
||||||
|
|
||||||
|
* Create an ``Ant``, ``Eclipse`` or ``SBT`` project |
||||||
|
|
||||||
|
* Write a simple OpenCV application in Java or Scala |
||||||
|
|
||||||
|
The same process was used to create the samples in the :file:`samples/java` folder of the OpenCV repository, |
||||||
|
so consult those files if you get lost. |
||||||
|
|
||||||
|
Get OpenCV with desktop Java support |
||||||
|
************************************ |
||||||
|
|
||||||
|
Starting from version 2.4.4 OpenCV includes desktop Java bindings. |
||||||
|
The most simple way to get it is downloading the appropriate package of **version 2.4.4 or higher** from the |
||||||
|
`OpenCV SourceForge repository <http://sourceforge.net/projects/opencvlibrary/files/>`_. |
||||||
|
|
||||||
|
.. note:: Windows users can find the prebuilt files needed for Java development in the |
||||||
|
:file:`opencv/build/java/` folder inside the package. |
||||||
|
For other OSes it's required to build OpenCV from sources. |
||||||
|
|
||||||
|
Another option to get OpenCV sources is to clone `OpenCV git repository |
||||||
|
<https://github.com/Itseez/opencv/>`_. |
||||||
|
In order to build OpenCV with Java bindings you need :abbr:`JDK (Java Development Kit)` |
||||||
|
(we recommend `Oracle/Sun JDK 6 or 7 <http://www.oracle.com/technetwork/java/javase/downloads/>`_), |
||||||
|
`Apache Ant <http://ant.apache.org/>`_ and `Python` v2.6 or higher to be installed. |
||||||
|
|
||||||
|
Build OpenCV |
||||||
|
############ |
||||||
|
|
||||||
|
Let's build OpenCV: |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
git clone git://github.com/Itseez/opencv.git |
||||||
|
cd opencv |
||||||
|
git checkout 2.4 |
||||||
|
mkdir build |
||||||
|
cd build |
||||||
|
|
||||||
|
Generate a Makefile or a MS Visual Studio* solution, or whatever you use for |
||||||
|
building executables in your system: |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
cmake -DBUILD_SHARED_LIBS=OFF .. |
||||||
|
|
||||||
|
or |
||||||
|
|
||||||
|
.. code-block:: bat |
||||||
|
|
||||||
|
cmake -DBUILD_SHARED_LIBS=OFF -G "Visual Studio 10" .. |
||||||
|
|
||||||
|
.. note:: When OpenCV is built as a set of **static** libraries (``-DBUILD_SHARED_LIBS=OFF`` option) |
||||||
|
the Java bindings dynamic library is all-sufficient, |
||||||
|
i.e. doesn't depend on other OpenCV libs, but includes all the OpenCV code inside. |
||||||
|
|
||||||
|
Examine the output of CMake and ensure ``java`` is one of the modules "To be built". |
||||||
|
If not, it's likely you're missing a dependency. You should troubleshoot by looking |
||||||
|
through the CMake output for any Java-related tools that aren't found and installing them. |
||||||
|
|
||||||
|
.. image:: images/cmake_output.png |
||||||
|
:alt: CMake output |
||||||
|
:align: center |
||||||
|
|
||||||
|
Now start the build: |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
make -j8 |
||||||
|
|
||||||
|
or |
||||||
|
|
||||||
|
.. code-block:: bat |
||||||
|
|
||||||
|
msbuild /m OpenCV.sln /t:Build /p:Configuration=Release /v:m |
||||||
|
|
||||||
|
Besides all this will create a ``jar`` containing the Java interface (:file:`bin/opencv_2.4.4.jar`) |
||||||
|
and a native dynamic library containing Java bindings and all the OpenCV stuff |
||||||
|
(:file:`bin/Release/opencv_java244.dll` or :file:`bin/libopencv_java244.so` respectively). |
||||||
|
We'll use these files later. |
||||||
|
|
||||||
|
Create a simple Java sample and an Ant build file for it |
||||||
|
******************************************************** |
||||||
|
|
||||||
|
.. note:: |
||||||
|
The described sample is provided with OpenCV library in the :file:`opencv/samples/java/ant` folder. |
||||||
|
|
||||||
|
* Create a folder where you'll develop this sample application. |
||||||
|
|
||||||
|
* In this folder create an XML file with the following content using any text editor: |
||||||
|
|
||||||
|
.. code-block:: xml |
||||||
|
:linenos: |
||||||
|
|
||||||
|
<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 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> |
||||||
|
|
||||||
|
.. note:: |
||||||
|
This XML file can be reused for building other Java applications. |
||||||
|
It describes a common folder structure in the lines 3 - 12 and common targets |
||||||
|
for compiling and running the application. |
||||||
|
|
||||||
|
When reusing this XML don't forget to modify the project name in the line 1, |
||||||
|
that is also the name of the `main` class (line 14). |
||||||
|
The paths to OpenCV `jar` and `jni lib` are expected as parameters |
||||||
|
(``"${ocvJarDir}"`` in line 5 and ``"${ocvLibDir}"`` in line 37), but |
||||||
|
you can hardcode these paths for your convenience. |
||||||
|
See `Ant documentation <http://ant.apache.org/manual/>`_ for detailed description |
||||||
|
of its build file format. |
||||||
|
|
||||||
|
* Create an :file:`src` folder next to the :file:`build.xml` file and a :file:`SimpleSample.java` file in it. |
||||||
|
|
||||||
|
* Put the following Java code into the :file:`SimpleSample.java` file: |
||||||
|
.. code-block:: java |
||||||
|
|
||||||
|
import org.opencv.core.Mat; |
||||||
|
import org.opencv.core.CvType; |
||||||
|
import org.opencv.core.Scalar; |
||||||
|
|
||||||
|
class SimpleSample { |
||||||
|
|
||||||
|
static{ System.loadLibrary("opencv_java244"); } |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
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()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
* Run the following command in console in the folder containing :file:`build.xml`: |
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
ant -DocvJarDir=path/to/dir/containing/opencv-244.jar -DocvLibDir=path/to/dir/containing/opencv_java244/native/library |
||||||
|
|
||||||
|
For example: |
||||||
|
|
||||||
|
.. code-block:: bat |
||||||
|
|
||||||
|
ant -DocvJarDir=X:\opencv-2.4.4\bin -DocvLibDir=X:\opencv-2.4.4\bin\Release |
||||||
|
|
||||||
|
The command should initiate [re]building and running the sample. |
||||||
|
You should see on the screen something like this: |
||||||
|
|
||||||
|
.. image:: images/ant_output.png |
||||||
|
:alt: run app with Ant |
||||||
|
:align: center |
||||||
|
|
||||||
|
Create a simple Java project in Eclipse |
||||||
|
*************************************** |
||||||
|
|
||||||
|
Now let's look at the possiblity of using OpenCV in Java when developing in Eclipse IDE. |
||||||
|
|
||||||
|
* Create a new Eclipse workspace |
||||||
|
* Create a new Java project via :guilabel:`File --> New --> Java Project` |
||||||
|
|
||||||
|
.. image:: images/eclipse_new_java_prj.png |
||||||
|
:alt: Eclipse: new Java project |
||||||
|
:align: center |
||||||
|
|
||||||
|
Call it say "HelloCV". |
||||||
|
|
||||||
|
* Open :guilabel:`Java Build Path` tab on :guilabel:`Project Properties` dialog |
||||||
|
and configure additional library (OpenCV) reference (jar and native library location): |
||||||
|
|
||||||
|
.. image:: images/eclipse_user_lib.png |
||||||
|
:alt: Eclipse: external JAR |
||||||
|
:align: center |
||||||
|
|
||||||
|
` ` |
||||||
|
|
||||||
|
.. image:: images/eclipse_user_lib2.png |
||||||
|
:alt: Eclipse: external JAR |
||||||
|
:align: center |
||||||
|
|
||||||
|
` ` |
||||||
|
|
||||||
|
.. image:: images/eclipse_user_lib3.png |
||||||
|
:alt: Eclipse: external JAR |
||||||
|
:align: center |
||||||
|
|
||||||
|
` ` |
||||||
|
|
||||||
|
.. image:: images/eclipse_user_lib4.png |
||||||
|
:alt: Eclipse: external JAR |
||||||
|
:align: center |
||||||
|
|
||||||
|
` ` |
||||||
|
|
||||||
|
.. image:: images/eclipse_user_lib5.png |
||||||
|
:alt: Eclipse: external JAR |
||||||
|
:align: center |
||||||
|
|
||||||
|
` ` |
||||||
|
|
||||||
|
.. image:: images/eclipse_user_lib6.png |
||||||
|
:alt: Eclipse: external JAR |
||||||
|
:align: center |
||||||
|
|
||||||
|
` ` |
||||||
|
|
||||||
|
.. image:: images/eclipse_user_lib7.png |
||||||
|
:alt: Eclipse: external JAR |
||||||
|
:align: center |
||||||
|
|
||||||
|
` ` |
||||||
|
|
||||||
|
.. image:: images/eclipse_user_lib8.png |
||||||
|
:alt: Eclipse: external JAR |
||||||
|
:align: center |
||||||
|
|
||||||
|
` ` |
||||||
|
|
||||||
|
* Add a new Java class (say ``Main``) containing the application entry: |
||||||
|
|
||||||
|
.. image:: images/eclipse_main_class.png |
||||||
|
:alt: Eclipse: Main class |
||||||
|
:align: center |
||||||
|
|
||||||
|
* Put some simple OpenCV calls there, e.g.: |
||||||
|
.. code-block:: java |
||||||
|
|
||||||
|
import org.opencv.core.CvType; |
||||||
|
import org.opencv.core.Mat; |
||||||
|
|
||||||
|
public class Main { |
||||||
|
public static void main(String[] args) { |
||||||
|
System.loadLibrary("opencv_java244"); |
||||||
|
Mat m = Mat.eye(3, 3, CvType.CV_8UC1); |
||||||
|
System.out.println("m = " + m.dump()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
* Press :guilabel:`Run` button and find the identity matrix content in the Eclipse ``Console`` window. |
||||||
|
|
||||||
|
.. image:: images/eclipse_run.png |
||||||
|
:alt: Eclipse: run |
||||||
|
:align: center |
||||||
|
|
||||||
|
Create an SBT project and samples in Java and Scala |
||||||
|
*************************************************** |
||||||
|
|
||||||
|
Now we'll create a simple Java application using SBT. This serves as a brief introduction to |
||||||
|
those unfamiliar with this build tool. We're using SBT because it is particularly easy and powerful. |
||||||
|
|
||||||
|
First, download and install `SBT <http://www.scala-sbt.org/>`_ using the instructions on its `web site <http://www.scala-sbt.org/>`_. |
||||||
|
|
||||||
|
Next, navigate to a new directory where you'd like the application source to live (outside :file:`opencv` dir). |
||||||
|
Let's call it "JavaSample" and create a directory for it: |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
cd <somewhere outside opencv> |
||||||
|
mkdir JavaSample |
||||||
|
|
||||||
|
Now we will create the necessary folders and an SBT project: |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
cd JavaSample |
||||||
|
mkdir -p src/main/java # This is where SBT expects to find Java sources |
||||||
|
mkdir project # This is where the build definitions live |
||||||
|
|
||||||
|
Now open :file:`project/build.scala` in your favorite editor and paste the following. |
||||||
|
It defines your project: |
||||||
|
|
||||||
|
.. code-block:: 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) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Now edit :file:`project/plugins.sbt` and paste the following. |
||||||
|
This will enable auto-generation of an Eclipse project: |
||||||
|
|
||||||
|
.. code-block:: scala |
||||||
|
|
||||||
|
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0") |
||||||
|
|
||||||
|
Now run ``sbt`` from the :file:`JavaSample` root and from within SBT run ``eclipse`` to generate an eclipse project: |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
sbt # Starts the sbt console |
||||||
|
> eclipse # Running "eclipse" from within the sbt console |
||||||
|
|
||||||
|
You should see something like this: |
||||||
|
|
||||||
|
.. image:: images/sbt_eclipse.png |
||||||
|
:alt: SBT output |
||||||
|
:align: center |
||||||
|
|
||||||
|
You can now import the SBT project to Eclipse using :guilabel:`Import ... -> Existing projects into workspace`. |
||||||
|
Whether you actually do this is optional for the guide; |
||||||
|
we'll be using SBT to build the project, so if you choose to use Eclipse it will just serve as a text editor. |
||||||
|
|
||||||
|
To test that everything is working, create a simple "Hello OpenCV" application. |
||||||
|
Do this by creating a file :file:`src/main/java/HelloOpenCV.java` with the following contents: |
||||||
|
|
||||||
|
.. code-block:: java |
||||||
|
|
||||||
|
public class HelloOpenCV { |
||||||
|
public static void main(String[] args) { |
||||||
|
System.out.println("Hello, OpenCV"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Now execute ``run`` from the sbt console, or more concisely, run ``sbt run`` from the command line: |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
sbt run |
||||||
|
|
||||||
|
You should see something like this: |
||||||
|
|
||||||
|
.. image:: images/sbt_run.png |
||||||
|
:alt: SBT run |
||||||
|
:align: center |
||||||
|
|
||||||
|
Copy the OpenCV jar and write a simple application |
||||||
|
******************************************************** |
||||||
|
|
||||||
|
Now we'll create a simple face detection application using OpenCV. |
||||||
|
|
||||||
|
First, create a :file:`lib/` folder and copy the OpenCV jar into it. |
||||||
|
By default, SBT adds jars in the lib folder to the Java library search path. |
||||||
|
You can optionally rerun ``sbt eclipse`` to update your Eclipse project. |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
mkdir lib |
||||||
|
cp <opencv_dir>/build/bin/opencv_<version>.jar lib/ |
||||||
|
sbt eclipse |
||||||
|
|
||||||
|
Next, create the directory src/main/resources and download this Lena image into it: |
||||||
|
|
||||||
|
.. image:: images/lena.png |
||||||
|
:alt: Lena |
||||||
|
:align: center |
||||||
|
|
||||||
|
Make sure it's called :file:`"lena.png"`. |
||||||
|
Items in the resources directory are available to the Java application at runtime. |
||||||
|
|
||||||
|
Next, copy :file:`lbpcascade_frontalface.xml` from :file:`opencv/data/` into the :file:`resources` |
||||||
|
directory: |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
cp <opencv_dir>/data/lbpcascades/lbpcascade_frontalface.xml src/main/resources/ |
||||||
|
|
||||||
|
Now modify src/main/java/HelloOpenCV.java so it contains the following Java code: |
||||||
|
|
||||||
|
.. code-block:: 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.highgui.Highgui; |
||||||
|
import org.opencv.objdetect.CascadeClassifier; |
||||||
|
|
||||||
|
// |
||||||
|
// Detects faces in an image, draws boxes around them, and writes the results |
||||||
|
// to "faceDetection.png". |
||||||
|
// |
||||||
|
class DetectFaceDemo { |
||||||
|
public void run() { |
||||||
|
System.out.println("\nRunning DetectFaceDemo"); |
||||||
|
|
||||||
|
// Create a face detector from the cascade file in the resources |
||||||
|
// directory. |
||||||
|
CascadeClassifier faceDetector = new CascadeClassifier(getClass().getResource("/lbpcascade_frontalface.xml").getPath()); |
||||||
|
Mat image = Highgui.imread(getClass().getResource("/lena.png").getPath()); |
||||||
|
|
||||||
|
// Detect faces in the image. |
||||||
|
// MatOfRect is a special container class for Rect. |
||||||
|
MatOfRect faceDetections = new MatOfRect(); |
||||||
|
faceDetector.detectMultiScale(image, faceDetections); |
||||||
|
|
||||||
|
System.out.println(String.format("Detected %s faces", faceDetections.toArray().length)); |
||||||
|
|
||||||
|
// Draw a bounding box around each face. |
||||||
|
for (Rect rect : faceDetections.toArray()) { |
||||||
|
Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0)); |
||||||
|
} |
||||||
|
|
||||||
|
// Save the visualized detection. |
||||||
|
String filename = "faceDetection.png"; |
||||||
|
System.out.println(String.format("Writing %s", filename)); |
||||||
|
Highgui.imwrite(filename, image); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class HelloOpenCV { |
||||||
|
public static void main(String[] args) { |
||||||
|
System.out.println("Hello, OpenCV"); |
||||||
|
|
||||||
|
// Load the native library. |
||||||
|
System.loadLibrary("opencv_java244"); |
||||||
|
new DetectFaceDemo().run(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Note the call to ``System.loadLibrary("opencv_java244")``. |
||||||
|
This command must be executed exactly once per Java process prior to using any native OpenCV methods. |
||||||
|
If you don't call it, you will get ``UnsatisfiedLink errors``. |
||||||
|
You will also get errors if you try to load OpenCV when it has already been loaded. |
||||||
|
|
||||||
|
Now run the face detection app using ``sbt run``: |
||||||
|
|
||||||
|
.. code-block:: bash |
||||||
|
|
||||||
|
sbt run |
||||||
|
|
||||||
|
You should see something like this: |
||||||
|
|
||||||
|
.. image:: images/sbt_run_face.png |
||||||
|
:alt: SBT run |
||||||
|
:align: center |
||||||
|
|
||||||
|
It should also write the following image to :file:`faceDetection.png`: |
||||||
|
|
||||||
|
.. image:: images/faceDetection.png |
||||||
|
:alt: Detected face |
||||||
|
:align: center |
||||||
|
|
||||||
|
You're done! |
||||||
|
Now you have a sample Java application working with OpenCV, so you can start the work on your own. |
||||||
|
We wish you good luck and many years of joyful life! |
After Width: | Height: | Size: 41 KiB |
@ -0,0 +1,49 @@ |
|||||||
|
<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 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> |
@ -0,0 +1,19 @@ |
|||||||
|
import org.opencv.core.Mat; |
||||||
|
import org.opencv.core.CvType; |
||||||
|
import org.opencv.core.Scalar; |
||||||
|
|
||||||
|
class SimpleSample { |
||||||
|
|
||||||
|
static{ System.loadLibrary("opencv_java244"); } |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
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()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<classpath> |
||||||
|
<classpathentry kind="src" path="src"/> |
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/> |
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/opencv-2.4.4"/> |
||||||
|
<classpathentry kind="output" path="bin"/> |
||||||
|
</classpath> |
@ -0,0 +1,17 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<projectDescription> |
||||||
|
<name>HelloCV</name> |
||||||
|
<comment></comment> |
||||||
|
<projects> |
||||||
|
</projects> |
||||||
|
<buildSpec> |
||||||
|
<buildCommand> |
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name> |
||||||
|
<arguments> |
||||||
|
</arguments> |
||||||
|
</buildCommand> |
||||||
|
</buildSpec> |
||||||
|
<natures> |
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature> |
||||||
|
</natures> |
||||||
|
</projectDescription> |
@ -0,0 +1,11 @@ |
|||||||
|
eclipse.preferences.version=1 |
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled |
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 |
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve |
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.7 |
||||||
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate |
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate |
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate |
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error |
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error |
||||||
|
org.eclipse.jdt.core.compiler.source=1.7 |
@ -0,0 +1,12 @@ |
|||||||
|
import org.opencv.core.CvType; |
||||||
|
import org.opencv.core.Mat; |
||||||
|
|
||||||
|
public class Main { |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
System.loadLibrary("opencv_java244"); |
||||||
|
Mat m = Mat.eye(3, 3, CvType.CV_8UC1); |
||||||
|
System.out.println("m = " + m.dump()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
A demo of the Java wrapper for OpenCV with two examples: |
||||||
|
1) feature detection and matching and |
||||||
|
2) face detection. |
||||||
|
The examples are coded in Scala and Java. |
||||||
|
Anyone familiar with Java should be able to read the Scala examples. |
||||||
|
Please feel free to contribute code examples in Scala or Java, or any JVM language. |
||||||
|
|
||||||
|
To run the examples: |
||||||
|
1) Install OpenCV and copy the OpenCV jar to lib/. |
||||||
|
This jar must match the native libraries installed in your system. |
||||||
|
If this isn't the case, you may get a java.lang.UnsatisfiedLinkError at runtime. |
||||||
|
2) Go to the root directory and type "sbt/sbt run". |
||||||
|
This should generate images in your current directory. |
@ -0,0 +1,22 @@ |
|||||||
|
import sbt._ |
||||||
|
import Keys._ |
||||||
|
|
||||||
|
object OpenCVJavaDemoBuild 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 := "OpenCVJavaDemo") |
||||||
|
Project(id = "OpenCVJavaDemo", base = file("."), settings = settings) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0") |
@ -0,0 +1 @@ |
|||||||
|
java -Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=384M -jar `dirname $0`/sbt-launch.jar "$@" |
@ -0,0 +1,44 @@ |
|||||||
|
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.highgui.Highgui; |
||||||
|
import org.opencv.objdetect.CascadeClassifier; |
||||||
|
|
||||||
|
/* |
||||||
|
* Detects faces in an image, draws boxes around them, and writes the results |
||||||
|
* to "faceDetection.png". |
||||||
|
*/ |
||||||
|
public class DetectFaceDemo { |
||||||
|
public void run() { |
||||||
|
System.out.println("\nRunning DetectFaceDemo"); |
||||||
|
|
||||||
|
// Create a face detector from the cascade file in the resources
|
||||||
|
// directory.
|
||||||
|
CascadeClassifier faceDetector = new CascadeClassifier(getClass() |
||||||
|
.getResource("/lbpcascade_frontalface.xml").getPath()); |
||||||
|
Mat image = Highgui.imread(getClass().getResource( |
||||||
|
"/AverageMaleFace.jpg").getPath()); |
||||||
|
|
||||||
|
// Detect faces in the image.
|
||||||
|
// MatOfRect is a special container class for Rect.
|
||||||
|
MatOfRect faceDetections = new MatOfRect(); |
||||||
|
faceDetector.detectMultiScale(image, faceDetections); |
||||||
|
|
||||||
|
System.out.println(String.format("Detected %s faces", |
||||||
|
faceDetections.toArray().length)); |
||||||
|
|
||||||
|
// Draw a bounding box around each face.
|
||||||
|
for (Rect rect : faceDetections.toArray()) { |
||||||
|
Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x |
||||||
|
+ rect.width, rect.y + rect.height), new Scalar(0, 255, 0)); |
||||||
|
} |
||||||
|
|
||||||
|
// Save the visualized detection.
|
||||||
|
String filename = "faceDetection.png"; |
||||||
|
System.out.println(String.format("Writing %s", filename)); |
||||||
|
Highgui.imwrite(filename, image); |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 272 KiB |
After Width: | Height: | Size: 278 KiB |
@ -0,0 +1,20 @@ |
|||||||
|
/* |
||||||
|
* The main runner for the Java demos. |
||||||
|
* Demos whose name begins with "Scala" are written in the Scala language, |
||||||
|
* demonstrating the generic nature of the interface. |
||||||
|
* The other demos are in Java. |
||||||
|
* Currently, all demos are run, sequentially. |
||||||
|
* |
||||||
|
* You're invited to submit your own examples, in any JVM language of |
||||||
|
* your choosing so long as you can get them to build. |
||||||
|
*/ |
||||||
|
object Main extends App { |
||||||
|
// We must load the native library before using any OpenCV functions. |
||||||
|
// You must load this library _exactly once_ per Java invocation. |
||||||
|
// If you load it more than once, you will get a java.lang.UnsatisfiedLinkError. |
||||||
|
System.loadLibrary("opencv_java") |
||||||
|
|
||||||
|
ScalaCorrespondenceMatchingDemo.run() |
||||||
|
ScalaDetectFaceDemo.run() |
||||||
|
new DetectFaceDemo().run() |
||||||
|
} |
@ -0,0 +1,69 @@ |
|||||||
|
import org.opencv.highgui.Highgui |
||||||
|
import org.opencv.features2d.DescriptorExtractor |
||||||
|
import org.opencv.features2d.Features2d |
||||||
|
import org.opencv.core.MatOfKeyPoint |
||||||
|
import org.opencv.core.Mat |
||||||
|
import org.opencv.features2d.FeatureDetector |
||||||
|
import org.opencv.features2d.DescriptorMatcher |
||||||
|
import org.opencv.core.MatOfDMatch |
||||||
|
import reflect._ |
||||||
|
|
||||||
|
/* |
||||||
|
* Finds corresponding points between a pair of images using local descriptors. |
||||||
|
* The correspondences are visualized in the image "scalaCorrespondences.png", |
||||||
|
* which is written to disk. |
||||||
|
*/ |
||||||
|
object ScalaCorrespondenceMatchingDemo { |
||||||
|
def run() { |
||||||
|
println(s"\nRunning ${classTag[this.type].toString.replace("$", "")}") |
||||||
|
|
||||||
|
// Detects keypoints and extracts descriptors in a given image of type Mat. |
||||||
|
def detectAndExtract(mat: Mat) = { |
||||||
|
// A special container class for KeyPoint. |
||||||
|
val keyPoints = new MatOfKeyPoint |
||||||
|
// We're using the SURF detector. |
||||||
|
val detector = FeatureDetector.create(FeatureDetector.SURF) |
||||||
|
detector.detect(mat, keyPoints) |
||||||
|
|
||||||
|
println(s"There were ${keyPoints.toArray.size} KeyPoints detected") |
||||||
|
|
||||||
|
// Let's just use the best KeyPoints. |
||||||
|
val sorted = keyPoints.toArray.sortBy(_.response).reverse.take(50) |
||||||
|
// There isn't a constructor that takes Array[KeyPoint], so we unpack |
||||||
|
// the array and use the constructor that can take any number of |
||||||
|
// arguments. |
||||||
|
val bestKeyPoints: MatOfKeyPoint = new MatOfKeyPoint(sorted: _*) |
||||||
|
|
||||||
|
// We're using the SURF descriptor. |
||||||
|
val extractor = DescriptorExtractor.create(DescriptorExtractor.SURF) |
||||||
|
val descriptors = new Mat |
||||||
|
extractor.compute(mat, bestKeyPoints, descriptors) |
||||||
|
|
||||||
|
println(s"${descriptors.rows} descriptors were extracted, each with dimension ${descriptors.cols}") |
||||||
|
|
||||||
|
(bestKeyPoints, descriptors) |
||||||
|
} |
||||||
|
|
||||||
|
// Load the images from the |resources| directory. |
||||||
|
val leftImage = Highgui.imread(getClass.getResource("/img1.png").getPath) |
||||||
|
val rightImage = Highgui.imread(getClass.getResource("/img2.png").getPath) |
||||||
|
|
||||||
|
// Detect KeyPoints and extract descriptors. |
||||||
|
val (leftKeyPoints, leftDescriptors) = detectAndExtract(leftImage) |
||||||
|
val (rightKeyPoints, rightDescriptors) = detectAndExtract(rightImage) |
||||||
|
|
||||||
|
// Match the descriptors. |
||||||
|
val matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE) |
||||||
|
// A special container class for DMatch. |
||||||
|
val dmatches = new MatOfDMatch |
||||||
|
// The backticks are because "match" is a keyword in Scala. |
||||||
|
matcher.`match`(leftDescriptors, rightDescriptors, dmatches) |
||||||
|
|
||||||
|
// Visualize the matches and save the visualization. |
||||||
|
val correspondenceImage = new Mat |
||||||
|
Features2d.drawMatches(leftImage, leftKeyPoints, rightImage, rightKeyPoints, dmatches, correspondenceImage) |
||||||
|
val filename = "scalaCorrespondences.png" |
||||||
|
println(s"Writing ${filename}") |
||||||
|
assert(Highgui.imwrite(filename, correspondenceImage)) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
import org.opencv.core.Core |
||||||
|
import org.opencv.core.MatOfRect |
||||||
|
import org.opencv.core.Point |
||||||
|
import org.opencv.core.Scalar |
||||||
|
import org.opencv.highgui.Highgui |
||||||
|
import org.opencv.objdetect.CascadeClassifier |
||||||
|
import reflect._ |
||||||
|
|
||||||
|
/* |
||||||
|
* Detects faces in an image, draws boxes around them, and writes the results |
||||||
|
* to "scalaFaceDetection.png". |
||||||
|
*/ |
||||||
|
object ScalaDetectFaceDemo { |
||||||
|
def run() { |
||||||
|
println(s"\nRunning ${classTag[this.type].toString.replace("$", "")}") |
||||||
|
|
||||||
|
// Create a face detector from the cascade file in the resources directory. |
||||||
|
val faceDetector = new CascadeClassifier(getClass.getResource("/lbpcascade_frontalface.xml").getPath) |
||||||
|
val image = Highgui.imread(getClass.getResource("/AverageMaleFace.jpg").getPath) |
||||||
|
|
||||||
|
// Detect faces in the image. |
||||||
|
// MatOfRect is a special container class for Rect. |
||||||
|
val faceDetections = new MatOfRect |
||||||
|
faceDetector.detectMultiScale(image, faceDetections) |
||||||
|
|
||||||
|
println(s"Detected ${faceDetections.toArray.size} faces") |
||||||
|
|
||||||
|
// Draw a bounding box around each face. |
||||||
|
for (rect <- faceDetections.toArray) { |
||||||
|
Core.rectangle( |
||||||
|
image, |
||||||
|
new Point(rect.x, rect.y), |
||||||
|
new Point(rect.x + rect.width, |
||||||
|
rect.y + rect.height), |
||||||
|
new Scalar(0, 255, 0)) |
||||||
|
} |
||||||
|
|
||||||
|
// Save the visualized detection. |
||||||
|
val filename = "scalaFaceDetection.png" |
||||||
|
println(s"Writing ${filename}") |
||||||
|
assert(Highgui.imwrite(filename, image)) |
||||||
|
} |
||||||
|
} |