OpenCV for Eclipse - java

Installation instructions: http://docs.opencv.org/doc/tutorials/introduction/desktop_java/java_dev_intro.html
I have downloaded everything. Everything seems to be working except when I run this sample program:
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
public class Main {
public static void main(String[] args) {
System.out.println("Welcome to OpenCV " + Core.VERSION);
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat m = Mat.eye(3, 3, CvType.CV_8UC1);
System.out.println("m = " + m.dump());
}
}
I get the output:
m = [1, 0, 0;
0, 1, 0;
0, 0, 1]
(which I hope is right).
But I also get these error messages:
objc[63784]: Class CVWindow is implemented in both /Users/.../cv2.so and /Users/... /libopencv_java246.dylib. One of the two will be used. Which one is undefined.
objc[63784]: Class CVView is implemented in both /Users/.../cv2.so and /Users/.../libopencv_java246.dylib. One of the two will be used. Which one is undefined.
objc[63784]: Class CVSlider is implemented in both /Users/.../cv2.so and /Users/.../libopencv_java246.dylib. One of the two will be used. Which one is undefined.
objc[63784]: Class CaptureDelegate is implemented in both /Users/... /cv2.so and /Users/jsuit/opencv/lib/libopencv_java246.dylib. One of the two will be used. Which one is undefined.
I have tried moving the cv2.so file to another folder, but then the program won't compile.

The problem has to do, as far as I can make out, with a reference to the Python libraries (the .so version) that ends up included within the Java libraries themselves. This would seem to be a build configuration error (following the instructions does produce it).
I was able to eliminate the double-definition error by re-building the Java version without support for the Python libraries in it, using the following in the cmake step (all else the same):
cmake -D BUILD_SHARED_LIBS=OFF -D BUILD_NEW_PYTHON_SUPPORT=NO ..
The newly produced Java libraries and .jar work just as before, but without the error message.
(Note that I can't guarantee this won't cause other problems, especially if you want to do some sort of mixed-language programming, but it does produce libraries useful for Java and Eclipse. You can always build multiple versions of OpenCV, too, some with support for Python, some without, and use whichever one you like if you switch languages at some point.)
Hat tip: http://answers.opencv.org/question/16015/mac-opencv-246-java-exception/

Related

InOut.readInt() only working in Windows Java Editor

At school, I write Java programs with Windows’ Java Editor (console mode). There, InOut.readInt() (used for user input) works without problems and I don’t have to import anything.
Now, I have a Java homework for the holidays, and I try to write Java programs on my Mac. In online console Java editors, the line InOut.readInt() causes this error:
/IntBetween10And100.java:8: error: cannot find symbol
int input = InOut.readInt("Integer --> ");
^
symbol: variable InOut
location: class IntBetween10And100
1 error
I already tried import lines (placed before the class) like:
import java.*
import java.util.*
import java.util.InOut
import java.io.BufferedStreamReader
import java.util.*;
public class IntBetween10And100 {
public static void main(String args[]) {
int input = InOut.readInt("Integer --> ");
}
}
int input = InOut.readInt("Integer --> ");
should produce the line
Integer -->
but instead, the error message (seen above) appears.
OK, so you are using the "Java-Editor" tool on Windows for writing your Java code.
It turns out that Java-Editor includes a class called InOut as an example class. (You can see it here: http://javaeditor.org/doku.php?id=en:examples).
For various reasons, it is not suitable for use in production code of any kind:
It is not part of the Java SE class library, or any 3rd-party libraries.
It is a class in the default package
It has limited functionality, even compared to the real System.in and System.out
It would interfere with any application or 3rd party library code that uses System.in in the normal way. (It creates its own BufferedReader to wrap System.in. That is liable to capture "type-ahead" input.)
You don't really need to use it for educational purposes either. It is only a wrapper class ...
However, if you want to use InOut outside of the Java-Editor context, you could simply download the source code from the page above and add it to your project. I can't tell you exactly how, but adding classes should be explained in the documentation of the tool you are using now! (If you are serious about learning Java, I would actually recommend that you download and install a real Java JDK and a real Java IDE on your own computer.)
The authors have neglected to include an explicit copyright notice in the InOut.java file. However, the Java-Editor site as a whole is licensed as "CC Attribution-Share Alike 4.0 International".

Java : Reuse a native library already loaded?

Disclaimer Not native English speaker, feel free to edit if needed.
I'm having a similar issue that the one explained here :
java.lang.UnsatisfiedLinkError: Native Library XXX.so already loaded in another classloader
I'm trying to follow the answer of user2543253. But I really lacks of knowledge in Java and the context is a bit different.
Links
.dll already loaded in another classloader? Seems also related to this question.
https://github.com/PatternConsulting/opencv/issues/7 Similar.
https://cycling74.com/articles/mxj-class-loading Explains the class loader behavior of MXJ
Context
Edit : Not sure if that context is really important, it seems to be the same problem described in link 1.
I want to use OpenCV inside an Application called Max/MSP.
To give an idea, it looks like this :
Max/MSP allows user to assemble Patch by cabling some objects together that are called externals, most of them are coded in C but you can also create externals in Java. To do so you need to instantiate them through an object called "mxj". For example, if my Java class is called TestOpenCV, I will create a box and put "mxj TestOpenCV" inside.
OpenCV seems correctly implemented, for exemple, I can instantiate a Mat object and post its content to Max console.
Problems appears when I change the Java code of the mxj object. To update my object, I delete it and recreate it again. Then, the same issue that explained here appears...
Max console return this error message :
java.lang.UnsatisfiedLinkError: Native Library
C:\Windows\System32\opencv_java300.dll already loaded in another
classloader at java.lang.ClassLoader.loadLibrary1(Unknown Source) at
java.lang.ClassLoader.loadLibrary0(Unknown Source) at
java.lang.ClassLoader.loadLibrary(Unknown Source) at
java.lang.Runtime.loadLibrary0(Unknown Source) at
java.lang.System.loadLibrary(Unknown Source) at
OpenCVClassLoad.loadNativeLibrary(OpenCVClassLoad.java:5) at
TestOpenCV.(TestOpenCV.java:22) (mxj) unable to alloc instance
of TestOpenCV
What I tried
I tried to implement the answer of user2543253. He advices to create a tiny classes that import the native library and export it as a JAR. So I created a new Eclipse project added a source file to it
import org.opencv.core.Core;
public class OpenCVClassLoad {
public static void loadNativeLibrary() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
}
I added the openCV JAR to that project and exported it as a JAR.
Then I changed my code according to what user2543253 explained (there is more code,I kept the essential) :
import com.cycling74.max.*;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
public class TestOpenCV extends MaxObject {
static {
// System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
OpenCVClassLoad.loadNativeLibrary();
}
public TestOpenCV(Atom[] args)
{
// ...
}
public void notifyDeleted()
{
// ...
}
public void bang() {
// Executed when I trig the little bang button you can see
Mat m = new Mat(5, 9, CvType.CV_8UC4, new Scalar(0));
post("OpenCV Mat: " + m);
Mat mr1 = m.row(1);
mr1.setTo(new Scalar(1));
Mat mc5 = m.col(3);
mc5.setTo(new Scalar(5));
post("OpenCV Mat data:\n" + m.dump());
}
}
Of course, but that's a bit weird, in order to build correctly that project I kept the JAR from OpenCV in the build path :
As you can see, I also added the tiny class in the project build path.
After all of theses modifications, the mxj object stille loads correctly the first time and the bang() method still works but the problem still there. In fact it doesn't change anything from the past situation : If I modify the Java code, delete the object in Max and create a new one, error appears...
Question
There is a lot of SO questions addressing the same type of prob but context is always different and its hard to figure out what to do, especially with my basic knowledge of Java.
A workaround should be to simply reuse that library already loaded, no ? but how to achieve this ? Because if I check the library has already being loaded, I do it using a Try / Catch, if I do nothing else. The externals acts like if the library had never been loaded...
How to reuse that native library ? (Of course, any alternative solution to this is welcome)
Just remove the second OpenCVClassLoad.loadNativeLibrary(); in your bang() method. In a plain Java application the code in a static block is only executed once.
Alternatively, you can specify the native library location in Eclipse instead of loading the library through Java source code.

Can't get OpenCV to work with Java+Maven+IntelliJ

I've seen lots of people asking similar questions to mine but their solutions aren't working for me. Here's what I've got:
I downloaded the latest OpenCV for Windows (2.4.9). I extracted this to C:\opencv-249
I then created a new Maven 3 project in IntelliJ. This works fine and I can run the compile/package goals, etc. I can execute and debug my program. This is all good.
Next, I tried to pull OpenCV into my test app and ended up with the following code:
package com.foo.OpenCVTest;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.CvType;
/**
* Created by rick on 5/7/2014.
*/
public class RobotCntrl {
static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }
static public void main(String args[]) {
System.out.println("In main!");
System.out.println("Core Lib: " + Core.NATIVE_LIBRARY_NAME);
Mat m = Mat.eye(3, 3, CvType.CV_8UC1);
System.out.println("m = " + m.dump());
}
}
I then added the local OpenCV to my pom.xml:
<dependency>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>2.4.9</version>
<systemPath>${java.home}/../../../../opencv-249/build/java/opencv-249.jar</systemPath>
<scope>system</scope>
</dependency>
And I added OpenCV as a project library:
And I modified the IntelliJ VM Options (Edit Configurations) to update the java.library.path to point to the OpenCV dlls:
When I run the application appears to load the opencv_java249.dll library just fine (it doesn't complain), but for the line:
Mat m = Mat.eye(3, 3, CvType.CV_8UC1);
It bombs out complaining that it can't find the underlying n_eye() native function:
In main!
Exception in thread "main" java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_eye(III)J
Core Lib: opencv_java249
at org.opencv.core.Mat.n_eye(Native Method)
at org.opencv.core.Mat.eye(Mat.java:1467)
at com.aether.Robots.RobotCntrl.main(RobotCntrl.java:25)
Process finished with exit code 1
I'm at a loss now. It's loading the wrapper library but it can't call the dependent functions. For the previous questions on similar issues, it tends to be resolved when people update their java.library.path variable, but mine seems correct:
-Djava.library.path=C:\opencv-249\build\x64\vc10\bin;C:\opencv-249\build\java\x64
or people forget to call System.loadLibrary(), but that call is succeeding (as far as I can tell) for me.
Any ideas?

PyDev Jython module_not_found_in_the_pythonpath, autocomplete not working

I've been searching for two days now trying to get PyDev to recognize my external .JAR (It's obfuscated for protection), however no matter what I do it doesn't want to work. I've read over the documentation for nearly a hour straight trying to get it to work.
I'm helping to work on an emulation server which uses Jython for scripting. I can compile and run the emulation server with the scripts working just fine however, without using autocompletion for the methods inside the engine part of the server which is obfuscated in a external .jar.
Here is an example code of a script which uses methods from the obfuscated .JAR (which isn't working with autocomplete, so I have to navigate through the package explorer to find the method I want to use):
import sys
def CreateStartingCharacter(core, object):
testObject = core.objectService.createObject('object/weapon/ranged/rifle/shared_rifle_t21.iff', object.getPlanet())
testObject.setCustomName('This is a Jython Rifle')
testObject.setStringAttribute('crafter', 'Light')
inventory = object.getSlottedObject('inventory')
inventory.add(testObject)
testClothing = core.objectService.createObject('object/tangible/wearables/cape/shared_cape_rebel_01.iff', object.getPlanet())
testClothing.setCustomName('Test Cape')
testCloak = core.objectService.createObject('object/tangible/wearables/robe/shared_robe_jedi_dark_s05.iff', object.getPlanet())
testCloak.setCustomName('Test Cloak')
inventory.add(testClothing)
inventory.add(testCloak)
return
This script is executed by the following command in Java (core is the class inside the external JAR, obfuscated)
core.scriptService.callScript("scripts/", "demo", "CreateStartingCharacter", object);
object is...
CreatureObject object = (CreatureObject)core.objectService.createObject(sharedRaceTemplate, core.terrainService.getPlanetList().get(0));
Like I said above, all of those methods that I used in the script were from the obfuscated JAR which isn't working with autocomplete. However, I can use a method that isn't in that JAR just fine such as:
from resources.common import RadialOptions
from services.sui import SUIWindow
from services.sui.SUIWindow import Trigger
from java.util import Vector
import sys
def createRadial(core, owner, target, radials):
radials.clear()
bank = owner.getSlottedObject('bank')
if bank:
radials.add(RadialOptions(0, 21, 1, ''))
radials.add(RadialOptions(0, 7, 1, ''))
radials.add(RadialOptions(1, RadialOptions.bankTransfer, 3, '#sui:bank_credits'))
radials.add(RadialOptions(1, RadialOptions.bankitems, 3, '#sui:bank_items'))
if owner.getBankCredits() > 0:
radials.add(RadialOptions(1, RadialOptions.bankWithdrawAll, 3, '#sui:bank_withdrawall'))
if owner.getCashCredits() > 0:
radials.add(RadialOptions(1, RadialOptions.bankDepositAll, 3, '#sui:bank_depositall'))
return
... and using RadialOptions. control+space will show me all the methods.
Help would be much appreciated. At this point I feel that it's not working because the JAR file is obfuscated or something like that. And yes, I've already added it to my PYTHONPATH and updated the interpreter, just like with the bin folder for my project.

How to call a java function from python/numpy?

it is clear to me how to extend Python with C++, but what if I want to write a function in Java to be used with numpy?
Here is a simple scenario: I want to compute the average of a numpy array using a Java class. How do I pass the numpy vector to the Java class and gather the result?
Thanks for any help!
I spent some time on my own question and would like to share my answer as I feel there is not much information on this topic on stackoverflow. I also think Java will become more relevant in scientific computing (e.g. see WEKA package for data mining) because of the improvement of performance and other good software development features of Java.
In general, it turns out that using the right tools it is much easier to extend Python with Java than with C/C++!
Overview and assessment of tools to call Java from Python
http://pypi.python.org/pypi/JCC: because of no proper
documentation this tool is useless.
Py4J: requires to start the Java process before using python. As
remarked by others this is a possible point of failure. Moreover, not many examples of use are documented.
JPype: although development seems to be death, it works well and there are
many examples on it on the web (e.g. see http://kogs-www.informatik.uni-hamburg.de/~meine/weka-python/ for using data mining libraries written in Java) . Therefore I decided to focus
on this tool.
Installing JPype on Fedora 16
I am using Fedora 16, since there are some issues when installing JPype on Linux, I describe my approach.
Download JPype, then modify setup.py script by providing the JDK path, in line 48:
self.javaHome = '/usr/java/default'
then run:
sudo python setup.py install
Afters successful installation, check this file:
/usr/lib64/python2.7/site-packages/jpype/_linux.py
and remove or rename the method getDefaultJVMPath() into getDefaultJVMPath_old(), then add the following method:
def getDefaultJVMPath():
return "/usr/java/default/jre/lib/amd64/server/libjvm.so"
Alternative approach: do not make any change in the above file _linux.py, but never use the method getDefaultJVMPath() (or methods which call this method). At the place of using getDefaultJVMPath() provide directly the path to the JVM. Note that there are several paths, for example in my system I also have the following paths, referring to different versions of the JVM (it is not clear to me whether the client or server JVM is better suited):
/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre/lib/x86_64/client/libjvm.so
/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre/lib/x86_64/server/libjvm.so
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/amd64/server/libjvm.so
Finally, add the following line to ~/.bashrc (or run it each time before opening a python interpreter):
export JAVA_HOME='/usr/java/default'
(The above directory is in reality just a symbolic link to my last version of JDK, which is located at /usr/java/jdk1.7.0_04).
Note that all the tests in the directory where JPype has been downloaded, i.e. JPype-0.5.4.2/test/testsuite.py will fail (so do not care about them).
To see if it works, test this script in python:
import jpype
jvmPath = jpype.getDefaultJVMPath()
jpype.startJVM(jvmPath)
# print a random text using a Java class
jpype.java.lang.System.out.println ('Berlusconi likes women')
jpype.shutdownJVM()
Calling Java classes from Java also using Numpy
Let's start implementing a Java class containing some functions which I want to apply to numpy arrays. Since there is no concept of state, I use static functions so that I do not need to create any Java object (creating Java objects would not change anything).
/**
* Cookbook to pass numpy arrays to Java via Jpype
* #author Mannaggia
*/
package test.java;
public class Average2 {
public static double compute_average(double[] the_array){
// compute the average
double result=0;
int i;
for (i=0;i<the_array.length;i++){
result=result+the_array[i];
}
return result/the_array.length;
}
// multiplies array by a scalar
public static double[] multiply(double[] the_array, double factor) {
int i;
double[] the_result= new double[the_array.length];
for (i=0;i<the_array.length;i++) {
the_result[i]=the_array[i]*factor;
}
return the_result;
}
/**
* Matrix multiplication.
*/
public static double[][] mult_mat(double[][] mat1, double[][] mat2){
// find sizes
int n1=mat1.length;
int n2=mat2.length;
int m1=mat1[0].length;
int m2=mat2[0].length;
// check that we can multiply
if (n2 !=m1) {
//System.err.println("Error: The number of columns of the first argument must equal the number of rows of the second");
//return null;
throw new IllegalArgumentException("Error: The number of columns of the first argument must equal the number of rows of the second");
}
// if we can, then multiply
double[][] the_results=new double[n1][m2];
int i,j,k;
for (i=0;i<n1;i++){
for (j=0;j<m2;j++){
// initialize
the_results[i][j]=0;
for (k=0;k<m1;k++) {
the_results[i][j]=the_results[i][j]+mat1[i][k]*mat2[k][j];
}
}
}
return the_results;
}
/**
* #param args
*/
public static void main(String[] args) {
// test case
double an_array[]={1.0, 2.0,3.0,4.0};
double res=Average2.compute_average(an_array);
System.out.println("Average is =" + res);
}
}
The name of the class is a bit misleading, as we do not only aim at computing the average of a numpy vector (using the method compute_average), but also multiply a numpy vector by a scalar (method multiply), and finally, the matrix multiplication (method mult_mat).
After compiling the above Java class we can now run the following Python script:
import numpy as np
import jpype
jvmPath = jpype.getDefaultJVMPath()
# we to specify the classpath used by the JVM
classpath='/home/mannaggia/workspace/TestJava/bin'
jpype.startJVM(jvmPath,'-Djava.class.path=%s' % classpath)
# numpy array
the_array=np.array([1.1, 2.3, 4, 6,7])
# build a JArray, not that we need to specify the Java double type using the jpype.JDouble wrapper
the_jarray2=jpype.JArray(jpype.JDouble, the_array.ndim)(the_array.tolist())
Class_average2=testPkg.Average2
res2=Class_average2.compute_average(the_jarray2)
np.abs(np.average(the_array)-res2) # ok perfect match!
# now try to multiply an array
res3=Class_average2.multiply(the_jarray2,jpype.JDouble(3))
# convert to numpy array
res4=np.array(res3) #ok
# matrix multiplication
the_mat1=np.array([[1,2,3], [4,5,6], [7,8,9]],dtype=float)
#the_mat2=np.array([[1,0,0], [0,1,0], [0,0,1]],dtype=float)
the_mat2=np.array([[1], [1], [1]],dtype=float)
the_mat3=np.array([[1, 2, 3]],dtype=float)
the_jmat1=jpype.JArray(jpype.JDouble, the_mat1.ndim)(the_mat1.tolist())
the_jmat2=jpype.JArray(jpype.JDouble, the_mat2.ndim)(the_mat2.tolist())
res5=Class_average2.mult_mat(the_jmat1,the_jmat2)
res6=np.array(res5) #ok
# other test
the_jmat3=jpype.JArray(jpype.JDouble, the_mat3.ndim)(the_mat3.tolist())
res7=Class_average2.mult_mat(the_jmat3,the_jmat2)
res8=np.array(res7)
res9=Class_average2.mult_mat(the_jmat2,the_jmat3)
res10=np.array(res9)
# test error due to invalid matrix multiplication
the_mat4=np.array([[1], [2]],dtype=float)
the_jmat4=jpype.JArray(jpype.JDouble, the_mat4.ndim)(the_mat4.tolist())
res11=Class_average2.mult_mat(the_jmat1,the_jmat4)
jpype.java.lang.System.out.println ('Goodbye!')
jpype.shutdownJVM()
I consider Jython to be one of the best options - which makes it seamless to use java objects in python. I actually integrated weka with my python programs, and it was super easy. Just import the weka classes and call them as you would in java within the python code.
http://www.jython.org/
I'm not sure about numpy support, but the following might be helpful:
http://pypi.python.org/pypi/JCC/

Categories

Resources