Monday, January 9, 2045

Bruce Lee: Be Water, My Friend

Lyrics:
 It is like a finger pointing away to the moon.
Don't concentrate on the finger,
or you will miss all that heavenly glory.

Empty your mind
Be formless, shapeless
Like Water
Water can flow
Or it can crash

Be water my friend
Running water never goes stale
So you gotta just keep on flowing

You have to train
You have to keep your reflexes
So that when you want it, it's there

When you want to move, you're moving
I mean you gotta put the whole hip into it
Snap it, snap it Become one with the *
You better train every part of your body

Running water never goes stale
So you gotta just keep on flowing

Under the sky Under the heaven
There is but one family
Do not believe in styles
Styles separate man
It's a process of continuing growth 

Mp3 file

Saturday, June 3, 2017

Building lightgbm in Mac Sierra

In order to build lightgbm in OSX Sierra, you might have to follow the steps provided by MS github
--
LightGBM depends on OpenMP for compiling, which isn't supported by Apple Clang.
Please use gcc/g++ instead.
Run following:
brew install cmake
brew install gcc --without-multilib
git clone --recursive https://github.com/Microsoft/LightGBM ; cd LightGBM
mkdir build ; cd build
cmake ..  ## cause errors
make -j 
ERRORs:  you might have errors as below caused by cmake.

-- The C compiler identification is unknown
-- The CXX compiler identification is unknown
CMake Error at CMakeLists.txt:8 (PROJECT):
  The CMAKE_C_COMPILER:

    gcc-7

  is not a full path and was not found in the PATH.

  Tell CMake where to find the compiler by setting either the environment
  variable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path to
  the compiler, or to the compiler name if it is in the PATH.


CMake Error at CMakeLists.txt:8 (PROJECT):
  The CMAKE_CXX_COMPILER:

    g++-7

  is not a full path and was not found in the PATH.

  Tell CMake where to find the compiler by setting either the environment
  variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
  to the compiler, or to the compiler name if it is in the PATH.


-- Configuring incomplete, errors occurred!
See also "/Users/xiezhen/Downloads/LightGBM/build/CMakeFiles/CMakeOutput.log".
See also "/Users/xiezhen/Downloads/LightGBM/build/CMakeFiles/CMakeError.log".



Solution:
Add the following code to after the second line of CMakeLists.txt in the folder of LightGBM. 

SET(MACOSX_DEPLOYMENT_TARGET ${DARWIN_MAJOR_SDK_VERSION}.${DARWIN_MINOR_SDK_VERSION})
SET(CMAKE_CXX_FLAGS "--sysroot ${CMAKE_OSX_SYSROOT} ${CMAKE_CXX_FLAGS}")

MESSAGE("Setting MACOSX_DEPLOYMENT_TARGET to '${MACOSX_DEPLOYMENT_TARGET}'.")

Thursday, May 11, 2017

Calling OpenCV2.4 APIs in AOSP

Here is a sample of calling OpenCV2.4 static library we have discussed in the other blog.
This sample is also compiled by NDS as an external package, which locates, for example, external/pprotector.

The directory tree is as follows and we called OpenCV2.4 APIs in privacy_detect.cpp. 

.
|-- Android.mk
|-- ImageUtils.h
|-- ImageUtils_0.7.cpp
|-- detectObject.cpp
|-- detectObject.h
|-- haarcascades
|   |-- faces.jpeg
|   |-- fist.xml
|   |-- haarcascade_eye.xml
|   |-- haarcascade_eye_tree_eyeglasses.xml
|   |-- haarcascade_frontalface_alt2.xml
|   |-- haarcascade_profileface.xml
|   |-- haarcascade_smile.xml
|   |-- lbpcascade_frontalface.xml
|   |-- palm.xml
|-- preprocessFace.cpp
|-- preprocessFace.h
|-- privacy_detect.cpp
|-- privacy_detect.h
|-- recognition.cpp

`-- recognition.h

As the compilation of OpenCV2.4 to AOSP, the big part is how to set up the NDK compiling configuration, which is Android.mk. Please note that the value of LOCAL_STATIC_LIBRARIES  includes the static library of OpenCV2.4 (i.e., libopencv24and other built-in static libraries with OpenCV 2.4 SDK.


Here is the content of my Android.mk :

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE     := libpprotector24
LOCAL_SRC_FILES  := privacy_detect.cpp detectObject.cpp ImageUtils_0.7.cpp preprocessFace.cpp recognition.cpp

LOCAL_STATIC_LIBRARIES += libopencv24 opencv_contrib  opencv_legacy  opencv_stitching  opencv_superres  opencv_ocl opencv_objdetect  opencv_ml  opencv_ts  opencv_videostab  opencv_video  opencv_photo  opencv_calib3d  opencv_features2d  opencv_highgui  opencv_imgproc  opencv_flann opencv_androidcamera  opencv_core tbb libjpeg libpng libtiff libjasper IlmImf


LOCAL_CFLAGS := -Wall -Wextra -Wno-error=non-virtual-dtor -Werror=return-type -std=c++11 -frtti -fexceptions
LOCAL_LDLIBS := prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/libgnustl_static.a -lc  -llog  -lm  -ldl  -lz

Compiling Opencv 2.4 for AOSP 5.1 using built-in NDK

I have tried to include OpenCV 2.4 to AOSP as a third party library, so that we can use OpenCV dealing with images in the kernel.  The idea is to copy the source code of OpenCV2.4 for Android directly to the AOSP as an external package and then call the built-in NDK to compile it to a static library. Then, codes in the kernel can directly import this library and call APIs.

Here I show you how to do this step by step.

STEP 1: Download OpenCV4Android SDK. Here is a link to SDK.
.
|-- etc
|   |-- haarcascades
|   |-- lbpcascades
|-- java
|   |-- assets
|   |-- bin
|   |-- gen
|   |-- javadoc
|   |-- res
|   |-- src
|-- native
    |-- 3rdparty
    |-- jni

    |-- libs

STEP 2: Create a directory under AOSP external folder. For example, I have create a folder named opencv24 in /Volumes/android/external/opencv24

STEP 3: Copy the native folder in the OpenCV4Android SDK to the folder you created in STEP 2.
Here is my directory tree. Specifically, I also copied the folder of haarcascades under etc/ in OpenCV4Android SDK to opencv24/.
.
|-- haarcascade
|-- native
    |-- 3rdparty
    | -- libs
    |-- jni
    | -- include
    |-- libs
        |-- armeabi
        |-- armeabi-v7a
        |-- mips

        |-- x86


STEP 4: Create an Android.mk file in the folder your created, e.g., opencv24/

The biggest challenge is to set up the configuration of NDK and then compile OpenCV 2.4 package correctly. The following a few steps are to introduce the main part in Android.mk.


1. Link gnustl_static
In NDK for app development like my other blog, we must define APP_STL := gnustl_static in Application.mk. However, while compiling Opencv 2.4 for AOSP, we must link gnustl_static in Android.mk. Even though the grammar of NDK looks similar for app development and AOSP compilation, they are actually different. Therefore, we must be able to fulfill APP_STL := gnustl_static in AOSP compilation following the discussion.

In your Android.mk

LOCAL_NDK_STL_VARIANT := gnustl_static
NDK_ROOT :=prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.9
LOCAL_C_INCLUDES := $(NDK_ROOT)/include
LOCAL_C_INCLUDES += $(NDK_ROOT)/libs/armeabi-v7a/include

#add the following line after the last LOCAL_LDLIBS
LOCAL_LDLIBS += $(NDK_ROOT)/libs/armeabi-v7a/libgnustl_static.a

2. In the last step, we use the ndk 9 for our compilation. However, it will cause a problem:

prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include/bits/ctype_base.h:67:32: error: '_CTYPE_N' was not declared in this scope

     static const mask digit  = _N;

The problem of ctype_bash.h in ndk has been lasted for a very long time.  In this discussion, they reported similar problem in ndk 6. In ndk 9, they resolved most of the problem, but left _CTYPE_N unresolved. Fortunately, some one in the discussion posted a patch file which we can use. My solution is to add a line of code (this code is from the patch file) to the ctype_base.h we are using.

Add
#define _CTYPE_N        0x04
to the file 
prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include/bits/ctype_base.h

3. When meeting the following problem, add a line LOCAL_CFLAGS += -Wno-error=non-virtual-dtor to your Android.mk. It will convert this error to warning.

core.hpp:1337:18: error: 'class cv::_InputArray' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
 class CV_EXPORTS _InputArray

Here is the content of my Android.mk :
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=STATIC

#link gnustl
LOCAL_NDK_STL_VARIANT := gnustl_static
NDK_ROOT :=prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.9
LOCAL_C_INCLUDES := $(NDK_ROOT)/include
LOCAL_C_INCLUDES += $(NDK_ROOT)/libs/armeabi-v7a/include
LOCAL_LDLIBS += $(NDK_ROOT)/libs/armeabi-v7a/libgnustl_static.a

include $(LOCAL_PATH)/native/jni/OpenCV.mk

LOCAL_MODULE     := libopencv24
LOCAL_CFLAGS += -Wall -Wextra -Wno-error=non-virtual-dtor
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/native/jni/include/ \                 $(LOCAL_PATH)/native/jni/include/opencv $(NDK_ROOT)/include \ $(NDK_ROOT)/libs/armeabi-v7a/include


include $(BUILD_STATIC_LIBRARY)

Finally, you can call make -j4 to compile your package and check the log to see whether the compilation process succeeds or not. You may probably meet many other wired errors, don't panic, search them one by one and try to add something to LOCAL_CFLAGS or change a few line of codes to solve them. Have fun!



The following is the overall directory tree in my external/opencv24/.


.
|-- Android.mk
|-- haarcascade
|   |-- haarcascade_anger.xml
|   |-- haarcascade_disgust.xml
|   |-- haarcascade_eye_new.xml
|   |-- haarcascade_fear.xml
|   |-- haarcascade_frontalface_alt_tree.xml
|   |-- haarcascade_mcs_mouth.xml
|   |-- haarcascade_mcs_nose.xml
|   |-- haarcascade_mcs_righteye.xml
|   |-- haarcascade_mouth.xml
|   |-- haarcascade_sad.xml
|   |-- haarcascade_smile.xml
|   |-- haarcascade_surprise.xml
|-- native
    |-- 3rdparty
    |   `-- libs
    |-- jni
    |   |-- OpenCV.mk
    |   |-- OpenCVConfig-version.cmake
    |   |-- OpenCVConfig.cmake
    |   |-- OpenCVModules_armeabi-release.cmake
    |   |-- OpenCVModules_armeabi.cmake
    |   |-- OpenCVModules_armeabi_v7a-release.cmake
    |   |-- OpenCVModules_armeabi_v7a.cmake
    |   |-- OpenCVModules_mips-release.cmake
    |   |-- OpenCVModules_mips.cmake
    |   |-- OpenCVModules_x86-release.cmake
    |   |-- OpenCVModules_x86.cmake
    |   |-- android.toolchain.cmake
    |   |-- include
    |-- libs
        |-- armeabi
        |-- armeabi-v7a
        |-- mips
    |-- x86 


Saturday, March 28, 2015

Android Studio + Android + Gradle + NDK + OpenCV + SWIG + OSX

The purpose of the combination is to automatically compile OpenCV C/C++ code and use it in Android. The following solution refers to many other resources like how to execute NDK in gradle[1], how to execute SWIG [2].  The platform that I am talking about is Mac OS X.

 Part I, let me explain why we choose each tool in the tile.
(1) Intellij v.s. Android Studio v.s. Eclipse
   As a pure IDE, I like Intellij much more than eclipse considering the great prompt tips to assist you write code faster. Android Studio is actually a specific IDE based on Intellij. Unfortunately, only eclipse supports NDK, which is required to compile OpenCV android.

Even though, I prefer Intellij to Android Studio for some reasons like we can compile python module in the same project. However, I did not figure out how to import opencv-libary as a gradle module into the project, which works as a library to your Android opencv program.

(2) Gradle v.s. Maven v.s. Ant
Honestly, I just went through maven, which I find is very helpful to test and deploy project. However, in Android Studio, it is shipped with Gradle. There are many Q/A in stackoverflow to talk about gradle questions, instead of Maven. The other reason is that Gradle was developed to overcome disadvantages of Maven or Ant, like flat xml files. However, in Gradle, all the configuration is like coding, even in JAVA language, which makes it more flexible and efficient. Ant? I do not know much about it. Just a sense that it is replaced by Maven and then Gradle.

The mort important reason is that Gradle works like script, which can easily call system command like a shell script. This is key to embed NDK to Intellij. If executing the third party program like SWIG in next step, gradle is almost the top choice.

(3) SWIG
The way android calls OpenCV is through JNI code, which is a special format of function declaration. Trust me, you wouldn't like to convert all the C/C++ code to JNI code MANUALLY.

e.g., a JNI format C code
JNIEXPORT jlong JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeCreateObject
  (JNIEnv *, jclass, jstring, jint);

Fortunately, SWIG is such a software to do this kind of dirty work for you. However, it is not convenient to cooperate with your IDE. You can manually execute commands in your shell every time. But with Gradle, you can easily write a task for SWIG. That is the other reason we choose Gradle over Maven.

 
Part II, let me explain each part of the code.

I. Preparation
    Download and Install the following packages.
    (1) Android Studio  //IDE
    (2) SWIG                //Generate JNI code for C/C++ code
    (3) Android SDK    //For developing Android
    (4) Android NDK   // For compile JNI code to the APK
    (5) OpenCV            //For developing OpenCV C code, see my other post.
    (6) OpenCV-android-sdk // For developing OpenCV Android code

II. Directory structure
 This is the direct structure of a Gradle module in Android Studio under the project view (NOT Android).

--> All the file are in the main/
--> All the JAVA code

--> These JAVA files are code for wrapping JNI code, which is generated automatically by SWIG. *_wrapper one which contains the related java method to each native one.

--> All your Android code are store under this directory.    
--> All the JNI related resource are stored in jni/ directory.  Android.mk is used to configure NDK. Application.mk is used to configure some STD c++ [3]
--> opencv_test.cpp and opencv_test.h are two normal c++ files which might be copied directly from you xcode. opencv_test.i is used to configure SWIG.  opencv_test_wrap.cpp is generated JNI code by SWIG.

--> jnilibs are used to store NDK generated files.

--> res/ stores all the android resource like layout file.
AndroidManifest.xml is an Android configuration file.
--> Your gradle file for this module.





III. Create two directories: main/jni and main/jnilibs

IV. Configure your SWIG in Gradle
In our sample project, C/C++ code are in two files: opencv_test.h and opencv_test.cpp. These two files are normal C/C++ code, which can be copied directly from your xcode.

To tell SWIG which files are to be converted, you need to prepare another file, opencv_test.i as the configuration, which will be passed to SWIG in the Gradle next.

Here is a sample of opencv_test.i.  We name the module "opencv_test_wrapper", which will be the name of generated JAVA file. Also between %{ and %}, we tell SWIG to convert "opencv_test.h", which defines all the methods. For detailed tutorial, please refer to SWIG tutorial.

%module opencv_test_wrapper

%{
#include "opencv_test.h"
%}

%include "opencv_test.h"

Here is a sample code for calling SWIG in Gradle. The basic code is from [2].

def coreWrapperDir=new File("${projectDir}/src/main/java/com/example/opencvswig/core")
//Create the directory for storing SWIG generated JAVA wrapped JNI files.
task createCoreWrapperDir{
    coreWrapperDir.mkdirs()
}
//Call SWIG to wrap your C/C++ code to a JAVA code
task runSwig(type:Exec, dependsOn:['createCoreWrapperDir']){
    commandLine '/usr/local/bin/swig'
    args '-c++', '-java', '-package', 'com.example.opencvswig.core', '-outdir', coreWrapperDir.absolutePath, '-o',"${projectDir}/src/main/jni/opencv_test_wrap.cpp", "${projectDir}/src/main/jni/opencv_test.i"
}
(1) commandLine is a command to refer to swig, unlike [2], it must be an ABSOLUTE path to swig. Otherwise, gradle probably fails to find SWIG.
(2) args is for defining arguments of SWIG. Note that the last argument is the configuration file opencv_test.i .

V. Configure your NDK in Gradle
The basic purpose of NDK is to compile all your C/C++ codes to a *.so file, which can be further loaded in your android code. Two files are supposed to be configured NDK: Android.mk and Application.mk

There is a example for Android.mk.
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

OPENCV_ROOT := path to your andorid sdk/OpenCV-android-sdk
#OPENCV_CAMERA_MODULES:=on
#OPENCV_INSTALL_MODULES:=on
include ${OPENCV_ROOT}/sdk/native/jni/OpenCV.mk

LOCAL_SRC_FILES  := opencv_test_wrap.cpp opencv_test.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_LDLIBS     += -llog -ldl
LOCAL_MODULE     := opencv_test
 
include $(BUILD_SHARED_LIBRARY)
(1) You have to include the path to OpenCV.mk, which usually locates in the OpenCV SDK for Android.
(2) In addition to your source C/C++ file, you need to add the JNI files generated by SWIG, like open_test_wrapp.cpp in our sample.
(3) opencv_test is the library name, which you can refer from your Android code.


VI. Import OpenCV JAVA library to your project
To write your OpenCV android code, you have to refer to the library provided by OpenCV. It is distributed as the normal project. You can use Android Studio (NOT Intellij) to import it to your project and set your module to depends on the library. This solution is the first four steps of answer [5].

VII. Call you native code

(1) Before calling the native code, you need to load the library.
System.loadLibrary("opencv_test");

(2) Since all the C/C++ methods that wrapped in JAVA are static ones in the class, you just use the classname to refer them.
In our sample, the generated JAVA class file opencv_test_wrapper.java, so just use opencv_test_wrapper to refer each method.

NOTE: if some methods are not visible to your code, please check the generated java code. Some of them might be set as protected.

(3) Make sure your OpenCV-android is the same version as your OpenCV OSX. If they do not match, you would probably cannot pass data like Mat from the Java code to C/C++ code.


Then, you are done. I will upload my project to github later.

References
[1] http://hujiaweibujidao.github.io/blog/2014/10/22/android-ndk-and-opencv-development-with-android-studio/
[2] http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/
[3] http://docs.opencv.org/doc/tutorials/introduction/android_binary_package/android_dev_intro.html
[4] http://www.swig.org/tutorial.html
[5] http://stackoverflow.com/a/27356635

Saturday, March 14, 2015

Configure Xcode 6.0 to develop OpenCV

As a newbie to both Xcode and OpenCV, it is really painful to make them work together smoothly. Here I list the way I figured out and hope it could help you a little bit.

Since all the following instructions come from other online resources, which I will make a reference as much as I can, MOST credits go to them.

We assume that you have installed MacPorts and CMake, otherwise, please search how to install them in Google and follow one instruction to install them.

1. Install OpenCV
   a) Choose the right version. The latest version is 3.0, which is too new for most online samples. I choose 2.4, which is the default version MacPorts can find.
  b) install OpenCV by MacPorts
      $sudo port list opencv     #check opencv version first
      $sudo port install opencv

  Many blogs like [1] and [2] list a very complex steps to configure OpenCV,  most of which I do not know why. The easiest way is just let Macport handle all of them.


2. Configure Xcode
   a) Find the directory where OpenCV has been installed.
     My open CV is installed in /opt/local/include/opencv, /opt/local/include/opencv2, /opt/local/lib/. It could also be installed in /usr/local/include and /usr/local/lib. Find the directory of opencv and opencv2 and you find the OpenCV.
 
   b) Create a command-line project in Xcode 6.0.
   c) Click the root directory (project), and on the right of the project, you can find the configuration of the project. Click "all" tab which will show you all the configuration items.

   d) Scroll down to find the item "Search Paths"
     (i) Click "Header Search Paths",  add "/opt/local/include".
     (ii) Click "Library Search Paths", add "/opt/local/lib"

  e) Scroll up to find the item "Linking"
     Click "Other Linker Flags ", add the following.
  "-lopencv_calib3d -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_highgui -lopencv_imgproc -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_superres -lopencv_ts -lopencv_video -lopencv_videostab"


In [3], they have a very detailed instruction, however, their OpenCV is 3.0. There linker flags have to be removed, which are "-lopencv_imgcodecs", "-lopencv_shape" and "-lopencv_videoio".

Sometimes, you might have to add "-lopencv_legacy" to include some obsolete lib of OpenCV.

Find some samples and have fun!

[1]https://sites.google.com/site/learningopencv1/installing-opencv
[2] http://blogs.wcode.org/2014/10/howto-install-build-and-use-opencv-macosx-10-10/
[3]http://blogs.wcode.org/2014/11/howto-setup-xcode-6-1-to-work-with-opencv-libraries/

Tuesday, January 20, 2015

Leetcode 16: 3Sum Closest


Problem: 

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution. 

For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

Analysis:
This problem is similar to 3Sum, instead we have to track the minimum gap during the process. The process of doing 3sum is the same:
Step 1: Sort the given array from low to high. 
Step 2: Get the sum of three different elements each time by using three pointers
           P1: traverse the array from the first element to the end-2. For each P1, another pointer P2                     points to the next element of P1 while the third pointer P3  points to the last element. 
Step 3: For each summation, keep tracking the minimum gap between the summation and the target,             and update the 

You may wonder why the three pointer algorithm achieves the minimum running time. The reason is that the first step make sure the each time, P1 points to a different value so that the combination of P1, P2 and P3 (P1<P2<P3) will never be traversed twice. Also,  you can consider this problem as a problem selecting three different elements from an array and then return the combinations.

public class Solution {
    public int threeSumClosest(int[] num, int target) {
        if(num==null || num.length<3){
            return -1;
        }
        int gap=Integer.MAX_VALUE;
        int temp=-1;
        Arrays.sort(num);
        for(int i=0;i<num.length;i++){
            int j=i+1;
            int k=num.length-1;
            while(j<k){
                int sum=num[i]+num[j]+num[k];
                if(Math.abs(target-sum)<gap){
                    gap=Math.abs(target-sum);
                    temp=sum;
                }
                if(sum<target){
                    j++;
                }else{
                    k--;
                }
            }
        }
        return temp;
    }
}