本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处!
今晚是平安夜,跟众多四眼技术宅一样,这个时候还是跟电脑过节
......
上次讲解了在Android上通过NDK把彩图转换为灰度图,现在可以把WindowsMobile版的ASIFT 例子移植到Android上了.......在这里还是要再次感谢Jean-Michel Morel和Guoshen Yu两位大牛的无私奉献,尊重知识尊重开源精神。
先来看看本文程序运行截图:
左图是设定识别率为最低的结果,右图是设定识别率为较低的结果。
本文的代码可以到这里下载:http://www.pudn.com/downloads314/sourcecode/comm/android/detail1391871.html
这里ASIFT的NDK代码(C++)跟WM篇的DLL代码大体一样,不过也存在一些不同:
1、JNI不支持引用传递,所以有些值必须通过函数返回,例如:
/**
* 取得放大/缩小之后的图像大小
*/
JNIEXPORT jintArray JNICALL Java_com_testASIFT_LibASIFT_GetZoomSize(
JNIEnv* env, jobject obj) {
jint arrint[2];
arrint[0] = IM_X;
arrint[1] = IM_Y;
jintArray result = env->NewIntArray(2);
env->SetIntArrayRegion(result, 0, 2, arrint);
return result;
}
/**
* 返回匹配后图像的大小 jintArray[0]为width, jintArray[1]为height
*/
JNIEXPORT jintArray JNICALL Java_com_testASIFT_LibASIFT_GetMatchedImageSize(
JNIEnv* env, jobject obj) {
jint arrint[2];
arrint[0] = wo;
arrint[1] = ho;
jintArray result = env->NewIntArray(2);
env->SetIntArrayRegion(result, 0, 2, arrint);
return result;
}
2、ASIFT接受的是8bit的灰度图,使用前要转换为8bit的灰度图:
void PixelToVector(jint *cbuf, int w, int h, std::vector<float> *ipixels) {
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
// 获得像素的颜色
int color = cbuf[w * i + j];
int red = ((color & 0x00FF0000) >> 16);
int green = ((color & 0x0000FF00) >> 8);
int blue = color & 0x000000FF;
color = (red + green + blue) / 3;
ipixels->push_back(color);//保存灰度值
}
}
}
使用后要把8bit灰度图转为RGB565:
jintArray result = env->NewIntArray(wo * ho);
jint *cResult;
cResult = env->GetIntArrayElements(result, false);
int alpha = 0xFF << 24;
for (int i = 0; i < ho; i++) {
for (int j = 0; j < wo; j++) {
// 获得像素的颜色
int color = (int) opixelsASIFT[wo * i + j];
color = alpha | (color << 16) | (color << 8) | color;
cResult[wo * i + j] = color;
}
}
env->ReleaseIntArrayElements(result, cResult, 0);
主类testASIFT.java的逻辑代码如下:
public class testASIFT extends Activity {
/** Called when the activity is first created. */
ImageView imgView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.setTitle("Android上使用ASIFT---hellogv");
imgView=(ImageView)this.findViewById(R.id.ImageView01);
LibASIFT.initZoomSize(320, 480);//缩放目标的大小
int []size=LibASIFT.GetZoomSize();//判断是否设置成功
Log.e(String.valueOf(size[0]),String.valueOf(size[1]));
Bitmap img1=((BitmapDrawable) getResources().getDrawable(R.drawable.adam1)).getBitmap();
int w1=img1.getWidth(),h1=img1.getHeight();
int[] pix1 = new int[w1 * h1];
img1.getPixels(pix1, 0, w1, 0, 0, w1, h1);
//提取第一张图片的特征点
LibASIFT.initImage1(pix1, w1, h1, 2);
Bitmap img2=((BitmapDrawable) getResources().getDrawable(R.drawable.adam2)).getBitmap();
int w2=img2.getWidth(),h2=img2.getHeight();
int[] pix2 = new int[w2 * h2];
img2.getPixels(pix2, 0, w2, 0, 0, w2, h2);
int[] imgPixels=LibASIFT.Match2ImageForImg(pix2, w2, h2, 2);//两图匹配
int[] imgSize=LibASIFT.GetMatchedImageSize();//匹配结果图的大小
Bitmap imgResult=Bitmap.createBitmap(imgSize[0], imgSize[1], Config.RGB_565);
imgResult.setPixels(imgPixels, 0, imgResult.getWidth(), 0, 0, imgResult.getWidth(), imgResult.getHeight());
imgView.setImageBitmap(imgResult);//显示结果
}
}