Tuesday, 3 June 2014

Configure OpenCV for Android and manipulate image HSV

Hey Guys,

Just used OpenCV in  one of my project to manipulate image Hue, Saturation and Brightness.

Here is source code:
//**************************//
In Java class:
//Image input
InputStream is;
is = this.getResources().openRawResource(R.drawable.img_test);
Bitmap bmInImg = BitmapFactory.decodeStream(is);

int[] mPhotoIntArray;
int[] mOutArray;

mPhotoIntArray = new int[bmInImg.getWidth() * bmInImg.getHeight()];
// Copy pixel data from the Bitmap into the 'intArray' array
bmInImg.getPixels(mPhotoIntArray, 0, bmInImg.getWidth(), 0, 0, bmInImg.getWidth(), bmInImg.getHeight());

// create the canny result buffer
mOutArray= new int[bmInImg.getWidth() * bmInImg.getHeight()];

hsb(bmInImg.getHeight(), bmInImg.getWidth(), h,s,b, mPhotoIntArray, mOutArray);

//use recived output
Bitmap bmOutImg = Bitmap.createBitmap(bmInImg.getWidth(), bmInImg.getHeight(), Config.ARGB_8888);
bmOutImg.setPixels(mOutArray, 0, bmInImg.getWidth(), 0, 0, bmInImg.getWidth(), bmInImg.getHeight());
img.setImageBitmap(bmOutImg);


public native boolean hsb(int width, int height, double hueEffect,double satrEffect,double brightnessEffect, int[] mPhotoIntArray, int[] mOutArray);


static
{
System.loadLibrary("first-opencv");
}

//**************************//
JNI file:

#include <jni.h>

#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc_c.h>
#include <android/log.h>
using namespace cv;

//jboolean - return type
// Java - jni notation
// com_deepapps_ui - package name of class in which method loaded/declared.
// EditorFragmentActivity - class in  the package.
// hsb - method name

extern "C" jboolean Java_com_deepapps_ui_EditorFragmentActivity_hsb(
JNIEnv* env, jobject thiz, jint width, jint height, jdouble hueEffect,
jdouble saturationEffect, jdouble brightnessEffect, jintArray in,
jintArray out) {
//get the data pointer.
IplImage *hsv, *hue, *sat, *val, *b, *r, *g, *brg;
double scale = 1;
int key = 0, depth;
CvSize size;

jint* _in = env->GetIntArrayElements(in, 0);
jint* _out = env->GetIntArrayElements(out, 0);

//Build the Mat structure for input data
Mat mSrc(height, width, CV_8UC4, (unsigned char *) _in);
//Build the Mat structure for output data
Mat mOut(height, width, CV_8UC4, (unsigned char *) _out);

//Convert Mat to IplImage
IplImage mSrcImg = mSrc;
IplImage mOutImg = mOut;

if (mSrcImg.nChannels != 3) {
printf("image is not compatible to precess!");
exit - 1;
}

size = cvGetSize(&mSrcImg);
depth = mSrcImg.depth;
hue = cvCreateImage(size, depth, 1);
sat = cvCreateImage(size, depth, 1);
val = cvCreateImage(size, depth, 1);
hsv = cvCreateImage(size, depth, 3);
cvZero(hsv);
cvZero(hue);
cvZero(sat);
cvZero(val);
b = cvCreateImage(size, depth, 1);
r = cvCreateImage(size, depth, 1);
g = cvCreateImage(size, depth, 1);
brg = cvCreateImage(size, depth, 3);
cvZero(brg);
cvZero(hue);
cvZero(sat);
cvZero(val);
IplImage *im1_a = cvCreateImage(cvGetSize(&mSrcImg), 8, 1); //hold alpha chanel
IplImage *im1_bgra = cvCreateImage(cvGetSize(&mSrcImg), 8, 4);
/* Convert from Red-Green-Blue to Hue-Saturation-Value */
cvCvtColor(&mSrcImg, im1_bgra, CV_BGR2BGRA);
cvCvtColor(&mSrcImg, hsv, CV_BGR2HSV);

/* Split hue, saturation and value of hsv on them */
cvSplit(im1_bgra, hue, sat, val, im1_a);
cvSplit(hsv, hue, sat, val, 0);

cvConvertScale(hue, hue, scale, hueEffect); //update hue // (uchar) ((double)src*scale+saturation)
cvConvertScale(sat, sat, scale, saturationEffect); //update sat

cvMerge(hue, sat, val, 0, hsv);
cvCvtColor(hsv, brg, CV_HSV2BGR);

cvSplit(brg, b, g, r, 0);
cvMerge(b, g, r, im1_a, &mOutImg);//merge b g r and orignal apha

mOut = &mOutImg
+ Scalar(brightnessEffect, brightnessEffect, brightnessEffect); //update brightness

__android_log_write(ANDROID_LOG_ERROR, "satr", "4");
//release the pointer.
env->ReleaseIntArrayElements(in, _in, 0);
env->ReleaseIntArrayElements(out, _out, 0);
return true;
}


Put this code in "open-cv.cpp" under jni folder.( jni should be in root folder of project)

Create Android.mk file in jni folder and put:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_INSTALL_MODULES:=on
OPENCV_CAMERA_MODULES:=off
OPENCV_LIB_TYPE:=STATIC
include ..replacewithopencvfolderpath\sdk\native\jni\OpenCV.mk
LOCAL_MODULE    := open-cv
LOCAL_SRC_FILES := open-cv.cpp
LOCAL_LDLIBS +=  -llog -ldl
include $(BUILD_SHARED_LIBRARY)

Create Application.mk in jni folder and put:

APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a
APP_PLATFORM := android-9
APP_MODULES := open-cv





//make sure your sourcecode and opencv libs folders path must be without space in there name.

Download opencv from: http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.4.9/OpenCV-2.4.9-android-sdk.zip/download

I hope you must have android ndk configured in your eclipse.
Or follow steps: https://developer.android.com/tools/sdk/ndk/index.html


Android project properties:
-> C/C++ build
Builder setting -> build command : ndk-build

-> C/C++ General Setting
  Path and Symbol
Add:
1. ..ndkfolderpath\sources\cxx-stl\system\include
2. ..ndkfolderpath\sources\cxx-stl\gnu-libstdc++\4.6\include
3. ..ndkfolder\platforms\android-9\arch-arm\usr\include
4  ..opencvfolder\sdk\native\jni\include

Let me know if have any doubt.


keywords: opencv android, android jni, Hue , Saturation, Brightness, Image color manipulation, android NDK

Thursday, 20 February 2014

Linkify text

Hey Guys,

Lets see the use of Linkify in Android.

The Linkify class is available in Android SDK. With this class we can specify a regular expression to match, and a scheme to append before linkified text. The matched text is added after scheme to allow the correct data to be looked up.

For example, we want to linkify all text starts with either number or small case alphabet or capital case alphabet (with no spaces). Linkify can turn this in URI - something like http://www.google.com/text which can then be used to locate the correct application with data.

Here is the code snippet:

               TextView txtOutput = (TextView) findViewById(R.id.adb_output);
txtOutput .setText(" This is simple text To search");
Pattern wordMatcher = Pattern.compile("\\b[A-Za-z0-9]+\\b");   //you can change the regular expression as per your requirement.

String viewURL=    "http://www.google.com/";
Linkify.addLinks(txtOutput , wordMatcher , viewURL);


Please let me know if have any query.