Android で OpenCL を試す
の続きです
OpenCL の Image2D
OpenCL では,基本的な1次元の配列の他に,
画像の2次元のデータを取り扱う Image2D というデータ型が用意されている。
使い方
clCreateImage2D を使って画像データから Image2D を作成する。
引数は、画像データが格納された1次元配列のアドレスを示すポインター。
カーネルプログラムからは、
read_imagef と write_imagef を使って読み書きする。
-
[clCreateImage2D] (https://www.khronos.org/registry/OpenCL/sdk/1.0/docs/man/xhtml/clCreateImage2D.html)
Image2D のサンプル
Image2D のサンプルコードとして、
github に公開されているものを試す。
パソコン向けのC++ 版なので、Android向けに変更する。
このサンプルはガウシアンフィルタを使って画像のぼかしを行う。
重みは 3x3 の基本的なもの
|1|2|1|
|2|4|2|
|1|2|1|
ぼかしの効果は画像を拡大しないとわからない。
ガウスぼかしの効果について記事を書いた。
OpenCL を使って ガウスぼかしをする
Android の画像から Image2D を作成する
当初は、Android の Bitmap から Image2D を作成しようとした。
先人の例があるだろと思ったが、全く見つからない。
結局、うまくいかなかった。
OpenCV の Maから Image2D を作成する例が見つかったので、
Mat を仲介役にした。
-
[OpenCL leading with OpenCV]
(https://stackoverflow.com/questions/18687178/opencl-leading-with-opencv) -
How to create cv::Mat from buffer (array of T* data) using a template function
Java プログラム
画像を Bitmap 形式にする
Bitmap bitmap = BitmapFactory.decodeFile(pathName);
OpenCV の Mat 形式にする
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Mat mat = new Mat(height, width, CvType.CV_8UC4);
Utils.bitmapToMat(bitmap, mat);
native プログラムを呼ぶ
ImageFilter(
mat.getNativeObjAddr() );
public native void ImageFilter(long matAddr);
native プログラム
JNIEXPORT void JNICALL
Java_jp_ohwada_android_opencl5_MainActivity_ImageFilter(
jlong addr
)
{
// 引数から Mat を復元する
Mat& mat = *(Mat*)addr;
char *buffer = reinterpret_cast<char *>(mat.data);
Image2D を作成する
cl_mem image = clCreateImage2D(context,
CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
&clImageFormat,
width,
height,
0,
buffer,
&errNum);
アプリを作成する
OpenCL と OpenCV の環境が必要です。
下記を読んでください。
_ AndroidStudio で OpenCV をインポートする
(1) プロジェクトを作成する
(2) OpenCV の Android 用 SDK を用意する
(3) OpenCL のライブラリを用意する
(4) app/src/main/Assets フォルダーにOPenCLのカーネルプログラムファイルを配置する
(5) レイアウトファイルに ImageView を配置する
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<ImageView
android:id="@+id/outputImageView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/picture" />
(6) MainActivity を作成する
public class MainActivity extends Activity
private native void nativeStepOpenCL (
// 詳細 略
(7) C++ のプログラムファイルを作成する
extern "C" void Java_com_intel_sample_androidbasicocl_MainActivity_nativeStepOpenCL
(
// 詳細 略
(8) CMakeLists.txt を作成する
add_library( # Sets the name of the library.
ImageFilter2D
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
ImageFilter2D.cpp )
(9) app/build.gradle を変更する
externalNativeBuild {
cmake {
path 'src/main/cpp/CMakeLists.txt'
}
}
アプリを実行する
analyze apk により下記の4つが同封されていることが確認できる。
- libImageFilter2D.so
- libOpenCL.so
- libopencv_java4.so
- libc++_shared.so
スクリーンショット
ぱっと見では、変換前後で違いがわからない。
左が変換前、右が変換後
画像を拡大すると、ぼかしが効いているのがわかる
左が変換前、右が変換後
サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/OpenCL5