您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“如何實現(xiàn)物體檢測與跟蹤”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
實現(xiàn)步驟
圖片預(yù)處理:在圖像預(yù)處理環(huán)節(jié),通過編碼、閾值及濾波、改善模式、離散模式運算等基本運算方式,在盡可能保留圖像所有內(nèi)容信息的基礎(chǔ)上,整理突出圖像特征,以達到最佳圖像特征提取的狀態(tài)。
圖像特征提取:經(jīng)過預(yù)處理的圖像在特征提取環(huán)節(jié),提取出價值高的特征,使高維特征空間擁有更好的分離性,更便于進行算法識別。圖像特征提取一般細(xì)分成幾個模塊來進行:灰度值、亮度值、形狀、紋理等視覺上的基本特征提??;基于像素點顏色的顏色特征提??;物體紋理及結(jié)構(gòu)材質(zhì)的紋理特征提?。换谳喞突趨^(qū)域的形狀特征提??;以及圖像分割出的多個目標(biāo)之間空間位置關(guān)系信息的空間特征提取。
特征選擇:特征提取后,可根據(jù)具體物體識別情況進行特征選擇。比如在特征種類繁多、物體種類多的情況下,通過特征選擇找到各個特征適配的場合。
建模:特征選擇之后,在建模環(huán)節(jié)建立特征集合,分辨異同點,提取相同點,主要建模對象是特征與特征之間的空間結(jié)構(gòu)關(guān)系。
匹配:匹配環(huán)節(jié)是用模型去識別匹配新圖像,識別圖像屬于哪類物體,條件符合可將物體與圖像其他部分分離。
定位:物體識別后進行對目標(biāo)物體的定位,即將識別到的物體坐標(biāo)與實際物理空間坐標(biāo)結(jié)合起來,之后可以進行對應(yīng)的跟蹤和模型疊加處理。
華為AR Engine提供的三大能力分別是運動跟蹤、環(huán)境跟蹤、人體和人臉跟蹤。
運動跟蹤主要通過終端設(shè)備攝像頭標(biāo)識特征點,并跟蹤這些特征點的移動變化,來不斷跟蹤終端設(shè)備位置和姿態(tài)。
環(huán)境跟蹤可以識別平面,如地面、墻壁等,也可估測平面周圍的光照強度。
人體和人臉跟蹤讓終端設(shè)備具備了對人的理解能力。通過定位人的手部位置和對特定手勢的識別,可將虛擬物體或內(nèi)容特效放置在人的手上;結(jié)合深度器件,還可精確還原手部的21個骨骼點的運動跟蹤,做更為精細(xì)化的交互控制和特效疊加;當(dāng)識別范圍擴展到人的全身時,可利用識別到的23個人體關(guān)鍵位置,實時的檢測人體的姿態(tài),為體感和運動健康類的應(yīng)用開發(fā)提供能力支撐。
在AndroidManifest.xml中添加權(quán)限
打開main中的AndroidManifest.xml文件,在<application 前添加對相機的權(quán)限聲明,需要注意的是代碼中還需要動態(tài)進行權(quán)限申請,否則會有Permission Denied報錯
<uses-permission android:name="android.permission.CAMERA" />
配置MainActivity的顯示效果
首先通過 MainActivity extends Activity implements GLSurfaceView.Renderer創(chuàng)建MainActivity,在MainActivity的layout文件中新建一個GLSurfaceView,用于顯示攝像頭拍攝的實時畫面,提供給AREngine進行識別:
<android.opengl.GLSurfaceView android:id="@+id/surfaceview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="top" />
在MainActivity的onCreate階段進行SurfaceView的配置:
private GLSurfaceView mSurfaceView; private static final int CONFIG_CHOOSER_RED_SIZE = 8; private static final int CONFIG_CHOOSER_GREEN_SIZE = 8; private static final int CONFIG_CHOOSER_BLUE_SIZE = 8; private static final int CONFIG_CHOOSER_ALPHA_SIZE = 8; private static final int CONFIG_CHOOSER_DEPTH_SIZE = 16; private static final int CONFIG_CHOOSER_STENCIL_SIZE = 0; private static final int OPENGLES_VERSION = 2; mSurfaceView = findViewById(R.id.surfaceview); mSurfaceView.setPreserveEGLContextOnPause(true); mSurfaceView.setEGLContextClientVersion(OPENGLES_VERSION); mSurfaceView.setEGLConfigChooser(CONFIG_CHOOSER_RED_SIZE, // Alpha used for plane blending. CONFIG_CHOOSER_GREEN_SIZE, CONFIG_CHOOSER_BLUE_SIZE, CONFIG_CHOOSER_ALPHA_SIZE, CONFIG_CHOOSER_DEPTH_SIZE, CONFIG_CHOOSER_STENCIL_SIZE); // Alpha used for plane blending. mSurfaceView.setRenderer(this); mSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
加載一張框圖文件,用于標(biāo)記識別的位置,引導(dǎo)用戶進行物體識別:
fitToScanView = findViewById(R.id.image_view_fit_to_scan); InputStream bitmapstream; try { bitmapstream = getAssets().open("fit_to_scan.png"); } catch (IllegalArgumentException | IOException e) { Log.d(TAG, "open bitmap failed!"); return; } Bitmap bitmap = BitmapFactory.decodeStream(bitmapstream); fitToScanView.setImageBitmap(bitmap);
AREngine檢測和配置權(quán)限申請
物體識別功能的使用需要設(shè)備支持AREngine,并且已經(jīng)安裝了AREngine的APK包,所以要對運行的設(shè)備進行判斷,是否支持該功能
rivate boolean arEngineAbilityCheck() { boolean isInstallArEngineApk = AREnginesApk.isAREngineApkReady(this); if (!isInstallArEngineApk && isRemindInstall) { Toast.makeText(this, "Please agree to install.", Toast.LENGTH_LONG).show(); finish(); } Log.d(TAG, "Is Install AR Engine Apk: " + isInstallArEngineApk); if (!isInstallArEngineApk) { //Code of jumping to AppGallery to download the APK isRemindInstall = true; } return AREnginesApk.isAREngineApkReady(this); }
AREngine檢測完成之后,再進行相機權(quán)限的動態(tài)申請
private static final String[] PERMISSIONS_ARRAYS = new String[]{Manifest.permission.CAMERA}; public static void requestPermission(final Activity activity) { Log.d(TAG, "requestPermission >>"); for (String permission : PERMISSIONS_ARRAYS) { if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { permissionsList.add(permission); } } ActivityCompat.requestPermissions(activity, permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_PERMISSIONS); Log.d(TAG, "requestPermission <<"); }
以上步驟完成之后,說明設(shè)備支持AREngine的物體識別功能,并且已經(jīng)獲得了相機的使用權(quán)限,接下來就可以創(chuàng)建ARSession,并進行識別數(shù)據(jù)庫的配置
配置物體識別數(shù)據(jù)庫
在進行物體識別之前,要將想識別的對象的圖片添加到數(shù)據(jù)庫中,使用的是ARAugmentedImageDatabase,創(chuàng)建一個boolean函數(shù),進行數(shù)據(jù)庫的圖片添加,并給后續(xù)是否進行識別作判斷:
private boolean setupAugmentedImageDatabase(ARWorldTrackingConfig config) { ARAugmentedImageDatabase augmentedImageDatabase; Optional<Bitmap> augmentedImageBitmapOptional = loadAugmentedImageBitmap(); Bitmap augmentedImageBitmap = null; if (augmentedImageBitmapOptional.isPresent()) { augmentedImageBitmap = loadAugmentedImageBitmap().get(); } else { return false; } if (augmentedImageBitmap == null) { return false; } augmentedImageDatabase = new ARAugmentedImageDatabase(mSession); augmentedImageDatabase.addImage("image_name", augmentedImageBitmap); config.setAugmentedImageDatabase(augmentedImageDatabase); String text = String.format(Locale.ROOT, "has set ImageNum: %d", augmentedImageDatabase.getNumImages()); messageSnackbarHelper.showMessage(this, text); return true; }
所添加的識別圖片源可以放置在Assets文件夾內(nèi),通過InputStream打開為Bitmap的格式
private Optional<Bitmap> loadAugmentedImageBitmap() { try (InputStream is = getAssets().open("cup.jpg")) { return Optional.of(BitmapFactory.decodeStream(is)); } catch (IOException e) { Log.e(TAG, "IO exception loading augmented image bitmap.", e); } return Optional.empty(); }
配置識別后顯示效果
在MainActivity的onDrawFrame中配置識別到物體之后的顯示效果,在檢測到要識別的物體后,用一個方框?qū)⒆R別的物體標(biāo)識出來。
public void onDrawFrame(GL10 unused) { Log.d(TAG, "onDrawFrame >>"); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); if (mSession == null) { Log.d(TAG, "onDrawFrame mSession is null"); return; } try { ARFrame frame = mSession.update(); ARCamera camera = frame.getCamera(); if (camera.getTrackingState() == ARTrackable.TrackingState.PAUSED) { return; } Log.d(TAG, "ARTrackable.TrackingState" + camera.getTrackingState()); drawAugmentedImages(frame, projmtx, viewmtxs, colorCorrectionRgbas); } catch (Throwable t) { Log.e(TAG, "Exception on the OpenGL thread", t); } Log.d(TAG, "onDrawFrame <<"); }
判斷是否識別到物體時,調(diào)用ARAugmentedImage的getTrackingStatus方法,如果是TRACKING的話,則為識別到了
switch (augmentedImage.getTrackingState()) { case TRACKING: augmentedImageRenderer.draw(viewmtxs, projmtx, augmentedImage, centerAnchor, colorCorrectionRgbas); break; default: break; }
之后通過getCenterPose獲取物體的中心位置信息,將邊框添加到顯示中
anchorPose = augmentedImage.getCenterPose(); float scaleFactor = 1.0f; float[] modelMatrixs = new float[MODEL_MATRIX_SIZE]; float[] tintColors = convertHexToColor(TINT_COLORS_HEXS[augmentedImage.getIndex() % TINT_COLORS_HEXS.length]); worldBoundaryPoses[0].toMatrix(modelMatrixs, 0); imageFrameUpperLeft.updateModelMatrix(modelMatrixs, scaleFactor); imageFrameUpperLeft.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColors); worldBoundaryPoses[1].toMatrix(modelMatrixs, 0); imageFrameUpperRight.updateModelMatrix(modelMatrixs, scaleFactor); imageFrameUpperRight.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColors); worldBoundaryPoses[2].toMatrix(modelMatrixs, 0); imageFrameLowerRight.updateModelMatrix(modelMatrixs, scaleFactor); imageFrameLowerRight.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColors); worldBoundaryPoses[3].toMatrix(modelMatrixs, 0); imageFrameLowerLeft.updateModelMatrix(modelMatrixs, scaleFactor); imageFrameLowerLeft.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColors);
“如何實現(xiàn)物體檢測與跟蹤”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。