Code xử lý ảnh trong android

OpenCV là một thư viện xử lý ảnh mã nguồn mở nổi tiếng trên nền PC và hiện nay đã có phiên bản dành cho mobile trên nền Android, iOS. Bài này giới thiệu cách cài đặt môi trường và một số khái niệm cơ bản nhất để phát triển ứng dụng xử lý ảnh trên nền Android sử dụng OpenCV.

Bước 1. CÀI ĐẶT MÔI TRƯỜNG:

1. JDK 1.7.0_17

2. Eclipse IDE (lập trình Android trên PC thì tốt nhất cài luôn bản tích hợp Eclipse ADT Bundle của Google đã tích hợp sẵn nhiều thứ: Eclipse IDE, ADT, Android SDK, Android platform tool). Download ở đây: http://developer.android.com/sdk/index.html


3. Android SDK (nếu dùng bản Eclipse ADT Bundle ở trên đã có sẵn rồi thì ko phải cài thêm)

4. Android NDK (android-ndk-r9)

5. CDT plugin for Eclipse (dành để phát triển Native C++ với Android)

6. Update Android SDK. OpenCV hỗ trợ các API từ version 11 trở lên.
Xem hướng dẫn thông tin cài đặt từ bước 1-6 ở link dưới đây nếu cần thông tin bổ sung.
 http://docs.opencv.org/doc/tutorials/introduction/android_binary_package/android_dev_intro.html#android-dev-intro

7. Download OpenCV 2.4.6 cho Android và un-zip ra một folder trên PC.
http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.4.6/OpenCV-2.4.6-android-sdk-r2.zip/download

Bước 2: TẠO PROJECT SAMPLE
Khi phát triển ứng dụng OpenCV trên Android có 2 cách:
1. Phát triển hoàn toàn bằng Java và sử dụng Android API của OpenCV
2. Phát triển phần giao diện và logic bằng Java, phần OpenCV sử dụng C++ thông qua JNI để tái sử dụng source code có sẵn và dùng được trên nền tảng khác như iOS

Ở đây ta sẽ tạo project và cấu hình theo từng cách, đầu tiên là cách 1.
1. Mở Eclipse tạo project Android application như bình thường, compile để test

2. Import OpenCV 2.4.6 library project vào cùng workspace (import từ root directory của folder OpenCV ở bước 7 phía trên)

3. Từ Android project của mình add reference đến OpenCV: Project -> Properties -> Android -> Library -> Add (lưu ý chỗ này kiểm tra để thư viện add vào phải là đường dẫn tương đối thì khi compile mới ko bị lỗi, tốt nhất tạo project Android Application của mình ở trong thư mục OpenCV-2.4.6-android-sdk\samples để lúc add vào Eclipse tự nhận đường dẫn tương đối)

4. Nếu định sử dụng OpenCV cho tính năng nào của Android OS thì cần add quyền sử dụng tương ứng vào file AndroidManifest.xml tương ứng.


5. Như trên ta đã hoàn thành việc config cơ bản, giờ vào code để load library OpenCV lên.
Có 2 cách, cách chuẩn của OpenCV là load theo kiểu Async, sẽ load 1 thư viện của OpenCV là OpenCV Manager từ trong máy điện thoại lên, nếu máy điện thoại chưa có thì OpenCV sẽ yêu cầu người dùng down từ Google Play về và cài đặt. API load như sau:

OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_6, this, mLoaderCallback);

Cách 2 là load theo kiểu InitDebug, sẽ yêu cầu ta copy các thư viện của OpenCV vào thư mục libs của Android project sau đó load lên như các thư viện android bình thường và không yêu cầu máy điện thoại phải cài đặt OpenCV manager. Copy các lib từ thư mục c:\OpenCV-2.4.6-android-sdk\sdk\native\libs\ vào thư mục libs của project, API load như sau:

OpenCVLoader.initDebug()


Chi tiết cụ thể ở bước 5 có thể xem ở link sau:
http://docs.opencv.org/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.html#dev-with-ocv-on-android
Sau khi load xong library OpenCV sẽ gọi hàm load callback báo đã load xong.  Lưu ý nếu trong code của hàm callback có đoạn sử dụng tài nguyên hay giao diện nào thì cần đặt vị trí hàm initDebug() ở vị trí sau đoạn khởi tạo tài nguyên tương ứng để tránh TH tài nguyên chưa khởi tạo xong, bị null, mà ở code hàm callback đã sử dụng.

6. Sau khi load library xong ta có thể sử dụng các API của OpenCV ví dụ như đoạn code sau:
Mat matSrc = new Mat();
Mat matDst = new Mat();
Bitmap bmpSrc = BitmapFactory.decodeFile(picturePath);                       
Utils.bitmapToMat(bmpSrc, matSrc);
Imgproc.cvtColor(matSrc, matDst, Imgproc.COLOR_RGB2BGRA);


Toàn bộ các bước trên có thể tham khảo trong project demo DecoShashin mình đã tạo, xem trên Github.


Nếu phát triển ứng dụng theo cách 2, tức code native C++ sử dụng OpenCV thì các bước khác biệt so với cách 1 (chỉ dùng Android và OpenCV Java API) như sau:

1. Sử dụng Native C++ sẽ yêu cầu cài Android NDK, CDT plugin, trong project Android application ta sẽ tự tạo thư mục JNI và để các file code C++ vào đó (*.cpp), các hàm ở C++ sẽ phải có giao diện export để bên Java code có thể dùng được. Ta cũng phải chuyển project Android thành C/C++ Project (Add nature) bằng cách chọn project rồi vào menu New/Other/Convert to C/C++ Project.

2. Trong project sẽ phải có 2 file Android.mk và Application.mk (tự tạo) để phục vụ setting compile C++. Sau khi compile C++ code thành library trong code Java sẽ phải loadlibrary đó lên để sử dụng. 

 3. Lưu ý: format của hàm export trong file c++ sẽ theo dạng sau:
Java + tên gói package của android project + tên class sẽ gọi hàm c++ + tên hàm
các thành phần trên phải được nối với nhau bằng dấu “_”, dấu chấm “.” trong tên package cũng phải đổi thành “_”. Ví dụ:

extern “C” {
JNIEXPORT void JNICALL Java_vn_vtcsoft_decoshashin_DecorateScreen_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);


4. Để build C++ trong Eclipse và debug được thì trong project setting phải đặt vào mục Properties/C/C++ Build/Builder Setting/Build Command dòng sau:
${NDKROOT}/ndk-build.cmd NDK_DEBUG=1
NDKROOT là tham số trỏ đến thư mục gốc của Android NDK R9. Sau khi thực hiện setting này khi nhấn build trên Eclipse nó sẽ gọi ndk để pre-build luôn các file code C++.

Để NDK compile được C++ code có include các header của OpenCV phải đặt:
${NDKROOT}/platforms/android-9/arch-arm/usr/include
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/include
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include
../../sdk/native/jni/include
vào mục Properties/C/C++ General/Path and Symbols/GNU C++ (lưu ý dòng cuối là dùng đường dẫn tương đối chỉ đến thư mục include của OpenCV SDK)

5. Sau khi setting xong khi nhấn build để kiểm tra xem có lỗi config gì ko. Nếu ko ta bắt đầu vào code Java để sử dụng hàm C++ thông qua JNI. Đầu tiên phải loadlibrary mà các hàm C++ này export ra bằng hàm sau: System.loadLibrary(“decoshashin”); // decoshashin là tên library, đc đặt trong file android.mk. Ngoài ra phải khai báo tên hàm native sẽ sử dụng trong thư viện theo cú pháp sau, ví dụ:
 public native void FindFeatures(long matAddrGr, long matAddrRgba);

That’s all! Đến đây ta đã thực hiện xong việc chuyển project Adroid sang C++ project, bổ sung thêm thư mục jni, file android.mk, application.mk. Cấu hình include các header thư viện cần thiết của OpenCV, cấu hình debug và tự build C++ code trong Eclipse, cách khai báo export hàm trong C++ và sử dụng trong Java code. Giờ chỉ việc viết code cụ thể vào các hàm C++ và test là xong.

Chi tiết có thể xem ở link sau:
http://docs.opencv.org/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.html#dev-with-ocv-on-android