Коммерческая поддержка:
JavaCV использует оболочки из пресетов JavaCPP часто используемых библиотек исследователей в области компьютерного зрения (OpenCV, FFmpeg, libdc1394, FlyCapture, Spinnaker, OpenKinect, librealsense, CL PS3 Eye Driver, videoInput, ARToolKitPlus, flandmark, Leptonica и Tesseract). и предоставляет служебные классы, упрощающие использование их функций на платформе Java, включая Андроид.
JavaCV также поставляется с аппаратным ускорением полноэкранного отображения изображений ( CanvasFrame
и GLCanvasFrame
), простыми в использовании методами для параллельного выполнения кода на нескольких ядрах ( Parallel
), удобной для пользователя геометрической и цветовой калибровкой камер и проекторов ( GeometricCalibrator
, ProCamGeometricCalibrator
. , ProCamColorCalibrator
), обнаружение и сопоставление характерных точек ( ObjectFinder
), набор классов, реализующих прямое выравнивание изображений системы проектор-камера (в основном GNImageAligner
, ProjectiveTransformer
, ProjectiveColorTransformer
, ProCamTransformer
и ReflectanceInitializer
), пакет анализа больших двоичных объектов ( Blobs
), а также разные функциональные возможности в классе JavaCV
. Некоторые из этих классов также имеют аналоги OpenCL и OpenGL, их имена заканчиваются на CL
или начинаются на GL
, например: JavaCVCL
, GLCanvasFrame
и т. д.
Чтобы узнать, как использовать API, поскольку документация в настоящее время отсутствует, обратитесь к разделу «Пример использования» ниже, а также к примерам программ, в том числе двум для Android ( FacePreview.java
и RecordActivity.java
), которые также находятся в каталоге samples
. Вам также может оказаться полезным обратиться к исходному коду ProCamCalib и ProCamTracker, а также к примерам, перенесенным из OpenCV2 Cookbook и связанных с ними вики-страниц.
Пожалуйста, держите меня в курсе любых обновлений или исправлений, которые вы вносите в код, чтобы я мог интегрировать их в следующий выпуск. Спасибо! И не стесняйтесь задавать вопросы в списке рассылки или на дискуссионном форуме, если у вас возникнут какие-либо проблемы с программным обеспечением! Я уверен, что он далеко не идеален...
Архивы, содержащие файлы JAR, доступны в виде релизов. Бинарный архив содержит сборки для Android, iOS, Linux, Mac OS X и Windows. Файлы JAR для конкретных дочерних модулей или платформ также можно получить индивидуально из центрального репозитория Maven.
Чтобы установить файлы JAR вручную, следуйте инструкциям в разделе «Установка вручную» ниже.
Мы также можем загрузить и установить все автоматически с помощью:
pom.xml
) < dependency >
< groupId >org.bytedeco</ groupId >
< artifactId >javacv-platform</ artifactId >
< version >1.5.11</ version >
</ dependency >
build.gradle.kts
или build.gradle
) dependencies {
implementation( " org.bytedeco:javacv-platform:1.5.11 " )
}
project.clj
) :dependencies [
[org.bytedeco/javacv-platform " 1.5.11 " ]
]
build.sbt
) libraryDependencies += " org.bytedeco " % " javacv-platform " % " 1.5.11 "
При этом загружаются двоичные файлы для всех платформ, но чтобы получить двоичные файлы только для одной платформы, мы можем установить для системного свойства javacpp.platform
(с помощью параметра командной строки -D
) что-то вроде android-arm
, linux-x86_64
, macosx-x86_64
, windows-x86_64
и т. д. Подробности см. в файле README.md пресетов JavaCPP. Другой вариант, доступный пользователям Gradle, — Gradle JavaCPP, а для пользователей Scala — SBT-JavaCV.
Чтобы использовать JavaCV, вам сначала необходимо загрузить и установить следующее программное обеспечение:
Кроме того, хотя это и не всегда требуется, некоторые функции JavaCV также зависят от:
Наконец, убедитесь, что все имеет одинаковую разрядность: 32-битные и 64-битные модули ни при каких обстоятельствах не смешиваются .
Просто поместите все нужные файлы JAR ( opencv*.jar
, ffmpeg*.jar
и т. д.) в дополнение к javacpp.jar
и javacv.jar
где-нибудь в пути к классам. Вот несколько более конкретных инструкций для распространенных случаев:
NetBeans (Java SE 7 или новее):
Eclipse (Java SE 7 или новее):
Код Visual Studio (Java SE 7 или новее):
+
.IntelliJ IDEA (Android 7.0 или новее):
app/libs
.+
» и выберите «2 Зависимость файла».libs
.android:extractNativeLibs="true"
После этого классы-оболочки для OpenCV и FFmpeg, например, смогут автоматически получать доступ ко всем своим API C/C++:
Определения классов, по сути, являются портами исходных заголовочных файлов C/C++ на Java, и я сознательно решил сохранить как можно большую часть исходного синтаксиса. Например, вот метод, который пытается загрузить файл изображения, сгладить его и сохранить обратно на диск:
import org . bytedeco . opencv . opencv_core .*;
import org . bytedeco . opencv . opencv_imgproc .*;
import static org . bytedeco . opencv . global . opencv_core .*;
import static org . bytedeco . opencv . global . opencv_imgproc .*;
import static org . bytedeco . opencv . global . opencv_imgcodecs .*;
public class Smoother {
public static void smooth ( String filename ) {
Mat image = imread ( filename );
if ( image != null ) {
GaussianBlur ( image , image , new Size ( 3 , 3 ), 0 );
imwrite ( filename , 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 org . bytedeco . opencv . opencv_core .*;
import org . bytedeco . opencv . opencv_imgproc .*;
import org . bytedeco . opencv . opencv_calib3d .*;
import org . bytedeco . opencv . opencv_objdetect .*;
import static org . bytedeco . opencv . global . opencv_core .*;
import static org . bytedeco . opencv . global . opencv_imgproc .*;
import static org . bytedeco . opencv . global . opencv_calib3d .*;
import static org . bytedeco . opencv . global . 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/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_alt.xml" );
File file = Loader . cacheResource ( url );
classifierName = file . getAbsolutePath ();
}
// We can "cast" Pointer objects by instantiating a new object of the desired class.
CascadeClassifier classifier = new CascadeClassifier ( classifierName );
if ( classifier == null ) {
System . err . println ( "Error loading classifier file " " + classifierName + " " ." );
System . exit ( 1 );
}
// The available FrameGrabber classes include OpenCVFrameGrabber (opencv_videoio),
// DC1394FrameGrabber, FlyCapture2FrameGrabber, OpenKinectFrameGrabber, OpenKinect2FrameGrabber,
// RealSenseFrameGrabber, RealSense2FrameGrabber, 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, JavaFX, Tesseract, OpenCV, etc).
OpenCVFrameConverter . ToMat converter = new OpenCVFrameConverter . ToMat ();
// 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.
Mat grabbedImage = converter . convert ( grabber . grab ());
int height = grabbedImage . rows ();
int width = grabbedImage . cols ();
// Objects allocated with `new`, clone(), or a create*() factory method are automatically released
// by the garbage collector, but may still be explicitly released by calling deallocate().
// You shall NOT call cvReleaseImage(), cvReleaseMemStorage(), etc. on objects allocated this way.
Mat grayImage = new Mat ( height , width , CV_8UC1 );
Mat rotatedImage = grabbedImage . clone ();
// The OpenCVFrameRecorder class simply uses the VideoWriter 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...
Mat randomR = new Mat ( 3 , 3 , CV_64FC1 ),
randomAxis = new Mat ( 3 , 1 , CV_64FC1 );
// 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 );
Rodrigues ( randomAxis , randomR );
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.
Point hatPoints = new Point ( 3 );
while ( frame . isVisible () && ( grabbedImage = converter . convert ( grabber . grab ())) != null ) {
// Let's try to detect some faces! but we need a grayscale image...
cvtColor ( grabbedImage , grayImage , CV_BGR2GRAY );
RectVector faces = new RectVector ();
classifier . detectMultiScale ( grayImage , faces );
long total = faces . size ();
for ( long i = 0 ; i < total ; i ++) {
Rect r = faces . get ( i );
int x = r . x (), y = r . y (), w = r . width (), h = r . height ();
rectangle ( grabbedImage , new Point ( x , y ), new Point ( x + w , y + h ), Scalar . 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 );
fillConvexPoly ( grabbedImage , hatPoints . position ( 0 ), 3 , Scalar . GREEN , CV_AA , 0 );
}
// Let's find some contours! but first some thresholding...
threshold ( grayImage , grayImage , 64 , 255 , CV_THRESH_BINARY );
// To check if an output argument is null we may call either isNull() or equals(null).
MatVector contours = new MatVector ();
findContours ( grayImage , contours , CV_RETR_LIST , CV_CHAIN_APPROX_SIMPLE );
long n = contours . size ();
for ( long i = 0 ; i < n ; i ++) {
Mat contour = contours . get ( i );
Mat points = new Mat ();
approxPolyDP ( contour , points , arcLength ( contour , true ) * 0.02 , true );
drawContours ( grabbedImage , new MatVector ( points ), - 1 , Scalar . BLUE );
}
warpPerspective ( grabbedImage , rotatedImage , randomR , rotatedImage . size ());
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.5.11</ version >
< properties >
< maven .compiler.source>1.7</ maven .compiler.source>
< maven .compiler.target>1.7</ maven .compiler.target>
</ properties >
< dependencies >
< dependency >
< groupId >org.bytedeco</ groupId >
< artifactId >javacv-platform</ artifactId >
< version >1.5.11</ version >
</ dependency >
<!-- Additional dependencies required to use CUDA and cuDNN -->
< dependency >
< groupId >org.bytedeco</ groupId >
< artifactId >opencv-platform-gpu</ artifactId >
< version >4.10.0-1.5.11</ version >
</ dependency >
<!-- Optional GPL builds with (almost) everything enabled -->
< dependency >
< groupId >org.bytedeco</ groupId >
< artifactId >ffmpeg-platform-gpl</ artifactId >
< version >7.1-1.5.11</ version >
</ dependency >
</ dependencies >
< build >
< sourceDirectory >.</ sourceDirectory >
</ build >
</ project >
И, поместив приведенный выше исходный код в Demo.java
или аналогично для других классов, найденных в samples
, мы можем использовать следующую команду, чтобы все сначала было установлено автоматически, а затем выполнено Maven:
$ mvn compile exec:java -Dexec.mainClass=Demo
Примечание . В случае ошибок убедитесь, что в файле pom.xml
в качестве artifactId
указано значение javacv-platform
, а не только javacv
, например. Артефактная javacv-platform
добавляет все необходимые бинарные зависимости.
Если доступных выше двоичных файлов недостаточно для ваших нужд, возможно, вам придется пересобрать их из исходного кода. С этой целью файлы проекта были созданы для:
После установки просто вызовите обычную команду mvn install
для JavaCPP, его пресетов и JavaCV. По умолчанию никаких других зависимостей, кроме компилятора C++ для JavaCPP, не требуется. Для получения более подробной информации обратитесь к комментариям внутри файлов pom.xml
.
Вместо того, чтобы вручную собирать собственные библиотеки, мы можем запустить mvn install
только для JavaCV и полагаться на артефакты моментальных снимков из сборок CI:
Руководитель проекта: Сэмюэл Одет samuel.audet at
gmail.com
Сайт разработчика: https://github.com/bytedeco/javacv.
Группа обсуждения: http://groups.google.com/group/javacv.