OpenCV no Android: Acesso a câmera usando C
Esse tutorial é composto por duas partes, ambas partem do princípio que você já tenha seguido o tutorial Iniciando com OpenCV e Android Studio :
- Como utilizar um código nativo em OpenCV no Android Studio.
- Como capturar uma imagem da câmera e salvar na memória interna.
1. Como utilizar um código nativo em OpenCV no Android Studio
Configurando o Ambiente
Requisitos:
- Se não possuir a biblioteca do OpenCV para Android, faça o download no site.
- Faça o download do NDK no link.
Primeiramente devemos adicionar as ferramentas externas:
- javah: responsável por gerar os arquivos de cabeçalho .h a partir do arquivo .java
- ndk-build: responsável por compilar o código nativo.
Para adicionarmos as ferramentas, no Android Studio, devemos ir em Preferences->External Tools e adicionar a ferramenta externa javah, com as seguintes configurações:
- Program: /usr/bin/javah ou o caminho onde o binário javah se encontra em seu computador, se seu sistema operacional for unix digite which javah
- Parameters:
-v -jni -d $ModuleFileDir$/src/main/jni $FileClass$
- Working directory: $SourcepathEntry$
Para adicionarmos a ferramenta externa ndk-build, devemos ir em Preferences->External Tools, com as seguintes configurações:
- Program: /Users/user/android-ndk-r10e/ndk-build ou o caminho onde se encontra o ndk-build
- Parameters:
NDK_PROJECT_PATH=$ModuleFileDir$/build/intermediates/ndk NDK_LIBS_OUT=$ModuleFileDir$/src/main/jniLibs NDK_APPLICATION_MK=$ModuleFileDir$/src/main/jni/Application.mk APP_BUILD_SCRIPT=$ModuleFileDir$/src/main/jni/Android.mk V=1
- Working directory: $SourcepathEntry$
Na classe MainActivity.java devemos indicar o nome das bibliotecas que serão geradas através da compilação do código nativo para que elas sejam carregadas. Para isso devemos adicionar este trecho de código na classe MainActivity.java:
public class MainActivity extends AppCompatActivity implements CvCameraViewListener2, View.OnClickListener { //... static { //O nome da biblioteca corresponde ao nome definido no arquivo Android.mk, que será visto posteriormente System.loadLibrary("NdkLib"); System.loadLibrary("opencv_java3"); } //o nome da função é definido pelo programador public native int grayOpenCV(long matRgba, long matGray); //... }
Ao clicar com o botão direito na classe MainActivity.java, deverão aparecer as ferramentas que adicionamos anteriormente. Clique em javah para que seja criado o diretório jni e gerado o arquivo de cabeçalho, nesse exemplo, com_example_giovaniromani_tutorialopencv_MainActivity.h em /src/main /jni:
Uma vez criado o diretório /src/main/jni, devemos adicionar três arquivos, dois responsáveis pela compilação e um contendo o código nativo que queremos utilizar, são eles: Android.mk, Application.mk e nativeCodeSobel.cpp
Criando e Editando os Arquivos de Configuração para a Compilação do Código Nativo
Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) #diretorio onde se encontra o sdk do OpenCV em seu computador OPENCVROOT:= /Users/user/OpenCV-android-sdk OPENCV_CAMERA_MODULES:=on OPENCV_INSTALL_MODULES:=on OPENCV_LIB_TYPE:=SHARED include ${OPENCVROOT}/sdk/native/jni/OpenCV.mk #arquivo contendo o código nativo LOCAL_SRC_FILES := nativeCodeSobel.cpp LOCAL_LDLIBS += -llog LOCAL_MODULE := NdkLib include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions APP_ABI := armeabi-v7a x86 APP_PLATFORM := android-16
nativeCodeGray.cpp
Neste arquivo se encontram as instruções que desejamos utilizar em código nativo.
#include "nativeCodeGray.h" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <stdlib.h> #include <stdio.h> #include <nativeCodeGray.h> //Atencao ao nome da biblioteca, ele deverá ser igual ao arquivo contido no diretório ///src/main/libs #include <com_example_giovaniromani_tutorialopencv_MainActivity.h> using namespace cv; /** @function main */ //Atenção ao nome do método, ele deverá ser igual ao nome contido no //com_example_giovaniromani_tutorialopencv_MainActivity.h JNIEXPORT jint JNICALL Java_com_example_giovaniromani_tutorialopencv_MainActivity_grayOpenCV (JNIEnv *, jobject, jlong matRgba, jlong matGray) { Mat &rgba = *(Mat *) matRgba; Mat &gray = *(Mat *) matGray; cvtColor(rgba, gray, CV_BGR2GRAY); }
Logo, teremos 5 arquivos no diretório src/main/jni.
No arquivo build.gradle do app devemos adicionar o seguinte trecho de código:
//... android{ //... sourceSets.main { jni.srcDirs = [] //desabilita chamada automática ao ndk-build } //Será necessário verificar e atualizar o caminho para o ndk-build task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') { commandLine "/Users/giovaniromani/MEGA/CodigoFonte/android-ndk-r10e/ndk-build", 'NDK_PROJECT_PATH=build/intermediates/ndk', 'NDK_LIBS_OUT=src/main/jniLibs', 'APP_BUILD_SCRIPT=src/main/jni/Android.mk', 'NDK_APPLICATION_MK=src/main/jni/Application.mk' } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild } } //....
Utilizando o Código Nativo
Por fim, para que seja exibida a imagem, devemos chamar o método passando como parâmetro duas matrizes:
@Override public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { Mat rgba = inputFrame.rgba(); Mat gray = new Mat(); grayOpenCV(rgba.getNativeObjAddr(), gray.getNativeObjAddr()); //retorna o objeto Mat que está em escala de cinza ao View para que seja exibida na tela return gray; }
2. Como capturar uma imagem da câmera e salvar na memória interna
Implementando o tratamento do evento OnClick
Devemos, inicialmente, implementar a interface View.OnClickListener, ela será responsável por obter e tratar o evento, que no nosso caso, será um toque na tela:
public class MainActivity extends AppCompatActivity implements CvCameraViewListener2, View.OnClickListener {
Você notará que a assinatura estará sublinhada de vermelho, isso acontece porque devemos, obrigatoriamente, sobrescrever o método OnClick.
@Override public void onClick(View v) { }
Para que a View possa capturar o evento, temos que ativar o seu listener, assim, devemos colocar a seguinte linha de código no método OnCreate da classe MainActivity:
mOpenCvCameraView.setOnClickListener(this);
Salvando a Imagem
Será necessário criar um atributo do tipo Mat que armazenará a imagem em escala de cinza, conforme nosso objetivo. Dessa forma teremos a declaração do atributo no início da classe e atribuiremos o objeto gray do tipo Mat ao atributo matGray dentro do método OnCameraFrame, conforme código abaixo:
public class MainActivity extends AppCompatActivity implements CvCameraViewListener2, View.OnClickListener { //... private Mat matGray; //... @Override public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { Mat rgba = inputFrame.rgba(); Mat gray = new Mat(); grayOpenCV(rgba.getNativeObjAddr(), gray.getNativeObjAddr()); matGray=gray; return gray; } //... }
Para que a imagem seja salva ao clicarmos na tela, devemos inserir as seguintes linhas de código no método OnClick:
@Override public void onClick(View v) { //Armazena uma cópia da matriz matGray na matriz src Mat src = matGray.clone(); //Realiza a cnoversão de Mat para Bitmap Bitmap bitmap = Bitmap.createBitmap(src.cols(), src.rows(), Bitmap.Config.ARGB_8888); Utils.matToBitmap(src, bitmap); ContentValues contentValues = new ContentValues(); Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); OutputStream outputStream; try { //Salva a imagem outputStream = getContentResolver().openOutputStream(uri); boolean compressed = bitmap.compress(Bitmap.CompressFormat.PNG, 0, outputStream); outputStream.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
Atenção
O Aplicativo deve ter permissão para pode acessar a memória externa do aparelho, para isso, devemos inserir as seguintes linhas no arquivo AndroidManifest.xml
[sourcecode language=”xml”]
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
[/sourcecode]
Para mais detalhes, o código está disponível no GitHub.
Referência:
[1] http://hujiaweibujidao.github.io/blog/2014/10/22/android-ndk-and-opencv-development-with-android-studio/


Boa noite,
copiei e colei o código logo abaixo da mensagem:
” No arquivo build.gradle do app devemos adicionar o seguinte trecho de código:”
Verifiquei o caminho para ndk-build e mesmo assim ocorre um erro no programa. Poderia me ajudar?
Grato.
Boa noite André,
há um problema de formatação no código.
A linha
compileTask – & g t; compileTask.dependsOn ndkBuild
deverá ser substituída por
compileTask -> compileTask.dependsOn ndkBuild
Caso tenha dúvidas sobre o código, ele está disponível no GitHub.
Se o problema persistir, nos comunique novamente indicando o erro.
Boa tarde,
o erro ainda continua, aparece a seguinte mensagem.
Error:Execution failed for task ‘:app:ndkBuild’.
> A problem occurred starting process ‘command ‘/C:/Users/andre/Downloads/android-ndk-r10e/ndk-build”
Boa tarde.
Tem algum desenvolvedor para um aplicativo android que interligue a captura de imagens do celular( OPENCV/TESSERAT… ) com um banco de dados e o sinesp cidadão. Seria usado embarcado em um veiculo visando o combate de ilícitos penais.
Aguardo maiores informações.
Obrigado.
rb.moc.liamgnull@livadlaicilop
Olá pessoal. Alguém consegue montar programar um aplicativo para android utilizando a tecnologia para obter placas de veículos e pesquisar no Senasp cidadão?
Caso afirmativo entre em contato no email moc.liamgnull@alivadlaicilop
Ei lá só queria dar-lhe um rápida heads-սp e qսe você saiba aⅼguns do imagens não estão carregando corretamente.
Nã᧐ sei porquê, mas еu acho qᥙe é սma գuestão dе
vinculaçãߋ. Já tentei em dois diferentes navegadores internet е ambos mostram a mesma resultado.