I am learning OpenCV library and want to develop a face recognization app, to do so I started with the integration of NDK with the android studio but I am stuck here in between.
I am able to successfully print the text message from cpp to activity in the Android framework
// Cpp Code
extern "C"
JNIEXPORT jstring JNICALL
Java_com_detectface_tasolmyfacerec_utils_Opencv_toastCPPNative(JNIEnv *env, jobject instance) {
std::string hello = "OpenCV FaceDetection";
return env->NewStringUTF(hello.c_str());
}
//Java Code
public native String toastCPPNative();
But when started adding the cpp supported headers they are not included and showing red highlight text, I want to include that files so that I can use the opencv algorithms
#include <opencv2/core.hpp>
CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
facedetection-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/facedetection-lib.cpp )
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
I am providing the screenshots also
Related
I am working on Android native project using C++ code built using CMake. Currently my app is running fine and native lib(.so) is successfully loaded using System.loadLibrary().
But I want to test JUnit tests on my mac in Android Studio. When running tests on mac, It throws error
myapp.dylib not found.
Here is my CMakeLists.txt :
cmake_minimum_required(VERSION 3.18.1)
# Declares and names the project.
project("myapplication")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
add_library( # Sets the name of the library.
myapplication
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp
native2.cpp)
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
Here is my cpp file:
#include <jni.h>
#include <string>
#include "header.h"
#include<android/log.h>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
return env->NewStringUTF(hello.c_str());
}
To build .dylib when running cmake from command line, I get other errors like jni not found and liblog(android log library) not found.
Is there a way that I can build .dylib for mac OS in such a way that it can resolve android specific dependencies like jni and log library?
I'm trying to use Google Oboe from my Android NDK application.
When I try to use oboe::AudioStreamBuilder from native-lib.cpp all is working fine.
But when I try to use oboe::AudioStreamBuilder from a class then I get the error message "error: undefined reference to 'oboe::AudioStreamBuilder::openStream(oboe::AudioStream**)'" when I rebuild the project.
Here is native-lib.cpp that is ok :
#include <jni.h>
#include <string>
#include <android/log.h>
#include "OboeAudioRecorder.h"
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_oboeaudiorecorder_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_example_oboeaudiorecorder_MainActivity_recordAudio(
JNIEnv * env,
jobject MainActivity
) {
oboe::AudioStreamBuilder builder;
builder.setDirection(oboe::Direction::Input);
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);
builder.setDeviceId(0);
oboe::AudioStream *stream;
oboe::Result r = builder.openStream(&stream);
if (r != oboe::Result::OK) {
return false;
}
return true;
}
And here is the class that cannot compile :
#include <oboe/Oboe.h>
#include <oboe/AudioStreamBuilder.h>
#include "OboeAudioRecorder.h"
OboeAudioRecorder::OboeAudioRecorder() {
oboe::AudioStreamBuilder builder;
builder.setDirection(oboe::Direction::Input);
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);
builder.setDeviceId(0);
oboe::AudioStream *stream;
oboe::Result r = builder.openStream(&stream);
if (r != oboe::Result::OK) {
return;
}
}
The CMakeLists.txt file :
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# <Begin> OBOE SPECIFIC
# Set the path to the Oboe directory.
set (OBOE_DIR "../../../../../oboe")
# Add the Oboe library as a subdirectory in your project.
# add_subdirectory tells CMake to look in this directory to
# compile oboe source files using oboe's CMake file.
# ./oboe specifies where the compiled binaries will be stored
add_subdirectory (${OBOE_DIR} ./oboe)
# Specify the path to the Oboe header files.
# This allows targets compiled with this CMake (application code)
# to see public Oboe headers, in order to access its API.
include_directories (${OBOE_DIR}/include)
# <End> OBOE SPECIFIC
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp )
add_library(
OboeAudioRecorder
SHARED
OboeAudioRecorder.cpp
)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib oboe OboeAudioRecorder
# Links the target library to the log library
# included in the NDK.
${log-lib} )
In your CMakeLists.txt change:
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp )
to
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp
OboeAudioRecorder.cpp
)
And remove all other references to OboeAudioRecorder.
Why does this work?
With the following lines you're attempting to build another library called OboeAudioRecorder:
add_library(
OboeAudioRecorder
SHARED
OboeAudioRecorder.cpp
)
This library is dependent on oboe but you don't specify that anywhere, you only specify the dependencies for the native-lib library:
target_link_libraries( # Specifies the target library.
native-lib oboe OboeAudioRecorder
# Links the target library to the log library
# included in the NDK.
${log-lib} )
That's why you get error: undefined reference when linking the OboeAudioRecorder library.
You could add a 2nd target_link_libraries(OboeAudioRecorder oboe) line but my guess is you don't want 2 separate libraries, you just want a single library which is dependent on oboe.
I am integrating Ceres Solver Library in my Android Application. I have created the prebuilt shared library (.so files) for all the architecture using CMakeLists.txt in Android Studio. Now I want to implement the Bundle adjustment in Java/Kotlin with OpenCV java wrappers.
To consume Ceres Solver in Android application we have to write the ceres solver logic in C++ using .so file and header files of the Ceres Solver and its dependency libraries. Then we have to write the wrappers to our own methods to consume in Java / Kotlin.
For this I am using the following CMakeLists.txt file
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp )
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
include_directories( C:/eigen-eigen-323c052e1731 )
include_directories( C:/My_Data/Ceres-Solver-Builder/ceres-solver/include )
include_directories( C:/My_Data/Ceres-Solver-Builder/ceres-solver/config )
include_directories( C:/My_Data/Ceres-Solver-Builder/ceres-solver/internal/ceres/miniglog )
include_directories( C:/My_Data/Ceres-Solver-Builder/ceres-solver/internal )
add_library( ceres-lib SHARED IMPORTED)
set_target_properties( # Specifies the target library.
ceres-lib
# Specifies the parameter you want to define.
PROPERTIES IMPORTED_LOCATION
# Provides the path to the library you want to import.
C:/My_Data/AS_Workspace/JNIApplication/app/src/main/jniLibs/${ANDROID_ABI}/libceres.so )
target_link_libraries( native-lib ceres-lib ${log-lib})
Sample C++ file that uses Ceres Solver classes and methods native-lib.cpp
#include <jni.h>
#include <string>
#include <bitset>
#include "ceres/ceres.h"
#include "glog/logging.h"
using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solver;
using ceres::Solve;
int test();
extern "C" JNIEXPORT jstring JNICALL
Java_com_trimble_jniapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
test();
return env->NewStringUTF(hello.c_str());
}
// A templated cost functor that implements the residual r = 10 -
// x. The method operator() is templated so that we can then use an
// automatic differentiation wrapper around it to generate its
// derivatives.
struct CostFunctor {
template<typename T>
bool operator()(const T *const x, T *residual) const {
residual[0] = 10.0 - x[0];
return true;
}
};
int test() {
//google::InitGoogleLogging(argv[0]);
// The variable to solve for with its initial value. It will be
// mutated in place by the solver.
double x = 0.5;
const double initial_x = x;
// Build the problem.
Problem problem;
// Set up the only cost function (also known as residual). This uses
// auto-differentiation to obtain the derivative (jacobian).
CostFunction *cost_function = new AutoDiffCostFunction<CostFunctor, 1, 1>(new CostFunctor);
problem.AddResidualBlock(cost_function, NULL, &x);
// Run the solver!
Solver::Options options;
options.minimizer_progress_to_stdout = true;
Solver::Summary summary;
Solve(options, &problem, &summary);
std::cout << summary.BriefReport() << "\n";
std::cout << "x : " << initial_x
<< " -> " << x << "\n";
return 0;
}
When I build the application I am getting the following error.
error One of CERES_USE_OPENMP, CERES_USE_CXX11_THREADS or CERES_NO_THREADS must be defined.
I am new to NDK, Cmake, and Ceres Solver, So I don't know how to fix this problem. Someone please suggest me how to fix the problem or point me what I am doing wrong. Thanks in advance.
As commented, you need to define at least one of these preprocessor definitions when using Ceres (see logic here). You can add definitions to the compilation with CMake using target_compile_definitions():
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp )
target_compile_definitions(native-lib PRIVATE CERES_USE_CXX11_THREADS=1)
...
I am developing an Android application that involves some image processing. I am now stitching images using OpenCV. I am doing it in c++. So, I integrated the OpenCV (both native c++ and Java) into my Android project. But when I use the stitching features in c++ and run my project, it is giving me the compilation error.
This is my whole c++ library (native-lib) for stitching images.
//
// Created by Acer on 3/28/2018.
//
#include <jni.h>
#include <string>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <iostream>
#include <fstream>
#include <opencv2/stitching.hpp>
using namespace std;
using namespace cv;
extern "C" {
jstring
Java_media_memento_memento_SphereCameraActivity_stitchPhotos(
JNIEnv *env,
jobject /* this */, jlong addrMat, jlong addrNewMat, jlongArray addrsPreviews) {
Mat &in = *(Mat *) addrMat;
Mat &newMat = *(Mat *) addrNewMat;
int size = env->GetArrayLength(addrsPreviews);
jlong *addrPreviewArray = env->GetLongArrayElements(addrsPreviews, NULL);
vector<Mat> imgs(size);
for (long i = 0; i < size; i++) {
jlong previewAddress = addrPreviewArray[i];
imgs[i] = *(Mat *) previewAddress;
}
bool try_use_gpu = false;
Mat pano;
Stitcher stitcher = Stitcher::createDefault(try_use_gpu);
Stitcher::Status status = stitcher.stitch(imgs, pano);
if (status != Stitcher::OK) {
//the return map would be null
} else {
//copy the map.
pano.copyTo(newMat);
newMat = pano;
}
env->ReleaseLongArrayElements(addrsPreviews, addrPreviewArray, 0);
}
}
This is my CMakeList.txt file
set(pathToProject C:/Users/iljim/Desktop/memento/memento-android)
set(pathToOpenCv C:/Users/iljim/Desktop/OpenCV-3.1.0-android-sdk/OpenCV-android-sdk)
# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
include_directories(C:/Users/iljim/Desktop/OpenCV-3.1.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/include)
# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add_library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.
add_library( # Specifies the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
add_library( # Specifies the name of the library.
cubemap
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/cubemap.cpp )
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# OpenCV lib
lib_opencv
# Cubemap lib
cubemap
# Links the target library to the log library
# included in the NDK.
${log-lib} )
When I run, I got the mentioned error.
Error:error: linker command failed with exit code 1 (use -v to see invocation)
Error:(49) undefined reference to 'cv::Stitcher::createDefault(bool)'
Error:(50) undefined reference to 'cv::Stitcher::stitch(cv::_InputArray const&, cv::_OutputArray const&)'
I found this link - undefined reference to `cv::Stitcher::createDefault(bool)'. But I believe I integrated the c++ opencv native lib properly. That is why I can use other libraries. When I check the file in the SDK folder, the stitching.hpp exists. So, what might be possible and how can I solve it?
I had a quite similar problem and solved it with linking "libopencv_stitching.a" static library from OpenCV SDK in my CMakeLists.txt file.
file(GLOB CVLIBS
path/to/your/opencv/sdk/staticlibs/${ANDROID_ABI}/libopencv_stitching.a)
...
target_link_libraries( # Specifies the target library.
...
${CVLIBS}
# Links the target library to the log library
# included in the NDK.
${log-lib})
Also this answer can be useful as well: Building OpenCV for Android and using it with the NDK
I am developing an Android application that involves some image processing. I am using Open CV. I integrated the open CV adding new module for Java and integrated for the native c++ as well. I can use the library in Java with no issues. But in C++, I am having some issues. Please see the code below.
//
// Created by iljim on 03/04/2018.
//
#include <jni.h>
#include <string>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
using namespace std;
using namespace cv;
extern "C"
JNIEXPORT jstring
JNICALL
Java_media_memento_memento_VRPhotoSphereActivity_convertEquiRectToCubeMap(
JNIEnv *env,
jobject /* this */, jlong addrMat, jlong addrNewMat) {
Mat& in = *(Mat*)addrMat;
Mat& face = *(Mat*)addrNewMat;
float faceTransform[6][2] =
{
{0, 0},
{M_PI / 2, 0},
{M_PI, 0},
{-M_PI / 2, 0},
{0, -M_PI / 2},
{0, M_PI / 2}
};
int faceId = 0;
int width = -1;
int height = -1;
float inWidth = in.cols;
float inHeight = in.rows;
// Allocate map
Mat mapx(height, width, CV_32F); //Please pay attention to this line.
}
In the above code, pay attention to the the line, "Mat mapx(height, width, CV_32F);". When I am writing code, I got no error. I can use Mat of OpenCV c++ library and import the required libraries as well. As you can see below. No error.
The problem is when I run my app, it is giving me compilation error in the logcat because of the line I highlighted.
This is the error.
Information:Gradle tasks [:app:assembleDebug]
C:\Users\iljim\Desktop\OpenCV-3.1.0-android-sdk\OpenCV-android-sdk\sdk\native\jni\include\opencv2\core\mat.inl.hpp
Error:(571) undefined reference to 'cv::fastFree(void*)'
Error:(663) undefined reference to 'cv::Mat::create(int, int const*, int)'
Error:(682) undefined reference to 'cv::Mat::deallocate()'
Error:error: linker command failed with exit code 1 (use -v to see invocation)
C:\Users\iljim\Desktop\memento\memento-android\app\src\main\cpp\cubemap.cpp
Warning:(280, 1) warning: control reaches end of non-void function [-Wreturn-type]
Warning:(280, 1) warning: control reaches end of non-void function [-Wreturn-type]
This is the screenshot
I believe I integrated the OpenCV for c++ correctly that is why it is not giving me any error when I was typing in some code that using features of OpenCV and was able to import the OpenCV libraries.
This is my CMakeList file
# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.
cmake_minimum_required(VERSION 3.4.1)
include_directories(C:/Users/iljim/Desktop/OpenCV-3.1.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/include)
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)
# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add_library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.
add_library( # Specifies the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
add_library( # Specifies the name of the library.
cubemap
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/cubemap.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# OpenCV lib
lib_opencv
# Cubemap lib
cubemap
# Links the target library to the log library
# included in the NDK.
${log-lib} )
What is wrong with my code? What might be the possible error? How can I fix it?