(看到有很多同学都来看这篇文章,说明可能是有必要的,然后这个写的比较水,所以 如果求干货的话,请移步:
http://www.cnblogs.com/letben/p/5885799.html
但是 要在这个里面下载那个169Mb的jar包。
)
也不能算是突发奇想,但是,eclipse 的确可以跑 opencv的类库。下面是跑动的一些背景:
https://github.com/bytedeco/javacv#manual-installation
javacv
介绍:
javacv使用来自javacpp的预置封装和提供工具包来让他们的功能更容易的在java平台以及android上使用。(这些javacpp的预置是研究人员在计算机视觉(包括:OpenCV, FFmpeg, libdc1394, PGR FlyCapture, OpenKinect, videoInput, ARToolKitPlus, and flandmark)上广泛应用的类库)
javacv包含硬件加速全屏图像显示(CanvasFrame
and GLCanvasFrame
),更容易的方式来执行代码在多核并行的情况下,用户友好的几何和颜色校准在相机和投影仪情况下(GeometricCalibrator
, ProCamGeometricCalibrator
, ProCamColorCalibrator
),探测和匹配特征点(ObjectFinder),一系列实现图像和投影相机对齐系统的设置(主要有:mainlyGNImageAligner
, ProjectiveTransformer
, ProjectiveColorTransformer
, ProCamTransformer
, andReflectanceInitializer
),一个斑点分析包(Blobs),还有许多混杂的功能在javacv类中。这些类中还包含OpenCL和 OpenGL对应的部分,他们的名字以CL结束或者以GL开头:举个例子:javaCVCL ,GLCanvasFrame,等等。
为了学习如何使用API,既然当前缺少文档,请参考一些 Sample Usage部分或者sample programs,包括两个对android的(FacePreview.java 和 RecordActivity.java),可以在样例目录中找到。你会发现参考一些源码也是有意义的比如 ProCamCalib and ProCamTracker as well as examples ported from OpenCV2 Cookbook and the associated wiki pages.
请告知我你做的在代码上的更新或者修改以便于我可以整合他们到下一个版本。谢谢。尽管问关于 the mailing list的问题,如果你遇到了在软件方面的问题。我知道还有许多需要改进的地方…
下载:
为了手动的安装jar文件,获得持续更新的文档和说明,需要手动安装下面的部分:
- JavaCV 1.2 binary archive javacv-1.2-bin.zip (169 MB)
- JavaCV 1.2 source archive javacv-1.2-src.zip (426 KB)
二进制文件包含了对android linux Mac OS X,和windows。对于特定子模块或者平台的jar包可以通过 Maven Central Repository 来单独包含。
我们也可以自动的下载安装通过下面的配置:
- Maven (inside the
pom.xml
file)
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.2</version>
</dependency>
- Gradle (inside the
build.gradle
file)
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.bytedeco', name: 'javacv', version: '1.2'
}
- sbt (inside the
build.sbt
file)
classpathTypes += "maven-plugin" libraryDependencies += "org.bytedeco" % "javacv" % "1.2" 补充一点:我们需要设置javacpp.platform 系统属性(通过 -D 命令行选项)像android-arm,或者设置javacpp.platform.dependencies 来真实的得到所有对于android linux Mac OS X 和windows 的二进制文件。如果建立的系统不工作我们需要手动增加 平台指定 人工产品。举个例子 在Gradle 和 sbt 请参考 README.md file of the JavaCPP Presets.另外一个对于Scala用的可靠选项是 sbt-javacv. 需要软件:
为了使用javaCv,你需要首先安装下面的软件:
一个实现java SE 7或者更高版本的:
- OpenJDK http://openjdk.java.net/install/ or
- Sun JDK http://www.oracle.com/technetwork/java/javase/downloads/ or
- IBM JDK http://www.ibm.com/developerworks/java/jdk/
进一步,尽管不总是需要,一些javaCV还是需要一些功能性上的支持:
- CL Eye Platform SDK (Windows only) http://codelaboratories.com/downloads/
- Android SDK API 14 or newer http://developer.android.com/sdk/
- JOCL and JOGL from JogAmp http://jogamp.org/
最后,请确保每个软件都是相同进制位的:32位和64位模块,任何时候都不要混淆
手动安装:
把所有需要的jar文件 (opencv*.jar
, ffmpeg*.jar
, etc.)包括javacpp.jar
and javacv.jar,一些在你的类路径里面,这是一些特定的指示对于大多数用例来讲:
NetBeans (Java SE 7 or newer):
1、window 选项,在工程上的Libraries部分右键, 选择:“Add JAR/Folder...”
2、定位jar包,选择他们,点击OK
Eclipse (Java SE 7 or newer):
1、导航栏:工程>属性>java Build Path> Libraries 点击 Add External JARs...
2、定位 jar文件,选择他们,点击ok
IntelliJ IDEA (Android 4.0 or newer):
1、遵循这一页的指示: http://developer.android.com/training/basics/firstapp/
2、复制所有的jar包到app/libs 子目录
3、导航到 File >工程结构> app>依赖, 点击+ 然后选择 2文件依赖
4、从libs 子目录中选择所有jar文件
之后,举个例子来自opencv和FFmpeg的封装类就会自动的连接他们的C/C++ APIs:
一些用例:
类的定义基本上都是在C / C++头文件的原始java端口,我特意决定尽可能保持原来的语法。例如,这里是一个方法,试图加载一个图像文件,平滑它,并将其保存到磁盘:
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;
import static org.bytedeco.javacpp.opencv_imgcodecs.*; public class Smoother {
public static void smooth(String filename) {
IplImage image = cvLoadImage(filename);
if (image != null) {
cvSmooth(image, image);
cvSaveImage(filename, image);
cvReleaseImage(image);
}
}
}
javacv在OpenCV和ffmpeg的上层还有辅助类和方法协助他们融入到java平台。这里是一个小的演示程序,展示了最常用的部分:
import java.io.File;
import java.net.URL;
import org.bytedeco.javacv.*;
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.indexer.*;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;
import static org.bytedeco.javacpp.opencv_calib3d.*;
import static org.bytedeco.javacpp.opencv_objdetect.*; public class Demo {
public static void main(String[] args) throws Exception {
String classifierName = null;
if (args.length > 0) {
classifierName = args[0];
} else {
URL url = new URL("https://raw.github.com/Itseez/opencv/2.4.0/data/haarcascades/haarcascade_frontalface_alt.xml");
File file = Loader.extractResource(url, null, "classifier", ".xml");
file.deleteOnExit();
classifierName = file.getAbsolutePath();
} // Preload the opencv_objdetect module to work around a known bug.
Loader.load(opencv_objdetect.class); // We can "cast" Pointer objects by instantiating a new object of the desired class.
CvHaarClassifierCascade classifier = new CvHaarClassifierCascade(cvLoad(classifierName));
if (classifier.isNull()) {
System.err.println("Error loading classifier file \"" + classifierName + "\".");
System.exit(1);
} // The available FrameGrabber classes include OpenCVFrameGrabber (opencv_videoio),
// DC1394FrameGrabber, FlyCaptureFrameGrabber, OpenKinectFrameGrabber,
// PS3EyeFrameGrabber, VideoInputFrameGrabber, and FFmpegFrameGrabber.
FrameGrabber grabber = FrameGrabber.createDefault(0);
grabber.start(); // CanvasFrame, FrameGrabber, and FrameRecorder use Frame objects to communicate image data.
// We need a FrameConverter to interface with other APIs (Android, Java 2D, or OpenCV).
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage(); // FAQ about IplImage and Mat objects from OpenCV:
// - For custom raw processing of data, createBuffer() returns an NIO direct
// buffer wrapped around the memory pointed by imageData, and under Android we can
// also use that Buffer with Bitmap.copyPixelsFromBuffer() and copyPixelsToBuffer().
// - To get a BufferedImage from an IplImage, or vice versa, we can chain calls to
// Java2DFrameConverter and OpenCVFrameConverter, one after the other.
// - Java2DFrameConverter also has static copy() methods that we can use to transfer
// data more directly between BufferedImage and IplImage or Mat via Frame objects.
IplImage grabbedImage = converter.convert(grabber.grab());
int width = grabbedImage.width();
int height = grabbedImage.height();
IplImage grayImage = IplImage.create(width, height, IPL_DEPTH_8U, 1);
IplImage rotatedImage = grabbedImage.clone(); // Objects allocated with a create*() or clone() factory method are automatically released
// by the garbage collector, but may still be explicitly released by calling release().
// You shall NOT call cvReleaseImage(), cvReleaseMemStorage(), etc. on objects allocated this way.
CvMemStorage storage = CvMemStorage.create(); // The OpenCVFrameRecorder class simply uses the CvVideoWriter of opencv_videoio,
// but FFmpegFrameRecorder also exists as a more versatile alternative.
FrameRecorder recorder = FrameRecorder.createDefault("output.avi", width, height);
recorder.start(); // CanvasFrame is a JFrame containing a Canvas component, which is hardware accelerated.
// It can also switch into full-screen mode when called with a screenNumber.
// We should also specify the relative monitor/camera response for proper gamma correction.
CanvasFrame frame = new CanvasFrame("Some Title", CanvasFrame.getDefaultGamma()/grabber.getGamma()); // Let's create some random 3D rotation...
CvMat randomR = CvMat.create(3, 3), randomAxis = CvMat.create(3, 1);
// We can easily and efficiently access the elements of matrices and images
// through an Indexer object with the set of get() and put() methods.
DoubleIndexer Ridx = randomR.createIndexer(), axisIdx = randomAxis.createIndexer();
axisIdx.put(0, (Math.random()-0.5)/4, (Math.random()-0.5)/4, (Math.random()-0.5)/4);
cvRodrigues2(randomAxis, randomR, null);
double f = (width + height)/2.0; Ridx.put(0, 2, Ridx.get(0, 2)*f);
Ridx.put(1, 2, Ridx.get(1, 2)*f);
Ridx.put(2, 0, Ridx.get(2, 0)/f); Ridx.put(2, 1, Ridx.get(2, 1)/f);
System.out.println(Ridx); // We can allocate native arrays using constructors taking an integer as argument.
CvPoint hatPoints = new CvPoint(3); while (frame.isVisible() && (grabbedImage = converter.convert(grabber.grab())) != null) {
cvClearMemStorage(storage); // Let's try to detect some faces! but we need a grayscale image...
cvCvtColor(grabbedImage, grayImage, CV_BGR2GRAY);
CvSeq faces = cvHaarDetectObjects(grayImage, classifier, storage,
1.1, 3, CV_HAAR_FIND_BIGGEST_OBJECT | CV_HAAR_DO_ROUGH_SEARCH);
int total = faces.total();
for (int i = 0; i < total; i++) {
CvRect r = new CvRect(cvGetSeqElem(faces, i));
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
cvRectangle(grabbedImage, cvPoint(x, y), cvPoint(x+w, y+h), CvScalar.RED, 1, CV_AA, 0); // To access or pass as argument the elements of a native array, call position() before.
hatPoints.position(0).x(x-w/10) .y(y-h/10);
hatPoints.position(1).x(x+w*11/10).y(y-h/10);
hatPoints.position(2).x(x+w/2) .y(y-h/2);
cvFillConvexPoly(grabbedImage, hatPoints.position(0), 3, CvScalar.GREEN, CV_AA, 0);
} // Let's find some contours! but first some thresholding...
cvThreshold(grayImage, grayImage, 64, 255, CV_THRESH_BINARY); // To check if an output argument is null we may call either isNull() or equals(null).
CvSeq contour = new CvSeq(null);
cvFindContours(grayImage, storage, contour, Loader.sizeof(CvContour.class),
CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
while (contour != null && !contour.isNull()) {
if (contour.elem_size() > 0) {
CvSeq points = cvApproxPoly(contour, Loader.sizeof(CvContour.class),
storage, CV_POLY_APPROX_DP, cvContourPerimeter(contour)*0.02, 0);
cvDrawContours(grabbedImage, points, CvScalar.BLUE, CvScalar.BLUE, -1, 1, CV_AA);
}
contour = contour.h_next();
} cvWarpPerspective(grabbedImage, rotatedImage, randomR); Frame rotatedFrame = converter.convert(rotatedImage);
frame.showImage(rotatedFrame);
recorder.record(rotatedFrame);
}
frame.dispose();
recorder.stop();
grabber.stop();
}
}
进一步:通过下面的内容创建一个pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.bytedeco.javacv</groupId>
<artifactId>demo</artifactId>
<version>1.2</version>
<dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</project>
通过把源代码放到:src/main/java/Demo.java里面:我们可以使用下面的命令在Maven中来让所有内容自动安装并执行:
$ mvn package exec:java -Dexec.mainClass=Demo
构建说明:
如果上面的二进制文件不能满足你的需要,你可能需要重新构建源码,为此项目需要重建:
- Maven 3.x http://maven.apache.org/download.html
- JavaCPP 1.2 https://github.com/bytedeco/javacpp
- JavaCPP Presets 1.2 https://github.com/bytedeco/javacpp-presets
一旦安装,对于javaCPP 和它的预置 和javaCV仅需要调用mvn install 命令。默认情况下,比起C++javaCPP不需要其他的依赖项,请参考pom.xml文件里面的注释来获得更多细节。
Project lead(项目领导): Samuel Audet samuel.audet at
gmail.com
Developer site(开发者站点): https://github.com/bytedeco/javacv
Discussion group(讨论组): http://groups.google.com/group/javacv