diff --git a/.gitignore b/.gitignore index 532601bfe9222eae0d6be7378322ab1b9c2eb110..547e94ea11f048c9e007996d4ee716d22a13742e 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,10 @@ build # clion building directories cmake-build-debug cmake-build-release + + +#ios demo +demo/ios/PaddleMobileDemo/PaddleMobileDemo/googlenet_combine/ +demo/ios/PaddleMobileDemo/PaddleMobileDemo/*.jpg +demo/ios/PaddleMobileDemo/PaddleMobileDemo/PaddleMobile/*.a +*.xcuserstate \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 89473e9f329a0a37dd3ed24f20e13d00513fca1f..a00d179a0d4972080c8fd392160f8ec451692e4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,15 +11,19 @@ option(MALI_GPU "mali gpu" OFF) option(FPGA "fpga" OFF) set(DEBUGING ON) -file(GLOB_RECURSE PADDLE_MOBILE_CC src/*.cc src/*.cpp src/*.c) +if (ARM_LINUX) +include("${CMAKE_CURRENT_LIST_DIR}/tools/arm-platform.cmake") +endif () + +file(GLOB_RECURSE PADDLE_MOBILE_CC src/*.cc src/*.cpp src/*.c src/*.mm) file(GLOB_RECURSE PADDLE_MOBILE_H src/*.h) if (CPU) add_definitions(-DPADDLE_MOBILE_CPU) else() - list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/operators/kernel/arm/*.h) - list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/operators/kernel/arm/*.cc) - list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/operators/kernel/arm/*.cpp) + list(REMOVE_ITEM PADDLE_MOBILE_CC ./src/operators/kernel/arm/*.h) + list(REMOVE_ITEM PADDLE_MOBILE_CC ./src/operators/kernel/arm/*.cc) + list(REMOVE_ITEM PADDLE_MOBILE_CC ./src/operators/kernel/arm/*.cpp) endif() @@ -37,9 +41,15 @@ if (MALI_GPU) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lOpenCL") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_ACL=1") else() - list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/operators/kernel/mali/*.h) - list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/operators/kernel/mali/*.cc) - list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/operators/kernel/mali/*.cpp) + file(GLOB_RECURSE _tmp_list src/operators/kernel/mali/*.cpp src/operators/kernel/mali/*.cc) + foreach(f ${_tmp_list}) + list(REMOVE_ITEM PADDLE_MOBILE_CC ${f}) + endforeach() + + file(GLOB_RECURSE _tmp_list_h src/operators/kernel/mali/*.h) + foreach(f ${_tmp_list_h}) + list(REMOVE_ITEM PADDLE_MOBILE_H ${f}) + endforeach() endif() if(FPGA) @@ -88,9 +98,9 @@ endif() if (NOT ANDROID_NDK_TOOLCHAIN_INCLUDED) - list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/jni/*.cpp) - list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/jni/*.h) - list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/operators/math/math_func_neon.h) + list(REMOVE_ITEM PADDLE_MOBILE_H ${CMAKE_CURRENT_SOURCE_DIR}/src/jni/paddle_mobile_jni.h) + list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/jni/paddle_mobile_jni.cpp) + list(REMOVE_ITEM PADDLE_MOBILE_H ${CMAKE_CURRENT_SOURCE_DIR}/src/operators/math/math_func_neon.h) endif () include_directories(src/) @@ -107,11 +117,18 @@ set_property(CACHE NET PROPERTY STRINGS "defult" "googlenet" "mobilenet" "yolo" include("${CMAKE_CURRENT_LIST_DIR}/tools/op.cmake") -# if (IS_IOS) -# add_library(paddle-mobile STATIC ${PADDLE_MOBILE_CC} ${PADDLE_MOBILE_H}) +if (IS_IOS) + add_library(paddle-mobile STATIC ${PADDLE_MOBILE_CC} ${PADDLE_MOBILE_H}) +else() + list(REMOVE_ITEM PADDLE_MOBILE_H ${CMAKE_CURRENT_SOURCE_DIR}/src/ios_io/PaddleMobile.h) + list(REMOVE_ITEM PADDLE_MOBILE_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/ios_io/PaddleMobile.mm) + list(REMOVE_ITEM PADDLE_MOBILE_H ${CMAKE_CURRENT_SOURCE_DIR}/src/ios_io/op_symbols.h) +endif () + if (ANDROID_NDK_TOOLCHAIN_INCLUDED) list(REMOVE_DUPLICATES CMAKE_CXX_FLAGS) add_library(paddle-mobile SHARED ${PADDLE_MOBILE_CC} ${PADDLE_MOBILE_H}) +elseif(IS_IOS) else () add_library(paddle-mobile SHARED ${PADDLE_MOBILE_CC} ${PADDLE_MOBILE_H}) endif () diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f07b2eeb93daa827361acc97951483c21092135f..a33db73e109042276b686e8ab74261273df87390 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -183,7 +183,6 @@ upstream 接下来等待 review,如果有需要修改的地方,参照上述步骤更新 origin 中的对应分支即可。 - ![](http://otkwwi4x8.bkt.clouddn.com/2018-06-20-15294877166787.jpg) 之后就可以提交代码了 @@ -223,7 +222,6 @@ upstream - 原因:如果仅仅修改一个文件但提交了十几个commit,每个commit只做了少量的修改,这会给评审人带来很大困扰。评审人需要逐一查看每个commit才能知道做了哪些修改,且不排除commit之间的修改存在相互覆盖的情况。 - 建议:每次提交时,保持尽量少的commit,可以通过`git commit --amend`补充上次的commit。对已经Push到远程仓库的多个commit,可以参考[squash commits after push](http://stackoverflow.com/questions/5667884/how-to-squash-commits-in-git-after-they-have-been-pushed)。 - 请注意每个commit的名称:应能反映当前commit的内容,不能太随意。 - 3. 如果解决了某个Issue的问题,请在该Pull Request的**第一个**评论框中加上:`fix #issue_number`,这样当该Pull Request被合并后,会自动关闭对应的Issue。关键词包括:close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved,请选择合适的词汇。详细可参考[Closing issues via commit messages](https://help.github.com/articles/closing-issues-via-commit-messages)。 此外,在回复评审人意见时,请您遵守以下约定: diff --git a/Dockerfile b/Dockerfile index 8f54b870d594ece33d9c93ea40908668d3ad2f0e..df7df032acefd39c20051e861d353644e3b91024 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,6 @@ RUN apt-get install -y --no-install-recommends \ unzip \ git \ make \ - cmake \ cmake-curses-gui \ python \ python-pip \ @@ -25,9 +24,14 @@ RUN apt-get install -y --no-install-recommends \ g++-arm-linux-gnueabi \ gcc-arm-linux-gnueabi RUN apt-get autoremove -y && apt-get clean -RUN pip install --upgrade pip -RUN pip install wheel && pip install pre-commit RUN ln -s clang-format-5.0 /usr/bin/clang-format +RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip +RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple wheel +RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pre-commit RUN cd /tmp && curl -O http://mirrors.neusoft.edu.cn/android/repository/android-ndk-r17b-linux-x86_64.zip +RUN curl -O https://mms-res.cdn.bcebos.com/cmake-3.10.3-Linux-x86_64.tar.gz && \ + tar xzf cmake-3.10.3-Linux-x86_64.tar.gz && \ + mv cmake-3.10.3-Linux-x86_64 /opt/cmake-3.10 && \ + mv /usr/bin/cmake /usr/bin/cmake.bak && ln -s /opt/cmake-3.10/bin/cmake /usr/bin/cmake RUN cd /opt && unzip /tmp/android-ndk-r17b-linux-x86_64.zip ENV NDK_ROOT /opt/android-ndk-r17b diff --git a/README.md b/README.md index f8957545a64fff7723bd4c1c6bc2db1fd90d728b..b299879ab73dde1d4e6b749596cfed6bf1888e9e 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,20 @@ [![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](LICENSE)--> - 欢迎来到 Paddle-Mobile GitHub 项目。 Paddle-Moible是PaddlePaddle组织下的项目,是一个致力于嵌入式平台的深度学习的框架。Paddle-Moible设计思想和PaddlePaddle的最新版fluid版本保持了高度一致,同时针对嵌入式做了大量优化。设计之初就对嵌入式的性能、体积、能耗、硬件平台覆盖等方面做了考虑。 +## 简单搜索线上效果 + +如下gif是简单搜索app的线上主体检测应用效果 + +![ezgif-1-050a733dfb](http://otkwwi4x8.bkt.clouddn.com/2018-07-05-ezgif-1-050a733dfb.gif) + +## Demo目录 + +[点我](https://github.com/PaddlePaddle/paddle-mobile/tree/develop/demo) + ## Features - **ARM CPU** @@ -23,7 +32,6 @@ Paddle-Moible是PaddlePaddle组织下的项目,是一个致力于嵌入式平 - **Mali GPU** Mali GPU是百度和ARM合作开发的,双方团队近期都在致力于将paddle的op能无缝运行在ACL(arm compute library)。目前已经支持squeezenet,googlenet,resnet等几个网络模型,后续会继续加大力度。使全部移动端paddle op能高效运行在mali gpu上。 - 在 - **苹果设备的GPU Metal实现** @@ -45,7 +53,7 @@ Paddle-Moible是PaddlePaddle组织下的项目,是一个致力于嵌入式平 - **体积** paddle-mobile从设计之初就深入考虑到移动端的包体积的问题,cpu实现中没有外部依赖。在编译过程中,如果该网络不需要的op是完全不会被打入的。同时编译选项优化也为体积压缩提供了帮助。 - 除了二进制体积,我们对代码体积极力避免过大。整个仓库不到5m的代码体积。 + 除了二进制体积,我们对代码体积极力避免过大。整个仓库的代码体积也非常小。 ## 文档 @@ -78,14 +86,7 @@ ONNX全称为“Open Neural Network Exchange”,即“开放的神经网络切 目前,百度也在做onnx支持工作。相关转换项目在这里:[paddle-onnx](https://github.com/PaddlePaddle/paddle-onnx)。 -```flow -st=>start: 其他模型 -op1=>operation: onnx模型 -op2=>operation: paddle-onnx -op3=>operation: paddle fluid模型 -e=>end: paddle-mobile运行 -st->op1->op2->op3->e -``` +![](http://otkwwi4x8.bkt.clouddn.com/2018-07-03-15305875853057.jpg) ### 4. 部分测试模型下载 [下载链接](https://mms-mis.cdn.bcebos.com/paddle-mobile/models.zip) diff --git a/demo/android/PaddleMobile_Android/.gitignore b/demo/android/PaddleMobile_Android/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..39fb081a42a86ccf8f9cf99dbccc8bdf7c828bce --- /dev/null +++ b/demo/android/PaddleMobile_Android/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/demo/android/PaddleMobile_Android/app/.gitignore b/demo/android/PaddleMobile_Android/app/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/demo/android/PaddleMobile_Android/app/.gitignore @@ -0,0 +1 @@ + diff --git a/demo/android/PaddleMobile_Android/app/build.gradle b/demo/android/PaddleMobile_Android/app/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..3d61efb83a083909a0038886469e1c7fce218e8c --- /dev/null +++ b/demo/android/PaddleMobile_Android/app/build.gradle @@ -0,0 +1,23 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 21 + defaultConfig { + applicationId "com.baidu.paddle" + minSdkVersion 15 + targetSdkVersion 21 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:21.0.3' +} diff --git a/demo/android/PaddleMobile_Android/app/proguard-rules.pro b/demo/android/PaddleMobile_Android/app/proguard-rules.pro new file mode 100644 index 0000000000000000000000000000000000000000..f1b424510da51fd82143bc74a0a801ae5a1e2fcd --- /dev/null +++ b/demo/android/PaddleMobile_Android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/demo/android/PaddleMobile_Android/app/src/main/AndroidManifest.xml b/demo/android/PaddleMobile_Android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..b9bf81dcb9fffb855d067cc7df1633ebcf586432 --- /dev/null +++ b/demo/android/PaddleMobile_Android/app/src/main/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/demo/android/PaddleMobile_Android/app/src/main/java/com/baidu/paddle/MainActivity.java b/demo/android/PaddleMobile_Android/app/src/main/java/com/baidu/paddle/MainActivity.java new file mode 100755 index 0000000000000000000000000000000000000000..febe816681d3845a61c5a8b40630e82ac9b4ea95 --- /dev/null +++ b/demo/android/PaddleMobile_Android/app/src/main/java/com/baidu/paddle/MainActivity.java @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2016 Baidu, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +package com.baidu.paddle; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; + +import android.provider.MediaStore; + +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; + +import static android.graphics.Color.blue; +import static android.graphics.Color.green; +import static android.graphics.Color.red; +import static com.baidu.paddle.MainActivity.TYPE.googlenet; + + +public class MainActivity extends Activity { + public static final int TAKE_PHOTO_REQUEST_CODE = 1001; + + private Context mContext = null; + + private int inputSize = 224; + + enum TYPE { + googlenet + } + + private TYPE type = googlenet; + private ImageView imageView; + private TextView tvSpeed; + private Button button; + private Bitmap bmp; + + static { + try { + System.loadLibrary("paddle-mobile"); + + } catch (SecurityException e) { + e.printStackTrace(); + + } catch (UnsatisfiedLinkError e) { + e.printStackTrace(); + + } catch (NullPointerException e) { + e.printStackTrace(); + + } + + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mContext = this; + setContentView(R.layout.main_activity); + init(); + } + + private void init() { + imageView = (ImageView) findViewById(R.id.imageView); + tvSpeed = (TextView) findViewById(R.id.tv_speed); + button = (Button) findViewById(R.id.button); + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (!isHasSdCard()) { + Toast.makeText(mContext, R.string.sdcard_not_available, + Toast.LENGTH_LONG).show(); + return; + } + Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + // save pic in sdcard + Uri imageUri = Uri.fromFile(getTempImage()); + intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); + startActivityForResult(intent, TAKE_PHOTO_REQUEST_CODE); + + } + }); + Button bt_load = (Button) findViewById(R.id.bt_load); + bt_load.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + String assetPath = "pml_demo"; + String sdcardPath = Environment.getExternalStorageDirectory() + + File.separator + assetPath + File.separator + type; + PML.load(sdcardPath); + + } + }); + Button bt_clear = (Button) findViewById(R.id.bt_clear); + bt_clear.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + PML.clear(); + + + } + }); + String assetPath = "pml_demo"; + String sdcardPath = Environment.getExternalStorageDirectory() + + File.separator + assetPath; + copyFilesFromAssets(this, assetPath, sdcardPath); + + + } + + public void copyFilesFromAssets(Context context, String oldPath, String newPath) { + try { + String[] fileNames = context.getAssets().list(oldPath); + if (fileNames.length > 0) { + // directory + File file = new File(newPath); + file.mkdirs(); + // copy recursivelyC + for (String fileName : fileNames) { + copyFilesFromAssets(context, oldPath + "/" + fileName, + newPath + "/" + fileName); + } + } else { + // file + InputStream is = context.getAssets().open(oldPath); + FileOutputStream fos = new FileOutputStream(new File(newPath)); + byte[] buffer = new byte[1024]; + int byteCount; + while ((byteCount = is.read(buffer)) != -1) { + fos.write(buffer, 0, byteCount); + } + fos.flush(); + is.close(); + fos.close(); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public File getTempImage() { + if (Environment.getExternalStorageState().equals( + Environment.MEDIA_MOUNTED)) { + File tempFile = new File(Environment.getExternalStorageDirectory(), "temp.jpg"); + try { + tempFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + + return tempFile; + } + return null; + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + switch (requestCode) { + case TAKE_PHOTO_REQUEST_CODE: + if (resultCode == RESULT_OK) { + DetectionTask detectionTask = new DetectionTask(); + detectionTask.execute(getTempImage().getPath()); + } + break; + default: + break; + } + } + + /** + * draw rect on imageView + * + * @param bitmap + * @param predicted + * @param viewWidth + * @param viewHeight + */ + private void drawRect(Bitmap bitmap, float[] predicted, int viewWidth, int viewHeight) { + + Canvas canvas = new Canvas(bitmap); + canvas.drawBitmap(bitmap, 0, 0, null); + if (type == googlenet) { + Paint paint = new Paint(); + paint.setColor(Color.RED); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(3.0f); + float x1 = 0; + float x2 = 0; + float y1 = 0; + float y2 = 0; + + // the googlenet result sequence is (left top right top bottom) + x1 = (predicted[0] * viewWidth / 224); + y1 = (predicted[1] * viewHeight / 224); + x2 = (predicted[2] * viewWidth / 224); + y2 = (predicted[3] * viewHeight / 224); + + + canvas.drawRect(x1, y1, x2, y2, paint); + } + + + imageView.setImageBitmap(bitmap); + + } + + float getMaxIndex(float[] predicted) { + float max = 0; + int index = 0; + for (int i = 0; i < predicted.length; i++) { + if (predicted[i] > max) { + max = predicted[i]; + index = i; + } + } + return index; + } + + public float[] getScaledMatrix(Bitmap bitmap, int desWidth, + int desHeight) { + float[] dataBuf = new float[3 * desWidth * desHeight]; + int rIndex; + int gIndex; + int bIndex; + int[] pixels = new int[desWidth * desHeight]; + Bitmap bm = Bitmap.createScaledBitmap(bitmap, desWidth, desHeight, false); + bm.getPixels(pixels, 0, desWidth, 0, 0, desWidth, desHeight); + int j = 0; + int k = 0; + for (int i = 0; i < pixels.length; i ++) { + int clr = pixels[i]; + j = i / desHeight; + k = i % desWidth; + rIndex = j * desWidth + k; + gIndex = rIndex + desHeight * desWidth; + bIndex = gIndex + desHeight * desWidth; + dataBuf[rIndex] = (float)((clr & 0x00ff0000)>> 16) -148; + dataBuf[gIndex] = (float)((clr & 0x0000ff00)>> 8) - 148; + dataBuf[bIndex] = (float)((clr & 0x000000ff)) -148; + + } + if (bm.isRecycled()) { + bm.recycle(); + } + return dataBuf; + + + } + /** + * check whether sdcard is mounted + * + * @return + */ + public boolean isHasSdCard() { + if (Environment.getExternalStorageState().equals( + Environment.MEDIA_MOUNTED)) { + return true; + } else { + return false; + } + } + + public void dumpData(float[] results, String filename) { + try { + File writename = new File(filename); + writename.createNewFile(); + BufferedWriter out = new BufferedWriter(new FileWriter(writename)); + for (float result : results) { + out.write(result + " "); + } + out.flush(); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + /** + * scale bitmap in case of OOM + * + * @param ctx + * @param filePath + * @return + */ + public Bitmap getScaleBitmap(Context ctx, String filePath) { + BitmapFactory.Options opt = new BitmapFactory.Options(); + opt.inJustDecodeBounds = true; + BitmapFactory.decodeFile(filePath, opt); + + int bmpWidth = opt.outWidth; + int bmpHeight = opt.outHeight; + + int maxSize = 500; + + opt.inSampleSize = 1; + while (true) { + if (bmpWidth / opt.inSampleSize < maxSize || bmpHeight / opt.inSampleSize < maxSize) { + break; + } + opt.inSampleSize *= 2; + } + opt.inJustDecodeBounds = false; + Bitmap bmp = BitmapFactory.decodeFile(filePath, opt); + return bmp; + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + Log.d("mdl", "mdl clear"); + // clear mdl + PML.clear(); + + } + + class DetectionTask extends AsyncTask { + private long time; + + public DetectionTask() { + super(); + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + if (type == googlenet) { + inputSize = 224; + } + } + + @Override + protected void onPostExecute(float[] result) { + super.onPostExecute(result); + try { + Bitmap src = Bitmap.createScaledBitmap(bmp, imageView.getWidth(), + imageView.getHeight(), false); + drawRect(src, result, imageView.getWidth(), imageView.getHeight()); + tvSpeed.setText("detection cost:" + time + "ms"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + protected void onProgressUpdate(Void... values) { + super.onProgressUpdate(values); + } + + @Override + protected void onCancelled() { + super.onCancelled(); + } + + @Override + protected float[] doInBackground(String... strings) { + bmp = getScaleBitmap(mContext, strings[0]); + float[] inputData = getScaledMatrix(bmp, inputSize, inputSize); + float[] result = null; + try { + long start = System.currentTimeMillis(); + result = PML.predict(inputData); + long end = System.currentTimeMillis(); + time = end - start; + + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + } +} diff --git a/demo/android/PaddleMobile_Android/app/src/main/java/com/baidu/paddle/PML.java b/demo/android/PaddleMobile_Android/app/src/main/java/com/baidu/paddle/PML.java new file mode 100644 index 0000000000000000000000000000000000000000..7649d4c081223bace01b806d1eb7dca57129ed7c --- /dev/null +++ b/demo/android/PaddleMobile_Android/app/src/main/java/com/baidu/paddle/PML.java @@ -0,0 +1,23 @@ +package com.baidu.paddle; + +public class PML { + /** + * Load + * @param modelPath + * @return + */ + public static native boolean load(String modelPath); + + + /** + * object detection + * + * @param buf + * @return + */ + public static native float[] predict(float[] buf); + + + public static native void clear(); + +} diff --git a/demo/android/PaddleMobile_Android/app/src/main/res/drawable/ic_launcher_background.xml b/demo/android/PaddleMobile_Android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..d5fccc538c179838bfdce779c26eebb4fa0b5ce9 --- /dev/null +++ b/demo/android/PaddleMobile_Android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/android/PaddleMobile_Android/app/src/main/res/layout/main_activity.xml b/demo/android/PaddleMobile_Android/app/src/main/res/layout/main_activity.xml new file mode 100644 index 0000000000000000000000000000000000000000..6653b182adbfc6d82d50d313db8c88789c0b027b --- /dev/null +++ b/demo/android/PaddleMobile_Android/app/src/main/res/layout/main_activity.xml @@ -0,0 +1,55 @@ + + + + +