[开源]基于姿态估计的运动计数APP开发(三)
1、前言:
在上一期中[開源]基于姿態估計的運動計數APP開發(二)中,我們已經完成了仰臥起坐算法的開發和windows的demo開發。本期主要是將該算法一直到android平臺上面,實現一個android手機上可以使用的APP。下面的視頻是我在西湖邊進行的測試,在背景比較干凈的情況下,效果還不錯哦。【獲取APP源碼請留言,或者添加我的微信,15158106211,備注“仰臥起坐APP”,讓我們一起學習一起進步。】
(CSDN放不了視頻,請見諒)
2、模型改進
有的朋友已經發現,上一期的demo中,只有兩個關鍵點,頭部和膝蓋,而這次的APP有三個關鍵點,分別是頭部,腰部和膝蓋。當只有兩個關鍵點的時候,模型很容易出現誤識別,會把關鍵點定位在一些其他東西上面,很少會考慮這是不是屬于一個人的特征。而使用了三個關鍵點之后,一方面更加有利于判斷姿勢,另一方面也相對于增加了一個監督信號,并且三個關鍵點都位于人身上,使得模型更容易理解和學習。因此在性能上有一定的提升,主要是降低了誤識別率。
3、APP框架
APP主要要Activiry類,兩個SurfaceView類,一個Alg類,一個Camera類組成。Alg類主要負責調用算法進行推理,并返回結果。這里我已經將pytorch訓練好的模型轉換成了NCNN模型,因此實際上是調用的NCNN庫的推理功能。Camera類主要負責攝像頭的打開和關閉,以及進行預覽回調。第一個SurfaceView(DisplayView)主要用于攝像頭預覽的展示。第二個SurfaceView(CustomView)主要用于繪制一些關鍵點信息,計數統計信息等。Activity就是最上層的一個管理類,負責管理整個APP,包括創建按鈕,創建SurfaceView,創建Alg類,創建Camera類等。
3、主要類源碼
3.1、Activity類核心源碼
public class MainActivity extends Activity implements Camera.PreviewCallback, AlgCallBack{private DisplayView mViewDisplay;private CustomView mViewCustom;private Button mBtnCameraOp;private Button mBtnCameraChange;private CameraUtil mCameraUtil;private AlgUtil mAlgUtil;private int mFrameCount = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {Log.i("zhengxing", "MainActivity::onCreate");super.onCreate(savedInstanceState);this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);this.requestWindowFeature(Window.FEATURE_NO_TITLE);this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);setContentView(R.layout.main);Log.i("zhengxing", "MainActivity::onCreate set basic info finished");// 創建兩個SurfaceViewmViewDisplay = (DisplayView)this.findViewById(R.id.display_view);mViewCustom = (CustomView)this.findViewById(R.id.custom_view);Log.i("zhengxing", "MainActivity::onCreate create visual toolkits finished");//初始化camera類和alg類mCameraUtil = new CameraUtil(mViewDisplay, this);mAlgUtil = new AlgUtil(getAssets(), this);Log.i("zhengxing", "MainActivity::onCreate create camera util and alg util finished");}// 開始按鈕public void onBtnStartClick(View view){Log.i("zhengxing", "MainActivity::onBtnStartClick");if (mCameraUtil.getCameraState() < 0){mCameraUtil.openCamera();Log.i("zhengxing", "MainActivity::onBtnStartClick the camera is closed, open it");}}//停止按鈕public void onBtnStopClick(View view){Log.i("zhengxing", "MainActivity::onBtnStopClick");if (mCameraUtil.getCameraState() >= 0){mCameraUtil.closeCamera();Log.i("zhengxing", "MainActivity::onBtnStopClick the camera is open, close it");}}//算法回調函數,處理算法返回結果@Overridepublic void onAlgRet(float[] ret) {float nAlgType = ret[0];float nClasss = ret[1];Log.i("zhengxing", "MainActivity::onAlgRet ret value:" + ret[0] + ';' + ret[1]);mViewCustom.drawAlgRet(ret);}//預覽回調函數,處理每一幀圖片@Overridepublic void onPreviewFrame(byte[] data, Camera camera) {mFrameCount ++;Log.i("zhengxing", "MainActivity::onPreviewFrame");Camera.Size size = camera.getParameters().getPreviewSize();mAlgUtil.addDataToQueue(data, size.width, size.height);}}3.2、Camera類核心源碼
public class CameraUtil {private Camera mCamera;private final int mCameraID;private final SurfaceView mViewDisplay;private final int mOrientation;private final Camera.PreviewCallback mPreviewCBack;public CameraUtil(SurfaceView displayView, Camera.PreviewCallback cameraCBack) {Log.i("zhengxing", "CameraUtil::CameraUtil");mCamera = null;mViewDisplay = displayView;mCameraID = Camera.CameraInfo.CAMERA_FACING_FRONT;mOrientation = 0;mPreviewCBack = cameraCBack;}//打開攝像頭public void openCamera() {Log.i("zhengxing", "CameraUtil::openCamera");if(mCamera == null) {mCamera = Camera.open(mCameraID);Camera.Parameters parameters = mCamera.getParameters();//parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);//mCamera.setParameters(parameters);mCamera.setDisplayOrientation(mOrientation);mCamera.setPreviewCallback(mPreviewCBack);try {mCamera.setPreviewDisplay(mViewDisplay.getHolder());} catch (IOException e) {e.printStackTrace();}mCamera.startPreview();}}//關閉攝像頭public void closeCamera() {Log.i("zhengxing", "CameraUtil::closeCamera");if (mCamera != null) {mCamera.setPreviewCallback(null);mCamera.stopPreview();mCamera.release();mCamera = null;}} }3.3、Alg類核心源碼
class AlgUtil implements Runnable {private boolean mThreadFlag;private final ArrayBlockingQueue mQueue;private final Alg mAlg;private final int mAlgThreads;private AlgCallBack mAlgCB;private final Thread mThread;public AlgUtil(AssetManager assertManager, AlgCallBack algCallBack) {Log.i("zhengxing", "AlgUtil::AlgUtil");mAlgCB = algCallBack;mAlgThreads = 1;mQueue = new ArrayBlockingQueue(3);mAlg = new Alg();mAlg.Init(assertManager);mThreadFlag = true;mThread = new Thread(this);mThread.start();}//將預覽圖片投遞到隊列中(由于算法處理可能會比較慢,并不是每一幀圖片都做算法處理)public boolean addDataToQueue(byte [] bytes, int width, int height) {Log.i("zhengxing", "AlgUtil::addDataToQueue");Bitmap bmp = null;try {YuvImage image = new YuvImage(bytes, ImageFormat.NV21, width, height, null);if (image != null) {ByteArrayOutputStream stream = new ByteArrayOutputStream();image.compressToJpeg(new Rect(0, 0, width, height), 100, stream);bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());stream.close();}} catch (Exception ex) {}Bitmap rgba = bmp.copy(Bitmap.Config.ARGB_8888, true);Bitmap imgSelect = Bitmap.createScaledBitmap(rgba, 312, 312, false);rgba.recycle();return mQueue.offer(imgSelect);}//返回算法推理結果給上層(Activity)public void setCallBack(AlgCallBack callBack) {Log.i("zhengxing", "AlgUtil::setCallBack");this.mAlgCB = callBack;}//線程體(所有算法推理都在線程中執行)@Overridepublic void run() {Log.i("zhengxing", "AlgUtil::run");while (mThreadFlag) {try {Bitmap bmp = (Bitmap) mQueue.poll(1000, TimeUnit.MILLISECONDS);if (bmp != null) {float[] x = mAlg.Run(bmp);this.mAlgCB.onAlgRet(x);}} catch (InterruptedException e) {e.printStackTrace();}}} }4、總結
這次仰臥起坐APP開發前后經歷了大約一個月的時間,都是在晚上或者周末進行的。雖然很累,但是我也學到了很多東西。從原來完全不了解姿態估計這個領域,以及嚴重低估關鍵點檢測的難度,到后來慢慢學習,整理相關論文,解決一個又一個難點,對我自己來說是一次極大的提升,也是對自己興趣愛好的執著。如果整個過程也讓你也有一點點的收獲,那將是對我極大的鼓勵。【獲取APP源碼請留言或者添加我的微信,15158106211,備注“仰臥起坐APP”,讓我們一起學習一起進步。】
總結
以上是生活随笔為你收集整理的[开源]基于姿态估计的运动计数APP开发(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2个月没人管!AMD老显卡终于要有新驱动
- 下一篇: 基于安卓手机的辅助驾驶APP开发