Merge pull request #1975 from magomimmo:clj-tut
This commit is contained in:
commit
ee270d1a18
@ -11,4 +11,5 @@
|
||||
.. |Author_EricCh| unicode:: Eric U+0020 Christiansen
|
||||
.. |Author_AndreyP| unicode:: Andrey U+0020 Pavlenko
|
||||
.. |Author_AlexS| unicode:: Alexander U+0020 Smorkalov
|
||||
.. |Author_BarisD| unicode:: Bar U+0131 U+015F U+0020 Evrim U+0020 Demir U+00F6 z
|
||||
.. |Author_MimmoC| unicode:: Mimmo U+0020 Cosenza
|
||||
.. |Author_BarisD| unicode:: Bar U+0131 U+015F U+0020 Evrim U+0020 Demir U+00F6 z
|
||||
|
@ -0,0 +1,728 @@
|
||||
.. _clojure_dev_intro:
|
||||
|
||||
Introduction to OpenCV Development with Clojure
|
||||
***********************************************
|
||||
|
||||
As of OpenCV 2.4.4, OpenCV supports desktop Java development using
|
||||
nearly the same interface as for Android development.
|
||||
|
||||
`Clojure <http://clojure.org/>`_ is a contemporary LISP dialect hosted
|
||||
by the Java Virtual Machine and it offers a complete interoperability
|
||||
with the underlying JVM. This means that we should even be able to use
|
||||
the Clojure REPL (Read Eval Print Loop) as and interactive programmable
|
||||
interface to the underlying OpenCV engine.
|
||||
|
||||
What we'll do in this tutorial
|
||||
==============================
|
||||
|
||||
This tutorial will help you in setting up a basic Clojure environment
|
||||
for interactively learning OpenCV within the fully programmable
|
||||
CLojure REPL.
|
||||
|
||||
Tutorial source code
|
||||
--------------------
|
||||
|
||||
You can find a runnable source code of the sample in the
|
||||
:file:`samples/java/clojure/simple-sample` folder of the OpenCV
|
||||
repository. After having installed OpenCV and Clojure as explained in
|
||||
the tutorial, issue the following command to run the sample from the
|
||||
command line.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
cd path/to/samples/java/clojure/simple-sample
|
||||
lein run
|
||||
|
||||
Preamble
|
||||
========
|
||||
|
||||
For detailed instruction on installing OpenCV with desktop Java support
|
||||
refer to the `corresponding tutorial <http://docs.opencv.org/2.4.4-beta/doc/tutorials/introduction/desktop_java/java_dev_intro.html>`_.
|
||||
|
||||
If you are in hurry, here is a minimum quick start guide to install
|
||||
OpenCV on Mac OS X:
|
||||
|
||||
NOTE 1: I'm assuming you already installed
|
||||
`xcode <https://developer.apple.com/xcode/>`_,
|
||||
`jdk <http://www.oracle.com/technetwork/java/javase/downloads/index.html>`_
|
||||
and `Cmake <http://www.cmake.org/cmake/resources/software.html>`_.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
cd ~/
|
||||
mkdir opt
|
||||
git clone https://github.com/Itseez/opencv.git
|
||||
cd opencv
|
||||
git checkout 2.4
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DBUILD_SHARED_LIBS=OFF ..
|
||||
...
|
||||
...
|
||||
make -j8
|
||||
# optional
|
||||
# make install
|
||||
|
||||
Install Leiningen
|
||||
=================
|
||||
|
||||
Once you installed OpenCV with desktop java support the only other
|
||||
requirement is to install
|
||||
`Leiningeng <https://github.com/technomancy/leiningen>`_ which allows
|
||||
you to manage the entire life cycle of your CLJ projects.
|
||||
|
||||
The available `installation guide <https://github.com/technomancy/leiningen#installation>`_ is very easy to be followed:
|
||||
|
||||
1. `Download the script <https://raw.github.com/technomancy/leiningen/stable/bin/lein>`_
|
||||
2. Place it on your ``$PATH`` (cf. ``~/bin`` is a good choice if it is
|
||||
on your ``path``.)
|
||||
3. Set the script to be executable. (i.e. ``chmod 755 ~/bin/lein``).
|
||||
|
||||
If you work on Windows, follow `this instruction <https://github.com/technomancy/leiningen#windows>`_
|
||||
|
||||
You now have both the OpenCV library and a fully installed basic Clojure
|
||||
environment. What is now needed is to configure the Clojure environment
|
||||
to interact with the OpenCV library.
|
||||
|
||||
Install the localrepo Leiningen plugin
|
||||
=======================================
|
||||
|
||||
The set of commands (tasks in Leiningen parlance) natively supported by
|
||||
Leiningen can be very easily extended by various plugins. One of them is
|
||||
the `lein-localrepo <https://github.com/kumarshantanu/lein-localrepo>`_
|
||||
plugin which allows to install any jar lib as an artifact in the local
|
||||
maven repository of your machine (typically in the ``~/.m2/repository``
|
||||
directory of your username).
|
||||
|
||||
We're going to use this ``lein`` plugin to add to the local maven
|
||||
repository the opencv components needed by Java and Clojure to use the
|
||||
opencv lib.
|
||||
|
||||
Generally speaking, if you want to use a plugin on project base only, it
|
||||
can be added directly to a CLJ project created by ``lein``.
|
||||
|
||||
Instead, when you want a plugin to be available to any CLJ project in
|
||||
your username space, you can add it to the ``profiles.clj`` in the
|
||||
``~/.lein/`` directory.
|
||||
|
||||
The ``lein-localrepo`` plugin will be useful to me in other CLJ
|
||||
projects where I need to call native libs wrapped by a Java interface.
|
||||
So I decide to make it available to any CLJ project:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
mkdir ~/.lein
|
||||
|
||||
Create a file named ``profiles.clj`` in the ``~/.lein`` directory and
|
||||
copy into it the following content:
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
{:user {:plugins [[lein-localrepo "0.5.2"]]}}
|
||||
|
||||
Here we're saying that the version release ``"0.5.2"`` of the
|
||||
``lein-localrepo`` plugin will be available to the ``:user`` profile for
|
||||
any CLJ project created by ``lein``.
|
||||
|
||||
You do not need to do anything else to install the plugin because it
|
||||
will be automatically downloaded from a remote repository the very first
|
||||
time you issue any ``lein`` task.
|
||||
|
||||
Install the java specific libs as local repository
|
||||
==================================================
|
||||
|
||||
If you followed the standard documentation for installing OpenCV on your
|
||||
computer, you should find the following two libs under the directory
|
||||
where you built OpenCV:
|
||||
|
||||
- the ``build/bin/opencv-247.jar`` java lib
|
||||
- the ``build/lib/libopencv_java247.dylib`` native lib (or ``.so`` in
|
||||
you built OpenCV a GNU/Linux OS)
|
||||
|
||||
They are the only opencv libs needed by the JVM to interact with OpenCV.
|
||||
|
||||
Take apart the needed opencv libs
|
||||
---------------------------------
|
||||
|
||||
Create a new directory to store in the above two libs. Start by copying
|
||||
into it the ``opencv-247.jar`` lib.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
cd ~/opt
|
||||
mkdir clj-opencv
|
||||
cd clj-opencv
|
||||
cp ~/opt/opencv/build/bin/opencv-247.jar .
|
||||
|
||||
First lib done.
|
||||
|
||||
Now, to be able to add the ``libopencv_java247.dylib`` shared native lib
|
||||
to the local maven repository, we first need to package it as a jar
|
||||
file.
|
||||
|
||||
The native lib has to be copied into a directories layout which mimics
|
||||
the names of your operating system and architecture. I'm using a Mac OS
|
||||
X with a X86 64 bit architecture. So my layout will be the following:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
mkdir -p native/macosx/x86_64
|
||||
|
||||
Copy into the ``x86_64`` directory the ``libopencv_java247.dylib`` lib.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
cp ~/opt/opencv/build/lib/libopencv_java247.dylib native/macosx/x86_64/
|
||||
|
||||
If you're running OpenCV from a different OS/Architecture pair, here
|
||||
is a summary of the mapping you can choose from.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
OS
|
||||
|
||||
Mac OS X -> macosx
|
||||
Windows -> windows
|
||||
Linux -> linux
|
||||
SunOS -> solaris
|
||||
|
||||
Architectures
|
||||
|
||||
amd64 -> x86_64
|
||||
x86_64 -> x86_64
|
||||
x86 -> x86
|
||||
i386 -> x86
|
||||
arm -> arm
|
||||
sparc -> sparc
|
||||
|
||||
Package the native lib as a jar
|
||||
-------------------------------
|
||||
|
||||
Next you need to package the native lib in a jar file by using the
|
||||
``jar`` command to create a new jar file from a directory.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
jar -cMf opencv-native-247.jar native
|
||||
|
||||
Note that ehe ``M`` option instructs the ``jar`` command to not create
|
||||
a MANIFEST file for the artifact.
|
||||
|
||||
Your directories layout should look like the following:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
tree
|
||||
.
|
||||
|__ native
|
||||
| |__ macosx
|
||||
| |__ x86_64
|
||||
| |__ libopencv_java247.dylib
|
||||
|
|
||||
|__ opencv-247.jar
|
||||
|__ opencv-native-247.jar
|
||||
|
||||
3 directories, 3 files
|
||||
|
||||
Locally install the jars
|
||||
------------------------
|
||||
|
||||
We are now ready to add the two jars as artifacts to the local maven
|
||||
repository with the help of the ``lein-localrepo`` plugin.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
lein localrepo install opencv-247.jar opencv/opencv 2.4.7
|
||||
|
||||
Here the ``localrepo install`` task creates the ``2.4.7.`` release of
|
||||
the ``opencv/opencv`` maven artifact from the ``opencv-247.jar`` lib and
|
||||
then installs it into the local maven repository. The ``opencv/opencv``
|
||||
artifact will then be available to any maven compliant project
|
||||
(Leiningen is internally based on maven).
|
||||
|
||||
Do the same thing with the native lib previously wrapped in a new jar
|
||||
file.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
lein localrepo install opencv-native-247.jar opencv/opencv-native 2.4.7
|
||||
|
||||
Note that the groupId, ``opencv``, of the two artifacts is the same. We
|
||||
are now ready to create a new CLJ project to start interacting with
|
||||
OpenCV.
|
||||
|
||||
Create a project
|
||||
----------------
|
||||
|
||||
Create a new CLJ project by using the ``lein new`` task from the
|
||||
terminal.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
# cd in the directory where you work with your development projects (e.g. ~/devel)
|
||||
lein new simple-sample
|
||||
Generating a project called simple-sample based on the 'default' template.
|
||||
To see other templates (app, lein plugin, etc), try `lein help new`.
|
||||
|
||||
The above task creates the following ``simple-sample`` directories
|
||||
layout:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
tree simple-sample/
|
||||
simple-sample/
|
||||
|__ LICENSE
|
||||
|__ README.md
|
||||
|__ doc
|
||||
| |__ intro.md
|
||||
|
|
||||
|__ project.clj
|
||||
|__ resources
|
||||
|__ src
|
||||
| |__ simple_sample
|
||||
| |__ core.clj
|
||||
|__ test
|
||||
|__ simple_sample
|
||||
|__ core_test.clj
|
||||
|
||||
6 directories, 6 files
|
||||
|
||||
We need to add the two ``opencv`` artifacts as dependencies of the newly
|
||||
created project. Open the ``project.clj`` and modify its dependencies
|
||||
section as follows:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
(defproject simple-sample "0.1.0-SNAPSHOT"
|
||||
:description "FIXME: write description"
|
||||
:url "http://example.com/FIXME"
|
||||
:license {:name "Eclipse Public License"
|
||||
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
||||
:dependencies [[org.clojure/clojure "1.5.1"]
|
||||
[opencv/opencv "2.4.7"] ; added line
|
||||
[opencv/opencv-native "2.4.7"]]) ;added line
|
||||
|
||||
|
||||
Note that The Clojure Programming Language is a jar artifact too. This
|
||||
is why Clojure is called an hosted language.
|
||||
|
||||
To verify that everything went right issue the ``lein deps`` task. The
|
||||
very first time you run a ``lein`` task it will take sometime to
|
||||
download all the required dependencies before executing the task
|
||||
itself.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
cd simple-sample
|
||||
lein deps
|
||||
...
|
||||
|
||||
The ``deps`` task reads and merges from the ``project.clj`` and the
|
||||
``~/.lein/profiles.clj`` files all the dependencies of the
|
||||
``simple-sample`` project and verifies if they have already been
|
||||
cached in the local maven repository. If the task returns without
|
||||
messages about not being able to retrieve the two new artifacts your
|
||||
installation is correct, otherwise go back and double check that you
|
||||
did everything right.
|
||||
|
||||
REPLing with OpenCV
|
||||
-------------------
|
||||
|
||||
Now ``cd`` in the ``simple-sample`` directory and issue the following
|
||||
``lein`` task:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
cd simple-sample
|
||||
lein repl
|
||||
...
|
||||
...
|
||||
nREPL server started on port 50907 on host 127.0.0.1
|
||||
REPL-y 0.3.0
|
||||
Clojure 1.5.1
|
||||
Docs: (doc function-name-here)
|
||||
(find-doc "part-of-name-here")
|
||||
Source: (source function-name-here)
|
||||
Javadoc: (javadoc java-object-or-class-here)
|
||||
Exit: Control+D or (exit) or (quit)
|
||||
Results: Stored in vars *1, *2, *3, an exception in *e
|
||||
|
||||
user=>
|
||||
|
||||
You can immediately interact with the REPL by issuing any CLJ expression
|
||||
to be evaluated.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (+ 41 1)
|
||||
42
|
||||
user=> (println "Hello, OpenCV!")
|
||||
Hello, OpenCV!
|
||||
nil
|
||||
user=> (defn foo [] (str "bar"))
|
||||
#'user/foo
|
||||
user=> (foo)
|
||||
"bar"
|
||||
|
||||
When ran from the home directory of a lein based project, even if the
|
||||
``lein repl`` task automatically loads all the project dependencies, you
|
||||
still need to load the opencv native library to be able to interact with
|
||||
the OpenCV.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)
|
||||
nil
|
||||
|
||||
Then you can start interacting with OpenCV by just referencing the fully
|
||||
qualified names of its classes.
|
||||
|
||||
NOTE 2: `Here <http://docs.opencv.org/java/>`_ you can find the
|
||||
full OpenCV Java API.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (org.opencv.core.Point. 0 0)
|
||||
#<Point {0.0, 0.0}>
|
||||
|
||||
Here we created a two dimensions opencv ``Point`` instance. Even if all
|
||||
the java packages included within the java interface to OpenCV are
|
||||
immediately available from the CLJ REPL, it's very annoying to prefix
|
||||
the ``Point.`` instance constructors with the fully qualified package
|
||||
name.
|
||||
|
||||
Fortunately CLJ offer a very easy way to overcome this annoyance by
|
||||
directly importing the ``Point`` class.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (import 'org.opencv.core.Point)
|
||||
org.opencv.core.Point
|
||||
user=> (def p1 (Point. 0 0))
|
||||
#'user/p1
|
||||
user=> p1
|
||||
#<Point {0.0, 0.0}>
|
||||
user=> (def p2 (Point. 100 100))
|
||||
#'user/p2
|
||||
|
||||
We can even inspect the class of an instance and verify if the value of
|
||||
a symbol is an instance of a ``Point`` java class.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (class p1)
|
||||
org.opencv.core.Point
|
||||
user=> (instance? org.opencv.core.Point p1)
|
||||
true
|
||||
|
||||
If we now want to use the opencv ``Rect`` class to create a rectangle,
|
||||
we again have to fully qualify its constructor even if it leaves in
|
||||
the same ``org.opencv.core`` package of the ``Point`` class.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (org.opencv.core.Rect. p1 p2)
|
||||
#<Rect {0, 0, 100x100}>
|
||||
|
||||
Again, the CLJ importing facilities is very handy and let you to map
|
||||
more symbols in one shot.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (import '[org.opencv.core Point Rect Size])
|
||||
org.opencv.core.Size
|
||||
user=> (def r1 (Rect. p1 p2))
|
||||
#'user/r1
|
||||
user=> r1
|
||||
#<Rect {0, 0, 100x100}>
|
||||
user=> (class r1)
|
||||
org.opencv.core.Rect
|
||||
user=> (instance? org.opencv.core.Rect r1)
|
||||
true
|
||||
user=> (Size. 100 100)
|
||||
#<Size 100x100>
|
||||
user=> (def sq-100 (Size. 100 100))
|
||||
#'user/sq-100
|
||||
user=> (class sq-100)
|
||||
org.opencv.core.Size
|
||||
user=> (instance? org.opencv.core.Size sq-100)
|
||||
true
|
||||
|
||||
Obviously you can call methods on instances as well.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (.area r1)
|
||||
10000.0
|
||||
user=> (.area sq-100)
|
||||
10000.0
|
||||
|
||||
Or modify the value of a member field.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (set! (.x p1) 10)
|
||||
10
|
||||
user=> p1
|
||||
#<Point {10.0, 0.0}>
|
||||
user=> (set! (.width sq-100) 10)
|
||||
10
|
||||
user=> (set! (.height sq-100) 10)
|
||||
10
|
||||
user=> (.area sq-100)
|
||||
100.0
|
||||
|
||||
If you find yourself not remembering a OpenCV class behavior, the
|
||||
REPL gives you the opportunity to easily search the corresponding
|
||||
javadoc documention:
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (javadoc Rect)
|
||||
"http://www.google.com/search?btnI=I%27m%20Feeling%20Lucky&q=allinurl:org/opencv/core/Rect.html"
|
||||
|
||||
Mimic the OpenCV Java Tutorial Sample in the REPL
|
||||
-------------------------------------------------
|
||||
|
||||
Let's now try to port to Clojure the `opencv java tutorial sample <http://docs.opencv.org/2.4.4-beta/doc/tutorials/introduction/desktop_java/java_dev_intro.html>`_.
|
||||
Instead of writing it in a source file we're going to evaluate it at the
|
||||
REPL.
|
||||
|
||||
Following is the original Java source code of the cited sample.
|
||||
|
||||
.. code:: 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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Add injections to the project
|
||||
-----------------------------
|
||||
|
||||
Before start coding, we'd like to eliminate the boring need of
|
||||
interactively loading the native opencv lib any time we start a new REPL
|
||||
to interact with it.
|
||||
|
||||
First, stop the REPL by evaluating the ``(exit)`` expression at the REPL
|
||||
prompt.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (exit)
|
||||
Bye for now!
|
||||
|
||||
Then open your ``project.clj`` file and edit it as follows:
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
(defproject simple-sample "0.1.0-SNAPSHOT"
|
||||
...
|
||||
:injections [(clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)])
|
||||
|
||||
Here we're saying to load the opencv native lib anytime we run the REPL
|
||||
in such a way that we have not anymore to remember to manually do it.
|
||||
|
||||
Rerun the ``lein repl`` task
|
||||
|
||||
.. code:: bash
|
||||
|
||||
lein repl
|
||||
nREPL server started on port 51645 on host 127.0.0.1
|
||||
REPL-y 0.3.0
|
||||
Clojure 1.5.1
|
||||
Docs: (doc function-name-here)
|
||||
(find-doc "part-of-name-here")
|
||||
Source: (source function-name-here)
|
||||
Javadoc: (javadoc java-object-or-class-here)
|
||||
Exit: Control+D or (exit) or (quit)
|
||||
Results: Stored in vars *1, *2, *3, an exception in *e
|
||||
|
||||
user=>
|
||||
|
||||
Import the interested OpenCV java interfaces.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (import '[org.opencv.core Mat CvType Scalar])
|
||||
org.opencv.core.Scalar
|
||||
|
||||
We're going to mimic almost verbatim the original OpenCV java tutorial
|
||||
to:
|
||||
|
||||
- create a 5x10 matrix with all its elements intialized to 0
|
||||
- change the value of every element of the second row to 1
|
||||
- change the value of every element of the 6th column to 5
|
||||
- print the content of the obtained matrix
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (def m (Mat. 5 10 CvType/CV_8UC1 (Scalar. 0 0)))
|
||||
#'user/m
|
||||
user=> (def mr1 (.row m 1))
|
||||
#'user/mr1
|
||||
user=> (.setTo mr1 (Scalar. 1 0))
|
||||
#<Mat Mat [ 1*10*CV_8UC1, isCont=true, isSubmat=true, nativeObj=0x7fc9dac49880, dataAddr=0x7fc9d9c98d5a ]>
|
||||
user=> (def mc5 (.col m 5))
|
||||
#'user/mc5
|
||||
user=> (.setTo mc5 (Scalar. 5 0))
|
||||
#<Mat Mat [ 5*1*CV_8UC1, isCont=false, isSubmat=true, nativeObj=0x7fc9d9c995a0, dataAddr=0x7fc9d9c98d55 ]>
|
||||
user=> (println (.dump m))
|
||||
[0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
|
||||
1, 1, 1, 1, 1, 5, 1, 1, 1, 1;
|
||||
0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
|
||||
0, 0, 0, 0, 0, 5, 0, 0, 0, 0;
|
||||
0, 0, 0, 0, 0, 5, 0, 0, 0, 0]
|
||||
nil
|
||||
|
||||
If you are accustomed to a functional language all those abused and
|
||||
mutating nouns are going to irritate your preference for verbs. Even
|
||||
if the CLJ interop syntax is very handy and complete, there is still
|
||||
an impedance mismatch between any OOP language and any FP language
|
||||
(bein Scala a mixed paradigms programming language).
|
||||
|
||||
To exit the REPL type ``(exit)``, ``ctr-D`` or ``(quit)`` at the REPL
|
||||
prompt.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (exit)
|
||||
Bye for now!
|
||||
|
||||
Interactively load and blur an image
|
||||
------------------------------------
|
||||
|
||||
In the next sample you will learn how to interactively load and blur and
|
||||
image from the REPL by using the following OpenCV methods:
|
||||
|
||||
- the ``imread`` static method from the ``Highgui`` class to read an
|
||||
image from a file
|
||||
- the ``imwrite`` static method from the ``Highgui`` class to write an
|
||||
image to a file
|
||||
- the ``GaussianBlur`` static method from the ``Imgproc`` class to
|
||||
apply to blur the original image
|
||||
|
||||
We're also going to use the ``Mat`` class which is returned from the
|
||||
``imread`` method and accpeted as the main argument to both the
|
||||
``GaussianBlur`` and the ``imwrite`` methods.
|
||||
|
||||
Add an image to the project
|
||||
---------------------------
|
||||
|
||||
First we want to add an image file to a newly create directory for
|
||||
storing static resources of the project.
|
||||
|
||||
.. image:: images/lena.png
|
||||
:alt: Original Image
|
||||
:align: center
|
||||
|
||||
.. code:: bash
|
||||
|
||||
mkdir -p resources/images
|
||||
cp ~/opt/opencv/doc/tutorials/introduction/desktop_java/images/lena.png resource/images/
|
||||
|
||||
Read the image
|
||||
--------------
|
||||
|
||||
Now launch the REPL as usual and start by importing all the OpenCV
|
||||
classes we're going to use:
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
lein repl
|
||||
nREPL server started on port 50624 on host 127.0.0.1
|
||||
REPL-y 0.3.0
|
||||
Clojure 1.5.1
|
||||
Docs: (doc function-name-here)
|
||||
(find-doc "part-of-name-here")
|
||||
Source: (source function-name-here)
|
||||
Javadoc: (javadoc java-object-or-class-here)
|
||||
Exit: Control+D or (exit) or (quit)
|
||||
Results: Stored in vars *1, *2, *3, an exception in *e
|
||||
|
||||
user=> (import '[org.opencv.core Mat Size CvType]
|
||||
'[org.opencv.highgui Highgui]
|
||||
'[org.opencv.imgproc Imgproc])
|
||||
org.opencv.imgproc.Imgproc
|
||||
|
||||
Now read the image from the ``resources/images/lena.png`` file.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (def lena (Highgui/imread "resources/images/lena.png"))
|
||||
#'user/lena
|
||||
user=> lena
|
||||
#<Mat Mat [ 512*512*CV_8UC3, isCont=true, isSubmat=false, nativeObj=0x7f9ab3054c40, dataAddr=0x19fea9010 ]>
|
||||
|
||||
As you see, by simply evaluating the ``lena`` symbol we know that
|
||||
``lena.png`` is a ``512x512`` matrix of ``CV_8UC3`` elements type. Let's
|
||||
create a new ``Mat`` instance of the same dimensions and elements type.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (def blurred (Mat. 512 512 CvType/CV_8UC3))
|
||||
#'user/blurred
|
||||
user=>
|
||||
|
||||
Now apply a ``GaussianBlur`` filter using ``lena`` as the source matrix
|
||||
and ``blurred`` as the destination matrix.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (Imgproc/GaussianBlur lena blurred (Size. 5 5) 3 3)
|
||||
nil
|
||||
|
||||
As a last step just save the ``blurred`` matrix in a new image file.
|
||||
|
||||
.. code:: clojure
|
||||
|
||||
user=> (Highgui/imwrite "resources/images/blurred.png" blurred)
|
||||
true
|
||||
user=> (exit)
|
||||
Bye for now!
|
||||
|
||||
Following is the new blurred image of Lena.
|
||||
|
||||
.. image:: images/blurred.png
|
||||
:alt: Blurred Image
|
||||
:align: center
|
||||
|
||||
Next Steps
|
||||
==========
|
||||
|
||||
This tutorial only introduces the very basic environment set up to be
|
||||
able to interact with OpenCV in a CLJ REPL.
|
||||
|
||||
I recommend any Clojure newbie to read the `Clojure Java Interop chapter <http://clojure.org/java_interop>`_ to get all you need to know
|
||||
to interoperate with any plain java lib that has not been wrapped in
|
||||
Clojure to make it usable in a more idiomatic and functional way within
|
||||
Clojure.
|
||||
|
||||
The OpenCV Java API does not wrap the ``highgui`` module
|
||||
functionalities depending on ``Qt`` (e.g. ``namedWindow`` and
|
||||
``imshow``. If you want to create windows and show images into them
|
||||
while interacting with OpenCV from the REPL, at the moment you're left
|
||||
at your own. You could use Java Swing to fill the gap.
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Copyright © 2013 Giacomo (Mimmo) Cosenza aka Magomimmo
|
||||
|
||||
Distributed under the BSD 3-clause License, the same of OpenCV.
|
BIN
doc/tutorials/introduction/clojure_dev_intro/images/blurred.png
Normal file
BIN
doc/tutorials/introduction/clojure_dev_intro/images/blurred.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 351 KiB |
BIN
doc/tutorials/introduction/clojure_dev_intro/images/lena.png
Normal file
BIN
doc/tutorials/introduction/clojure_dev_intro/images/lena.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 606 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
@ -156,6 +156,21 @@ world of the OpenCV.
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
================ =================================================
|
||||
|ClojureLogo| **Title:** :ref:`clojure_dev_intro`
|
||||
|
||||
*Compatibility:* > OpenCV 2.4.4
|
||||
|
||||
*Author:* |Author_MimmoC|
|
||||
|
||||
A tutorial on how to interactively use OpenCV from the Clojure REPL.
|
||||
|
||||
================ =================================================
|
||||
|
||||
.. |ClojureLogo| image:: images/clojure-logo.png
|
||||
:height: 90pt
|
||||
:width: 90pt
|
||||
|
||||
* **Android**
|
||||
|
||||
.. tabularcolumns:: m{100pt} m{300pt}
|
||||
@ -314,6 +329,7 @@ world of the OpenCV.
|
||||
../windows_visual_studio_image_watch/windows_visual_studio_image_watch
|
||||
../desktop_java/java_dev_intro
|
||||
../java_eclipse/java_eclipse
|
||||
../clojure_dev_intro/clojure_dev_intro
|
||||
../android_binary_package/android_dev_intro
|
||||
../android_binary_package/O4A_SDK
|
||||
../android_binary_package/dev_with_OCV_on_Android
|
||||
|
9
samples/java/clojure/simple-sample/.gitignore
vendored
Normal file
9
samples/java/clojure/simple-sample/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
/target
|
||||
/classes
|
||||
/checkouts
|
||||
pom.xml
|
||||
pom.xml.asc
|
||||
*.jar
|
||||
*.class
|
||||
/.lein-*
|
||||
/.nrepl-port
|
14
samples/java/clojure/simple-sample/project.clj
Normal file
14
samples/java/clojure/simple-sample/project.clj
Normal file
@ -0,0 +1,14 @@
|
||||
(defproject simple-sample "0.1.0-SNAPSHOT"
|
||||
:pom-addition [:developers [:developer {:id "magomimmo"}
|
||||
[:name "Mimmo Cosenza"]
|
||||
[:url "https://github.com/magomimmoo"]]]
|
||||
|
||||
:description "A simple project to start REPLing with OpenCV"
|
||||
:url "http://example.com/FIXME"
|
||||
:license {:name "BSD 3-Clause License"
|
||||
:url "http://opensource.org/licenses/BSD-3-Clause"}
|
||||
:dependencies [[org.clojure/clojure "1.5.1"]
|
||||
[opencv/opencv "2.4.7"]
|
||||
[opencv/opencv-native "2.4.7"]]
|
||||
:main simple-sample.core
|
||||
:injections [(clojure.lang.RT/loadLibrary org.opencv.core.Core/NATIVE_LIBRARY_NAME)])
|
BIN
samples/java/clojure/simple-sample/resources/images/lena.png
Normal file
BIN
samples/java/clojure/simple-sample/resources/images/lena.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 606 KiB |
@ -0,0 +1,16 @@
|
||||
;;; to run this code from the terminal: "$ lein run". It will save a
|
||||
;;; blurred image version of resources/images/lena.png as
|
||||
;;; resources/images/blurred.png
|
||||
|
||||
(ns simple-sample.core
|
||||
(:import [org.opencv.core Point Rect Mat CvType Size Scalar]
|
||||
org.opencv.highgui.Highgui
|
||||
org.opencv.imgproc.Imgproc))
|
||||
|
||||
(defn -main [& args]
|
||||
(let [lena (Highgui/imread "resources/images/lena.png")
|
||||
blurred (Mat. 512 512 CvType/CV_8UC3)]
|
||||
(print "Blurring...")
|
||||
(Imgproc/GaussianBlur lena blurred (Size. 5 5) 3 3)
|
||||
(Highgui/imwrite "resources/images/blurred.png" blurred)
|
||||
(println "done!")))
|
@ -0,0 +1,7 @@
|
||||
(ns simple-sample.core-test
|
||||
(:require [clojure.test :refer :all]
|
||||
[simple-sample.core :refer :all]))
|
||||
|
||||
(deftest a-test
|
||||
(testing "FIXME, I fail."
|
||||
(is (= 0 1))))
|
Loading…
Reference in New Issue
Block a user