本文來自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不支援引用傳遞,所以有些值必須通過函數返回,例如:
/**<br /> * 取得放大/縮小之後的映像大小<br /> */<br />JNIEXPORT jintArray JNICALL Java_com_testASIFT_LibASIFT_GetZoomSize(<br />JNIEnv* env, jobject obj) {<br />jint arrint[2];<br />arrint[0] = IM_X;<br />arrint[1] = IM_Y;<br />jintArray result = env->NewIntArray(2);<br />env->SetIntArrayRegion(result, 0, 2, arrint);<br />return result;<br />}<br />/**<br /> * 返回匹配後映像的大小 jintArray[0]為width, jintArray[1]為height<br /> */<br />JNIEXPORT jintArray JNICALL Java_com_testASIFT_LibASIFT_GetMatchedImageSize(<br />JNIEnv* env, jobject obj) {<br />jint arrint[2];<br />arrint[0] = wo;<br />arrint[1] = ho;<br />jintArray result = env->NewIntArray(2);<br />env->SetIntArrayRegion(result, 0, 2, arrint);<br />return result;<br />}
2、ASIFT接受的是8bit的灰階圖,使用前要轉換為8bit的灰階圖:
void PixelToVector(jint *cbuf, int w, int h, std::vector<float> *ipixels) {<br />for (int i = 0; i < h; i++) {<br />for (int j = 0; j < w; j++) {<br />// 獲得像素的顏色<br />int color = cbuf[w * i + j];<br />int red = ((color & 0x00FF0000) >> 16);<br />int green = ((color & 0x0000FF00) >> 8);<br />int blue = color & 0x000000FF;<br />color = (red + green + blue) / 3;<br />ipixels->push_back(color);//儲存灰階值<br />}<br />}<br />}<br />
使用後要把8bit灰階圖轉為RGB565:
jintArray result = env->NewIntArray(wo * ho);<br />jint *cResult;<br />cResult = env->GetIntArrayElements(result, false);<br />int alpha = 0xFF << 24;<br />for (int i = 0; i < ho; i++) {<br />for (int j = 0; j < wo; j++) {<br />// 獲得像素的顏色<br />int color = (int) opixelsASIFT[wo * i + j];<br />color = alpha | (color << 16) | (color << 8) | color;<br />cResult[wo * i + j] = color;<br />}<br />}<br />env->ReleaseIntArrayElements(result, cResult, 0);
主類testASIFT.java的邏輯代碼如下:
public class testASIFT extends Activity {<br /> /** Called when the activity is first created. */<br />ImageView imgView;<br /> @Override<br /> public void onCreate(Bundle savedInstanceState) {<br /> super.onCreate(savedInstanceState);<br /> setContentView(R.layout.main);<br /> this.setTitle("Android上使用ASIFT---hellogv");<br /> imgView=(ImageView)this.findViewById(R.id.ImageView01);</p><p> LibASIFT.initZoomSize(320, 480);//縮放目標的大小<br /> int []size=LibASIFT.GetZoomSize();//判斷是否設定成功<br /> Log.e(String.valueOf(size[0]),String.valueOf(size[1]));</p><p> Bitmap img1=((BitmapDrawable) getResources().getDrawable(R.drawable.adam1)).getBitmap();<br /> int w1=img1.getWidth(),h1=img1.getHeight();<br /> int[] pix1 = new int[w1 * h1];<br /> img1.getPixels(pix1, 0, w1, 0, 0, w1, h1);<br /> //提取第一張圖片的特徵點<br /> LibASIFT.initImage1(pix1, w1, h1, 2);<br /> Bitmap img2=((BitmapDrawable) getResources().getDrawable(R.drawable.adam2)).getBitmap();<br /> int w2=img2.getWidth(),h2=img2.getHeight();<br /> int[] pix2 = new int[w2 * h2];<br /> img2.getPixels(pix2, 0, w2, 0, 0, w2, h2);<br /> int[] imgPixels=LibASIFT.Match2ImageForImg(pix2, w2, h2, 2);//兩圖匹配<br /> int[] imgSize=LibASIFT.GetMatchedImageSize();//匹配結果圖的大小<br /> Bitmap imgResult=Bitmap.createBitmap(imgSize[0], imgSize[1], Config.RGB_565);<br /> imgResult.setPixels(imgPixels, 0, imgResult.getWidth(), 0, 0, imgResult.getWidth(), imgResult.getHeight());<br /> imgView.setImageBitmap(imgResult);//顯示結果</p><p> }<br />}