Suporte comercial:
JavaCV usa wrappers das predefinições JavaCPP de bibliotecas comumente usadas por pesquisadores no campo da visão computacional (OpenCV, FFmpeg, libdc1394, FlyCapture, Spinnaker, OpenKinect, librealsense, CL PS3 Eye Driver, videoInput, ARToolKitPlus, flandmark, Leptonica e Tesseract) e fornece classes utilitárias para facilitar o uso de suas funcionalidades na plataforma Java, incluindo Android.
JavaCV também vem com exibição de imagem em tela cheia acelerada por hardware ( CanvasFrame
e GLCanvasFrame
), métodos fáceis de usar para executar código em paralelo em vários núcleos ( Parallel
), calibração geométrica e de cores fácil de usar de câmeras e projetores ( GeometricCalibrator
, ProCamGeometricCalibrator
, ProCamColorCalibrator
), detecção e correspondência de pontos característicos ( ObjectFinder
), um conjunto de classes que implementam o alinhamento direto de imagem de sistemas projetor-câmera (principalmente GNImageAligner
, ProjectiveTransformer
, ProjectiveColorTransformer
, ProCamTransformer
e ReflectanceInitializer
), um pacote de análise de blob ( Blobs
), bem como funcionalidades diversas na classe JavaCV
. Algumas dessas classes também possuem uma contraparte OpenCL e OpenGL, seus nomes terminando com CL
ou começando com GL
, ou seja: JavaCVCL
, GLCanvasFrame
, etc.
Para saber como usar a API, já que atualmente falta documentação, consulte a seção Exemplo de uso abaixo, bem como os programas de exemplo, incluindo dois para Android ( FacePreview.java
e RecordActivity.java
), também encontrados no diretório samples
. Você também pode achar útil consultar o código-fonte do ProCamCalib e ProCamTracker, bem como exemplos portados do OpenCV2 Cookbook e das páginas wiki associadas.
Por favor, mantenha-me informado sobre quaisquer atualizações ou correções feitas no código para que eu possa integrá-las na próxima versão. Obrigado! E fique à vontade para fazer perguntas na lista de discussão ou no fórum de discussão se encontrar algum problema com o software! Tenho certeza que está longe de ser perfeito...
Arquivos contendo arquivos JAR estão disponíveis como versões. O arquivo binário contém compilações para Android, iOS, Linux, Mac OS X e Windows. Os arquivos JAR para módulos ou plataformas filho específicos também podem ser obtidos individualmente no Maven Central Repository.
Para instalar manualmente os arquivos JAR, siga as instruções na seção Instalação Manual abaixo.
Também podemos baixar e instalar tudo automaticamente com:
pom.xml
) < dependency >
< groupId >org.bytedeco</ groupId >
< artifactId >javacv-platform</ artifactId >
< version >1.5.11</ version >
</ dependency >
build.gradle.kts
ou 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 "
Isso baixa binários para todas as plataformas, mas para obter binários para apenas uma plataforma, podemos definir a propriedade do sistema javacpp.platform
(por meio da opção de linha de comando -D
) para algo como android-arm
, linux-x86_64
, macosx-x86_64
, windows-x86_64
, etc. Consulte o arquivo README.md das predefinições JavaCPP para obter detalhes. Outra opção disponível para usuários do Gradle é o Gradle JavaCPP e, da mesma forma, para usuários do Scala existe o SBT-JavaCV.
Para usar JavaCV, primeiro você precisa baixar e instalar o seguinte software:
Além disso, embora nem sempre seja obrigatório, algumas funcionalidades do JavaCV também dependem de:
Por fim, certifique-se de que tudo tenha o mesmo número de bits: módulos de 32 e 64 bits não se misturam em nenhuma circunstância .
Basta colocar todos os arquivos JAR desejados ( opencv*.jar
, ffmpeg*.jar
, etc.), além de javacpp.jar
e javacv.jar
, em algum lugar do seu caminho de classe. Aqui estão algumas instruções mais específicas para casos comuns:
NetBeans (Java SE 7 ou mais recente):
Eclipse (Java SE 7 ou mais recente):
Código do Visual Studio (Java SE 7 ou mais recente):
+
.IntelliJ IDEA (Android 7.0 ou mais recente):
app/libs
.+
e selecione "2 Dependência de arquivo".libs
.android:extractNativeLibs="true"
Depois disso, as classes wrapper para OpenCV e FFmpeg, por exemplo, podem acessar automaticamente todas as suas APIs C/C++:
As definições de classe são basicamente portas para Java dos arquivos de cabeçalho originais em C/C++, e decidi deliberadamente manter o máximo possível da sintaxe original. Por exemplo, aqui está um método que tenta carregar um arquivo de imagem, suavizá-lo e salvá-lo de volta no disco:
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 também vem com classes e métodos auxiliares além de OpenCV e FFmpeg para facilitar sua integração à plataforma Java. Aqui está um pequeno programa de demonstração demonstrando as partes úteis com mais frequência:
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 ();
}
}
Além disso, após criar um arquivo pom.xml
com o seguinte conteúdo:
< 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 >
E colocando o código fonte acima em Demo.java
, ou similarmente para outras classes encontradas nos samples
, podemos usar o seguinte comando para ter tudo primeiro instalado automaticamente e depois executado pelo Maven:
$ mvn compile exec:java -Dexec.mainClass=Demo
Nota : Em caso de erros, certifique-se de que o artifactId
no arquivo pom.xml
seja javacv-platform
, não apenas javacv
, por exemplo. O artefato javacv-platform
adiciona todas as dependências binárias necessárias.
Se os arquivos binários disponíveis acima não forem suficientes para suas necessidades, talvez seja necessário reconstruí-los a partir do código-fonte. Para tanto, foram criados os arquivos do projeto para:
Uma vez instalado, basta chamar o comando mvn install
usual para JavaCPP, seus Presets e JavaCV. Por padrão, nenhuma outra dependência além de um compilador C++ para JavaCPP é necessária. Consulte os comentários dentro dos arquivos pom.xml
para obter mais detalhes.
Em vez de construir as bibliotecas nativas manualmente, podemos executar mvn install
apenas para JavaCV e contar com os artefatos de snapshot das compilações de CI:
Líder do projeto: Samuel Audet samuel.audet at
gmail.com
Site do desenvolvedor: https://github.com/bytedeco/javacv
Grupo de discussão: http://groups.google.com/group/javacv