Monday, February 24, 2014

How-to Install OpenCV on an Android VM

Installing an Android emulator on Ubuntu is actually quite easy. Below, are the steps I took to get OpenCV 2.4.5 working on a Android emulator installed on my Ubuntu 12.04 machine. Most guides I have read assume that you are going to be using Eclipse. I don't use Eclipse.

1) Install the JDK and ant. 

:~$ sudo apt-get install openjdk-6-jdk 
:~$ sudo apt-get install ant 
:~$ export JAVA_HOME=/usr/lib/jvm/java-6-openjdk 
:~$ export PATH=$PATH:/usr/lib/jvm/java-6-openjdk/bin 

Sanity check: type “javac” in your terminal to confirm JDK is available. 

2) Install the Android SDK. Download android-sdk_r22.3-linux.tgz and unpack it: 

:~$ cd android-sdk-linux 
:~$ tools/android update sdk –no-ui 
:~$ export PATH=$PATH:~android-sdk-linux/tools :~android-sdk-linux/platform-tools 

3) Install the Android emulator from Genymotion and add a virtual device. Once installed, use its UI to “Add” a virtual device: 

:~$ cd genymotion 
:~$ ./genymotion 

In order to enable the drag & drop of “apk” files from the host to the Android VM, enter the path to the android-sdk-linux directory in the Genymotion settings, on the ADB tab. 

Start the VM. 

4) Install OpenCV on the Android VM. 
Download OpenCV 2.4.5  and unpack it. 
Drag & drop OpenCV-2.4.5-android-sdk/apk/OpenCV_2.4.8_Manager_2.16_x86.apk into the VM. 

Sanity check: In the Android emulator click the “OpenCV Manager” to confirm that you see no error messages. 

5) Test an OpenCV sample application. Compile the 15-puzzle application, for example: 

:~$ cd OpenCV-2.4.8-android-sdk/samples/15-puzzle 
:~$ android update project --path . 
:~$ ant debug 
:~$ cd bin 

Sanity check: Drag & drop OpenCV-2.4.8-android-sdk/samples/15-puzzle/bin/Puzzle15Activity-debug.apk into the emulator. Confirm that it works. 

6) Test an OpenCV native C++ application. Download and unpack android-ndk-r9c-linux-x86_64.tar from http://developer.android.com/tools/sdk/ndk/index.html 

:~$ export PATH=$PATH:~android-ndk-r9c/ 
:~$ cd OpenCV-2.4.8-android-sdk/samples/native-activity 

Modify the ABI in Android.mk: APP_ABI := all 
:~$ vi jni/Android.mk 

Build it:

:~$ android update project --path . 
:~$ ndk-build -B 
:~$ ant debug 
:~$ cd bin

Wednesday, February 05, 2014

Implement Data Parallelism on a GPU Directly in C++

Download: https://github.com/dimitrs/cpp-opencl

The cpp-opencl project provides a way to make programming GPUs easy for the developer. It allows you to implement data parallelism on a GPU directly in C++ instead of using OpenCL. See the example below. The code in the parallel_for_each lambda function is executed on the GPU, and all the rest is executed on the CPU. More specifically, the “square” function is executed both on the CPU (via a call to std::transform) and the GPU (via a call to compute::parallel_for_each). Conceptually, compute::parallel_for_each is similar to std::transform except that one executes code on the GPU and the other on the CPU.

#include <vector>
#include <stdio.h>
#include "ParallelForEach.h"

template<class T> 
T square(T x)  
{
    return x * x;
}

void func() {
  std::vector<int> In {1,2,3,4,5,6};
  std::vector<int> OutGpu(6);
  std::vector<int> OutCpu(6);

  compute::parallel_for_each(In.begin(), In.end(), OutGpu.begin(), [](int x){
      return square(x);
  });

  
  std::transform(In.begin(), In.end(), OutCpu.begin(), [](int x) {
    return square(x);
  });

  // 
  // Do something with OutCpu and OutGpu …..........

  //

}

int main() {
  func();
  return 0;
}


Function Overloading 

Additionally, it is possible to overload functions. The “A::GetIt” member function below is overloaded. The function marked as “gpu” will be executed on the GPU and other on the CPU.

struct A {
  int GetIt() const __attribute__((amp_restrict("cpu"))) {
    return 2;
  }
  int GetIt() const __attribute__((amp_restrict("gpu"))) {
    return 4;
  }
};

compute::parallel_for_each(In.begin(), In.end(), OutGpu.begin(), [](int x){
    A a; 
    return a.GetIt(); // returns 4
});



Build the Executable 

The tool uses a special compiler based on Clang/LLVM. 

cpp_opencl -x c++ -std=c++11 -O3 -o Input.cc.o -c Input.cc 

The above command generates four files: 
1. Input.cc.o 
2. Input.cc.cl 
3. Input.cc_cpu.cpp 
4. Input.cc_gpu.cpp 

Use the Clang C++ compiler directly to link: 

clang++ ./Input.cc.o -o test -lOpenCL 


Then just execute: 

./test