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

本文来自http://blog.youkuaiyun.com/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);//显示结果 } }

ASIFT算法在Python中的实现及其意义 ASIFT算法是在SIFT算法基础上进行改进得到的,主要解决了SIFT算法在仿射变换和视角变化下性能下降的问题。pyASIFT是一个基于Python的ASIFT算法实现,它封装了ASIFT算法的核心步骤,使得用户能够方便地在Python环境中使用ASIFT算法。对我而言ASIFT算法在Python中的实现具有重要意义。通过充分利用Python的编程优势和现有计算机视觉库的功能,我们可以方便地在Python环境中实现ASIFT算法,并将其应用于图像匹配、目标识别和三维重建等任务中,推动计算机视觉领域的发展。 阅读详情

相关推荐

OpenCV实例:使用ASIFT算法进行图像匹配

ASIFT是一种基于尺度不变特征变换的图像匹配算法,该算法不依赖于特定的图像内容和光照条件,因此具有较高的鲁棒性。本文将介绍如何使用OpenCV库实现ASIFT算法的图像匹配功能。至此,我们已经成功地实现了ASIFT算法的图像匹配功能。通过对多张图片进行匹配并比较其结果,我们可以获得更准确的图像相似性评估。匹配结果会在新窗口中显示,用户可以直观地看到两张图片之间的相似度。OpenCV实例:使用ASIFT算法进行图像匹配。第三步:读取测试图片并进行匹配。第一步:导入必要的库。第四步:展示匹配结果。

2301_79365003的博客 501

ASIFT算法过程实现 --- 配置避坑指南

ASIFT算法

m0_47489229的博客 2440

ASIFT自动配准程序

改进的SIFT自动寻找特征点,自动配准算法,具有仿射、旋转和尺度不变特性!C++程序,VS2010编译通过,可直接使用!另附有算法的相关论文!

ASIFT

SIFT 是一种检测与描述图像局部特征的方法。为了识别和描述图像中的目标, 需要从图像中提取出与目标相联系的特征。 利用这些特征可以从众多背景目标中识别 出所需目标。为了确保准确无误地识别出目标,要求在各种视角、光照、距离以及噪 声条件下仍然可以准确地进行匹配。 SIFT 使用不同的技术解决以上问题。对物体距 离远近, 大小和噪声条件的适应由高斯尺度空间来完成, 而视角、 光

u013074906的专栏 6149

ASIFT+OpenCV图像特征匹配实战 - VC工程源码

ASIFT+OpenCV图像特征匹配实战VC工程源码 OpenCV包含头文件: #include "cv.h" #include "highgui.h" #include "cxcore.h" 核心代码如下: if (!m_pImage1||!m_pImage2) { AfxMessageBox("please,select 2 images!"); return; } UpdateData(TRUE); CvSize sz1 = cvSize(m_pImage1->width,m_pImage1->height); CvSize sz2 = cvSize(m_pImage2->width,m_pImage2->height); CvScalar s; IplImage *gimg1 = cvCreateImage(sz1,IPL_DEPTH_8U,1); cvCvtColor(m_pImage1,gimg1,CV_BGR2GRAY); IplImage *gimg2 = cvCreateImage(sz2,IPL_DEPTH_8U,1); cvCvtColor(m_pImage2,gimg2,CV_BGR2GRAY); size_t w1, h1; w1 = gimg1->width; h1 = gimg1->height; float * iarr1 = new float[w1*h1]; for(int i=0;i<h1;i++) { for(int j=0;j<w1;j++) { s=cvGet2D(gimg1,i,j); iarr1[i*w1+j] = s.val[0]; } } vector ipixels1(iarr1, iarr1 + w1 * h1); delete [] iarr1; size_t w2, h2; w2 = gimg2->width; h2 = gimg2->height; float * iarr2 = new float[w2*h2]; for(int i=0;i<h2;i++) { for(int j=0;j<w2;j++) { s=cvGet2D(gimg2,i,j); iarr2[i*w2+j] = s.val[0]; } } vector ipixels2(iarr2, iarr2 + w2 * h2); delete [] iarr2; float wS = IM_X; float hS = IM_Y; float zoom1=0, zoom2=0; int wS1=0, hS1=0, wS2=0, hS2=0; vector ipixels1_zoom, ipixels2_zoom; if (!m_bOrininal) { if (m_lWidth==0 || m_lHeight == 0) return; wS = m_lWidth; hS = m_lHeight; float InitSigma_aa = 1.6; float fproj_p, fproj_bg; char fproj_i; float *fproj_x4, *fproj_y4; int fproj_o; fproj_o = 3; fproj_p = 0; fproj_i = 0; fproj_bg = 0; fproj_x4 = 0; fproj_y4 = 0; float areaS = wS * hS; // Resize image 1 float area1 = w1 * h1; zoom1 = sqrt(area1/areaS); wS1 = (int) (w1 / zoom1); hS1 = (int) (h1 / zoom1); int fproj_sx = wS1; int fproj_sy = hS1; float fproj_x1 = 0; float fproj_y1 = 0; float fproj_x2 = wS1; float fproj_y2 = 0; float fproj_x3 = 0; float fproj_y3 = hS1; /* Anti-aliasing filtering along vertical direction */ if ( zoom1 > 1 ) { float sigma_aa = InitSigma_aa * zoom1 / 2; GaussianBlur1D(ipixels1,w1,h1,sigma_aa,1); GaussianBlur1D(ipixels1,w1,h1,sigma_aa,0); } // simulate a tilt: subsample the image along the vertical axis by a factor of t. ipixels1_zoom.resize(wS1*hS1); fproj (ipixels1, ipixels1_zoom, w1, h1, &fproj;_sx, &fproj;_sy, &fproj;_bg, &fproj;_o, &fproj;_p, &fproj;_i , fproj_x1 , fproj_y1 , fproj_x2 , fproj_y2 , fproj_x3 , fproj_y3, fproj_x4, fproj_y4); // Resize image 2 float area2 = w2 * h2; zoom2 = sqrt(area2/areaS); wS2 = (int) (w2 / zoom2); hS2 = (int) (h2 / zoom2); fproj_sx = wS2; fproj_sy = hS2; fproj_x2 = wS2; fproj_y3 = hS2; /* Anti-aliasing filtering along vertical direction */ if ( zoom1 > 1 ) { float sigma_aa = InitSigma_aa * zoom2 / 2; GaussianBlur1D(ipixels2,w2,h2,sigma_aa,1); GaussianBlur1D(ipixels2,w2,h2,sigma_aa,0); } // simulate a tilt: subsample the image along the vertical axis by a factor of t. ipixels2_zoom.resize(wS2*hS2); fproj (ipixels2, ipixels2_zoom, w2, h2, &fproj;_sx, &fproj;_sy, &fproj;_bg, &fproj;_o, &fproj;_p, &fproj;_i , fproj_x1 , fproj_y1 , fproj_x2 , fproj_y2 , fproj_x3 , fproj_y3, fproj_x4, fproj_y4); } else { ipixels1_zoom.resize(w1*h1); ipixels1_zoom = ipixels1; wS1 = w1; hS1 = h1; zoom1 = 1; ipixels2_zoom.resize(w2*h2); ipixels2_zoom = ipixels2; wS2 = w2; hS2 = h2; zoom2 = 1; } int num_of_tilts1 = m_lTilts1; int num_of_tilts2 = m_lTilts2; int verb = 0; // Define the SIFT parameters siftPar siftparameters; default_sift_parameters(siftparameters); vector< vector > keys1; vector< vector > keys2; int num_keys1=0, num_keys2=0; SetWindowText("Computing keypoints on the two images..."); CString str1,str2; time_t tstart, tend1,tend2; tstart = time(0); DWORD dstart = GetTickCount(); num_keys1 = compute_asift_keypoints(ipixels1_zoom, wS1, hS1, num_of_tilts1, verb, keys1, siftparameters); tend1 = time(0); m_lKeyNum1 = num_keys1; UpdateData(FALSE); str1.Format("Img1 Keypoints computation accomplished in %f s",difftime(tend1, tstart)); SetWindowText(str1); num_keys2 = compute_asift_keypoints(ipixels2_zoom, wS2, hS2, num_of_tilts2, verb, keys2, siftparameters); tend2 = time(0); m_lKeyNum2 = num_keys2; UpdateData(FALSE); str2.Format("Img2 Keypoints computation accomplished in %f s ,Matching the keypoints...",difftime(tend2, tstart)); SetWindowText(str2); //// Match ASIFT keypoints int num_matchings; matchingslist matchings; tstart = time(0); num_matchings = compute_asift_matches(num_of_tilts1, num_of_tilts2, wS1, hS1, wS2, hS2, verb, keys1, keys2, matchings, siftparameters); tend1 = time(0); DWORD dSpan = GetTickCount() - dstart; cout << "Keypoints matching accomplished in " << difftime(tend1, tstart) << " seconds." << endl; str2.Format("Keypoints matching accomplished in %f s",difftime(tend1, tstart)); SetWindowText(str2); m_lMatches = num_matchings; UpdateData(FALSE); str1.Format("Total time used:%d ms",dSpan); AfxMessageBox(str1); cvRelease((void**)&gimg1;); cvRelease((void**)&gimg2;); 参考网址:http://www.ipol.im/pub/art/2011/my-asift/

ASIFT源码下载

ASITF算法出现已经很长时间了,这个算法主要是解决SIFT等特征提起算法在影像有较大倾斜角度时,同名点对提取较少的问题。有一些关于该算法的应用和改进算法效率的中文文章,一些博客也做了基本的介绍,但是总感觉大多是走马观花,讨论的不深入,希望对大家有所帮助。

【局部特征】ASIFT

      由于相机正面白摄物体时,相机的光轴方向可能发生变化,带来扭曲。而SIFT算法虽具有完全的尺度不变性,但不具有完全的仿射不变性,对拍摄角度发生大角度空间变化的图像特征提取有一定的局限性。ASift通过模拟经度与纬度实现完全的仿射不变,然后用SIFT算法把模拟图像进行比较,最后实现特征匹配。 ASIFT算法的具体步骤如下: 1.选取采样参数,模拟不同经度与纬度的图像。 2.计算模拟图...

weixin_34013044的博客 475

demo_ASIFT

两个文件夹:1.ASIFT源码(C++) 2.可以直接运行的ASIFT.exe

asfit算法学习

阿什顿发顺丰

jia_zhengshen的专栏 1962

Erie:OpenCV 的仿射匹配 C++ 库(基于 ASIFT)

伊利 OpenCV 的仿射匹配 C++ 库(基于 ASIFT) 算法 算法基于 AffineSIFT [1]。 给定一对图像,会生成每个图像的多个“视图”。 视图是通过仿射变换扭曲的原始图像,它显示了从某个预设视点看图像的样子。 通常,对于两个图像,拥有 10 个视图(9 个失真 + 1 个原始视图)或更少就足够了。 第一个图像的所有 10 个视图与第二个图像的所有 10 个视图成对匹配。 OpenCV 的feature2d模块用于匹配。 如果那些具有足够关键点匹配的对,则它们对结果有贡献。 大致思路就是这样。 与 ASIFT 的区别 可以使用 SIFT 的其他功能(ORB、SURF、BRISK、...) 实现了增量匹配。 如果图像不能在没有失真的情况下匹配,则使用倾斜 = 1 来创建失真的“视图”。 如果这还不够,则使用倾斜 = 2,依此类推。 编译 确保你有OpenCV和Boost库

CYUSB3065配置CMOS

按照OG02B10的时序电路,在通过SCCB配置CMOS之前,需要三个电源上电,Xshutdown高电平和配置时钟电路。找到手册的第6章SCCB(跟IIC很像),可以看到SCCB的地址与SID引脚有关,这个需要到硬件原理图上确认下。这是Cypress的一个支持MIPI和UVC的模块,有例程支持OV5640,现在要替换替换成OG02B10。寄存器参数需要找到厂家的FAE,由他们提供,OG02B10的资料已经上传。(2)参考得宏的电路,时钟由主控提供,目前程序未实现。这里有两个重要参数需要搞定,摄像头的。

qq_40773212的博客 2943

[ASIFT 0] ASIFT算法深入讲解

ASITF算法中文资料太少,本文深入的介绍ASIF

Y. LI 1万+

GNU Radio系列教程(一):什么是GNU Radio?为什么我需要用GNU Radio?

目录 一、什么是软件无线电? 二、GNU Radio到底能做什么事情? 三、我如果不精通编程,还能用GNU Radio吗? 四、GNU Radio使用需要授权吗? 五、基于GNU Radio,人们已经做了取得了哪些成果? 六、数字信号处理、基带、时钟同步…这些名词是什么意思? 七、有用的链接和联系方式 GNU Radio是一个免费的开源软件工具包,该工具包提供了可用于软件无线电的信号处理模块。基于一些通用的射频前端设备,该工具包可以用来实现软件无线电系统。此外,该工具包也可以用于单纯...

无线通信实验室 1万+

ORB图像特征匹配算法改进ASIFT算法——AORB算法

一、ORB算法原理 使用FAST算法进行特征点检测。将某点与其周围12个点进行比较,灰度值之差大于某个阙值则不同,若有n个不同则为特征点。 使用BRIEF算法描述特征点,生成描述符。在特征点周围取N个点对,将他们的比较结果作为描述子,相似为1,不相似为0,最后生成一串二进制符。 使用RANSAC算法(随机抽样一致算法)进行误匹配点剔除。首先剔除明显的错误点,再用最小二乘法(最小化误差的平方)拟合剩余点。 二、大视角匹配算法 ASIFT算法即仿射SIFT算法,利用仿射变换模型去模拟相机实际位置,从而估计

qq_43209593的博客 628

手把手教你实现阿克曼ROS小车的运动控制

本文详细介绍了如何从零开始实现阿克曼ROS小车的运动控制。内容涵盖硬件搭建、STM32底层PID速度与舵机控制、ROS层阿克曼运动学模型解析,以及上下位机通信协议设计。通过手把手的代码示例和调试步骤,帮助机器人爱好者与开发者掌握将高级速度指令转化为小车具体动作的全流程,实现流畅的阿克曼转向控制。

weixin_29193259的博客 198

大模型训练(1):流水线并行

Gpipe的方法是,在训练时计算和运用的是micro-batch里的均值和方差,但同时持续追踪全部mini-batch的移动平均和方差,以便在测试阶段进行使用。流水线并行的核心思想是:在模型并行的基础上,进一步引入数据并行的办法,即把原先的数据再划分成若干个更小的batch,分批送入GPU进行训练,算一部分就让下一个GPU动起来。从实验结果可知,在关掉NVlinks的情况下,Gpipe一样也能实现随着GPU数量的增加,训练速度也增加的效果。前文说过,随着模型的增加,每块GPU中存储的中间结果也会越大。

呆呆象呆呆的博客 1968
上一篇: Android提高十六篇之使用NDK把彩图转换灰度图
下一篇: 在Android上使用ZXing识别条形码/二维码
「已注销」
博客等级 码龄8年 1粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值