天天看点

Android上使用ASIFT实现对视角变化更鲁棒的特征匹配

 本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处!

     今晚是平安夜,跟众多四眼技术宅一样,这个时候还是跟电脑过节

Android上使用ASIFT实现对视角变化更鲁棒的特征匹配

......

     上次讲解了在Android上通过NDK把彩图转换为灰度图,现在可以把WindowsMobile版的ASIFT 例子移植到Android上了.......在这里还是要再次感谢Jean-Michel Morel和Guoshen Yu两位大牛的无私奉献,尊重知识尊重开源精神。

先来看看本文程序运行截图:

Android上使用ASIFT实现对视角变化更鲁棒的特征匹配
Android上使用ASIFT实现对视角变化更鲁棒的特征匹配

左图是设定识别率为最低的结果,右图是设定识别率为较低的结果。

本文的代码可以到这里下载: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);//显示结果

}

}