├── README.md
├── app
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── mbv2.pt
│ └── ym.jpg
│ ├── java
│ └── org
│ │ └── pytorch
│ │ └── helloworld
│ │ ├── FaceUtils.java
│ │ ├── MainActivity.java
│ │ └── facebbox.java
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ └── ic_launcher_background.xml
│ ├── layout
│ └── activity_main.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── demo.jpg
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── trace_model.py
/README.md:
--------------------------------------------------------------------------------
1 | # facedetection_android.pytorch
2 | Light-weight face detection on Android with pytorch model
3 |
4 | This is Android demo for [LightWeightFaceDetector](https://github.com/midasklr/LightWeightFaceDetector)
5 |
6 | We train a ultra light weight face detection and landmark align model which is only 643.7 k.
7 |
8 | ## wider face validation performance
9 |
10 | | Models | Easy | Medium | Hard | Model Size |
11 | | ------------------------- | ------- | -------- | ------- | ---------- |
12 | | mobilenetv1_0.25 | 0.91718 | 0.79766 | 0.3592 | 1.6 M |
13 | | mobilenetv2_0.1 | 0.85330 | 0.68946 | 0.2993 | 1.3 M |
14 | | mobilenetv3_small | 0.93419 | 0.83259 | 0.3850 | 2.8 M |
15 | | efficientnet-b0 | 0.93167 | 0.81466 | 0.37020 | 16.4 M |
16 | | mobilenetv2_0.1_lite_3fpn | 0.80379 | 0.716958 | 0.34924 | 426 k |
17 | | mobilenetv2_0.1_lite_3pan | 0.83309 | 0.77181 | 0.5301 | 643.7 k |
18 | | mobilenetv2_0.1_lite_4pan | 0.83965 | 0.791419 | 0.5964 | 813 k |
19 |
20 | ## Android Pytorch Detection
21 |
22 | This demo is follow the [Android](https://pytorch.org/) resnet18 demo.
23 |
24 | After pytorch 1.3, pytorch model can be easily deploy to android, see [details](https://blog.csdn.net/IEEE_FELLOW/article/details/108420007) for how to deploy ur pytorch model.
25 |
26 | 
27 |
28 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | repositories {
4 | jcenter()
5 | }
6 |
7 | android {
8 | compileSdkVersion 28
9 | buildToolsVersion "29.0.2"
10 | defaultConfig {
11 | applicationId "org.pytorch.helloworld"
12 | minSdkVersion 21
13 | targetSdkVersion 28
14 | versionCode 1
15 | versionName "1.0"
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | implementation 'androidx.appcompat:appcompat:1.1.0'
26 | implementation 'org.pytorch:pytorch_android:1.4.0'
27 | implementation 'org.pytorch:pytorch_android_torchvision:1.4.0'
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/assets/mbv2.pt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/assets/mbv2.pt
--------------------------------------------------------------------------------
/app/src/main/assets/ym.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/assets/ym.jpg
--------------------------------------------------------------------------------
/app/src/main/java/org/pytorch/helloworld/FaceUtils.java:
--------------------------------------------------------------------------------
1 | package org.pytorch.helloworld;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Matrix;
7 |
8 | import org.pytorch.Tensor;
9 |
10 | import java.io.File;
11 | import java.io.FileOutputStream;
12 | import java.io.IOException;
13 | import java.io.InputStream;
14 | import java.io.OutputStream;
15 | import java.nio.FloatBuffer;
16 |
17 | public class FaceUtils {
18 | public static Tensor bitmapToFloat32Tensor(
19 | final Bitmap bitmap, final float[] normMeanRGB, final float normStdRGB[]) {
20 | return bitmapToFloat32Tensor(
21 | bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), normMeanRGB, normStdRGB);
22 | }
23 | public static Tensor bitmapToFloat32Tensor(
24 | final Bitmap bitmap,
25 | int x,
26 | int y,
27 | int width,
28 | int height,
29 | float[] normMeanRGB,
30 | float[] normStdRGB) {
31 |
32 | final FloatBuffer floatBuffer = Tensor.allocateFloatBuffer(3 * width * height);
33 | bitmapToFloatBuffer(bitmap, x, y, width, height, normMeanRGB, normStdRGB, floatBuffer, 0);
34 | return Tensor.fromBlob(floatBuffer, new long[]{1, 3, height, width});
35 | }
36 | public static void bitmapToFloatBuffer(
37 | final Bitmap bitmap,
38 | final int x,
39 | final int y,
40 | final int width,
41 | final int height,
42 | final float[] normMeanRGB,
43 | final float[] normStdRGB,
44 | final FloatBuffer outBuffer,
45 | final int outBufferOffset) {
46 | checkOutBufferCapacity(outBuffer, outBufferOffset, width, height);
47 |
48 | final int pixelsCount = height * width;
49 | final int[] pixels = new int[pixelsCount];
50 | bitmap.getPixels(pixels, 0, width, x, y, width, height);
51 | final int offset_g = pixelsCount;
52 | final int offset_b = 2 * pixelsCount;
53 | for (int i = 0; i < pixelsCount; i++) {
54 | final int c = pixels[i];
55 | float r = ((c >> 16) & 0xff) / 1.0f;
56 | float g = ((c >> 8) & 0xff) / 1.0f;
57 | float b = ((c) & 0xff) / 1.0f;
58 | // System.out.print(" "+r+" ;"+g+" ;"+b);
59 | float rF = (r - normMeanRGB[0]) / normStdRGB[0];
60 | float gF = (g - normMeanRGB[1]) / normStdRGB[1];
61 | float bF = (b - normMeanRGB[2]) / normStdRGB[2];
62 | outBuffer.put(outBufferOffset + i, rF);
63 | outBuffer.put(outBufferOffset + offset_g + i, gF);
64 | outBuffer.put(outBufferOffset + offset_b + i, bF);
65 | }
66 | }
67 |
68 | private static void checkOutBufferCapacity(FloatBuffer outBuffer, int outBufferOffset, int tensorWidth, int tensorHeight) {
69 | if (outBufferOffset + 3 * tensorWidth * tensorHeight > outBuffer.capacity()) {
70 | throw new IllegalStateException("Buffer underflow");
71 | }
72 | }
73 |
74 | public static Bitmap PreProcessing(Bitmap bitmap)
75 | {
76 | int imgw = bitmap.getWidth();
77 | int imgh = bitmap.getHeight();
78 | float scaleHeight;
79 | float scaleWidth;
80 | if(imgw > imgh){
81 | scaleHeight = 640.0f / ((float) imgw);
82 | scaleWidth = 640.0f / ((float) imgw) ;
83 | }else {
84 | scaleWidth = 640.0f / ((float) imgh);
85 | scaleHeight = 640.0f / ((float) imgh) ;
86 | }
87 | Matrix matrix = new Matrix();
88 | matrix.postScale(scaleWidth, scaleHeight);
89 | // 得到新的图片
90 | Bitmap newbm = Bitmap.createBitmap(bitmap, 0, 0, imgw, imgh, matrix,
91 | true);
92 |
93 | int imgmin = Math.min(newbm.getWidth(),newbm.getHeight());
94 | int padsize = (int) (640 - imgmin)/2;
95 | Bitmap mergebitmap = Bitmap.createBitmap(640, 640, Bitmap.Config.ARGB_8888);
96 | if(newbm.getHeight()>newbm.getWidth()) {
97 | Bitmap bgBitmap1 = Bitmap.createBitmap(padsize, 640, Bitmap.Config.ARGB_8888);//创建一个新空白位图
98 | Bitmap bgBitmap2 = Bitmap.createBitmap(640 - padsize, 640, Bitmap.Config.ARGB_8888);
99 | Canvas canvasadd = new Canvas(mergebitmap);
100 | canvasadd.drawBitmap(bgBitmap1, 0, 0, null);
101 | canvasadd.drawBitmap(newbm, padsize, 0, null);
102 | canvasadd.drawBitmap(bgBitmap2, padsize + newbm.getWidth(), 0, null);
103 | }else if (newbm.getHeight()=rightColumnMin || downRowMin<=upRowMax){
124 | return 0;
125 | }
126 | int s1 = (rect1w-rect1x)*(rect1h-rect1y);
127 | int s2 = (rect2w-rect2x)*(rect2h-rect2y);
128 | float sCross = (downRowMin-upRowMax)*(rightColumnMin-leftColumnMax);
129 | return sCross/(s1+s2-sCross);
130 | }
131 |
132 | public static facebbox[] getAnchors(int imw, int imh){
133 | int num = 0;
134 | double fmw1 = Math.ceil(((float) imw) / 16.0f );
135 | double fmh1 = Math.ceil(((float) imh) / 16.0f );
136 | double fmw2 = Math.ceil(((float) imw) / 32.0f );
137 | double fmh2 = Math.ceil(((float) imh) / 32.0f );
138 | double fmw3 = Math.ceil(((float) imw) / 64.0f );
139 | double fmh3 = Math.ceil(((float) imh) / 64.0f );
140 |
141 | int totalnum = 2*(((int)fmh1)*((int)fmw1)+((int)fmh2)*((int)fmw2)+((int)fmh3)*((int)fmw3));
142 | facebbox[] Anchors = new facebbox[totalnum];
143 | for (int k = 0; k < fmh1; k++) {
144 | for (int j = 0; j < fmw1; j++) {
145 | double s_kx = 16.0 / ((double) imw);
146 | double s_ky = 16.0 / ((double) imh);
147 | double dense_cx = (j + 0.5) * 16 / ((double) imw);
148 | double dense_cy = (k + 0.5) * 16 / ((double) imh);
149 | facebbox boxtmp = new facebbox();
150 | boxtmp.x1 = (float) dense_cx;
151 | boxtmp.y1 = (float) dense_cy;
152 | boxtmp.x2 = (float) s_kx;
153 | boxtmp.y2 = (float) s_ky;
154 | Anchors[num] =boxtmp;
155 | num += 1;
156 |
157 | double s_kx2 = 32.0 / ((double) imw);
158 | double s_ky2 = 32.0 / ((double) imh);
159 | double dense_cx2 = (j + 0.5) * 16 / ((double) imw);
160 | double dense_cy2 = (k + 0.5) * 16 / ((double) imh);
161 | facebbox boxtmp2 = new facebbox();
162 | boxtmp2.x1 = (float) dense_cx2;
163 | boxtmp2.y1 = (float) dense_cy2;
164 | boxtmp2.x2 = (float) s_kx2;
165 | boxtmp2.y2 = (float) s_ky2;
166 | Anchors[num] = boxtmp2;
167 | num += 1;
168 | }
169 | }
170 |
171 | for (int k = 0; k < fmh2; k++) {
172 | for (int j = 0; j < fmw2; j++) {
173 | double s_kx = 64.0 / ((double) imw);
174 | double s_ky = 64.0 / ((double) imh);
175 | double dense_cx = (j + 0.5) * 32 / ((double) imw);
176 | double dense_cy = (k + 0.5) * 32 / ((double) imh);
177 | facebbox boxtmp = new facebbox();
178 | boxtmp.x1 = (float) dense_cx;
179 | boxtmp.y1 = (float) dense_cy;
180 | boxtmp.x2 = (float) s_kx;
181 | boxtmp.y2 = (float) s_ky;
182 | Anchors[num] =boxtmp;
183 | num += 1;
184 |
185 | double s_kx2 = 128.0 / ((double) imw);
186 | double s_ky2 = 128.0 / ((double) imh);
187 | double dense_cx2 = (j + 0.5) * 32 / ((double) imw);
188 | double dense_cy2 = (k + 0.5) * 32 / ((double) imh);
189 | facebbox boxtmp2 = new facebbox();
190 | boxtmp2.x1 = (float) dense_cx2;
191 | boxtmp2.y1 = (float) dense_cy2;
192 | boxtmp2.x2 = (float) s_kx2;
193 | boxtmp2.y2 = (float) s_ky2;
194 | Anchors[num] = boxtmp2;
195 | num += 1;
196 | }
197 | }
198 |
199 | for (int k = 0; k < fmh3; k++) {
200 | for (int j = 0; j < fmw3; j++) {
201 | double s_kx = 256.0 / ((double) imw);
202 | double s_ky = 256.0 / ((double) imh);
203 | double dense_cx = (j + 0.5) * 64 / ((double) imw);
204 | double dense_cy = (k + 0.5) * 64 / ((double) imh);
205 | facebbox boxtmp = new facebbox();
206 | boxtmp.x1 = (float) dense_cx;
207 | boxtmp.y1 = (float) dense_cy;
208 | boxtmp.x2 = (float) s_kx;
209 | boxtmp.y2 = (float) s_ky;
210 | Anchors[num] =boxtmp;
211 | num += 1;
212 |
213 | double s_kx2 = 512.0 / ((double) imw);
214 | double s_ky2 = 512.0 / ((double) imh);
215 | double dense_cx2 = (j + 0.5) * 64 / ((double) imw);
216 | double dense_cy2 = (k + 0.5) * 64 / ((double) imh);
217 | facebbox boxtmp2 = new facebbox();
218 | boxtmp2.x1 = (float) dense_cx2;
219 | boxtmp2.y1 = (float) dense_cy2;
220 | boxtmp2.x2 = (float) s_kx2;
221 | boxtmp2.y2 = (float) s_ky2;
222 | Anchors[num] = boxtmp2;
223 | num += 1;
224 | }
225 | }
226 | return Anchors;
227 | }
228 |
229 |
230 | /**
231 | * Copies specified asset to the file in /files app directory and returns this file absolute path.
232 | *
233 | * @return absolute file path
234 | */
235 | public static String assetFilePath(Context context, String assetName) throws IOException {
236 | File file = new File(context.getFilesDir(), assetName);
237 | if (file.exists() && file.length() > 0) {
238 | return file.getAbsolutePath();
239 | }
240 |
241 | try (InputStream is = context.getAssets().open(assetName)) {
242 | try (OutputStream os = new FileOutputStream(file)) {
243 | byte[] buffer = new byte[4 * 1024];
244 | int read;
245 | while ((read = is.read(buffer)) != -1) {
246 | os.write(buffer, 0, read);
247 | }
248 | os.flush();
249 | }
250 | return file.getAbsolutePath();
251 | }
252 | }
253 |
254 | }
255 |
--------------------------------------------------------------------------------
/app/src/main/java/org/pytorch/helloworld/MainActivity.java:
--------------------------------------------------------------------------------
1 | package org.pytorch.helloworld;
2 | import android.content.Context;
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.Paint;
6 | import android.graphics.Color;
7 | import android.os.Bundle;
8 | import android.util.Log;
9 | import android.graphics.Matrix;
10 | import android.widget.ImageView;
11 | import android.widget.TextView;
12 | import android.graphics.Canvas;
13 | import org.pytorch.IValue;
14 | import org.pytorch.Module;
15 | import org.pytorch.Tensor;
16 |
17 | import java.io.File;
18 | import java.io.FileOutputStream;
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 | import java.io.OutputStream;
22 | import java.nio.FloatBuffer;
23 |
24 | import androidx.appcompat.app.AppCompatActivity;
25 |
26 | public class MainActivity extends AppCompatActivity {
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_main);
32 |
33 | Bitmap bitmap = null;
34 | Module module = null;
35 | try {
36 | // creating bitmap from packaged into app android asset 'image.jpg',
37 | // app/src/main/assets/image.jpg
38 | bitmap = BitmapFactory.decodeStream(getAssets().open("ym.jpg"));
39 | // loading serialized torchscript module from packaged into app android asset model.pt,
40 | // app/src/model/assets/model.pt
41 | module = Module.load(FaceUtils.assetFilePath(this, "mbv2.pt"));
42 | System.out.println("Succeed load model ...");
43 | } catch (IOException e) {
44 | Log.e("Pytorch ClS", "Error reading assets", e);
45 | finish();
46 | }
47 |
48 | //************************* resize and padding to 640*640 *********************//
49 | Bitmap mergebitmap= FaceUtils.PreProcessing(bitmap);
50 |
51 | // preparing input tensor
52 | // float[] face_mean = new float[]{104.0f, 117.0f, 123.0f};
53 | float[] face_mean = new float[]{116.0f, 117.0f, 111.0f}; //offset to {104.0f, 117.0f, 123.0f}
54 | float[] face_std = new float[]{1.0f, 1.0f, 1.0f};
55 | final Tensor inputTensor = FaceUtils.bitmapToFloat32Tensor(mergebitmap,
56 | face_mean, face_std);
57 |
58 | System.out.println(inputTensor.getDataAsFloatArray().length);
59 | // System.out.println("inputTensor " +inputTensor.numel());
60 | // running the model
61 | long startTime = System.currentTimeMillis();
62 | final IValue[] outputTensor = module.forward(IValue.from(inputTensor)).toTuple();
63 | long endTime = System.currentTimeMillis();
64 | System.out.println("程序运行时间:" + (endTime - startTime) / 2 + "ms");
65 | long infertime = (endTime - startTime) / 2;
66 | System.out.println("Out put length : " + outputTensor.length);
67 | //*************************** bbox ******************************//
68 | IValue bbox = outputTensor[0];
69 | Tensor boxt = bbox.toTensor();
70 | float[] facebox = boxt.getDataAsFloatArray();
71 |
72 | IValue cls = outputTensor[1];
73 | Tensor clst = cls.toTensor();
74 | float[] facecls = clst.getDataAsFloatArray();
75 |
76 | // IValue ldm = outputTensor[2];
77 | // Tensor ldmt = ldm.toTensor();
78 | // float[] faceldm = ldmt.getDataAsFloatArray();
79 |
80 | System.out.println("face box length : " + facebox.length);
81 | System.out.println("face cls length : " + facecls.length);
82 | // System.out.println("face landmark length : " + faceldm.length);
83 | int imw = mergebitmap.getWidth();
84 | int imh = mergebitmap.getHeight();
85 |
86 | double fmw1 = Math.ceil(((float) imw) / 16.0f );
87 | double fmh1 = Math.ceil(((float) imh) / 16.0f );
88 | double fmw2 = Math.ceil(((float) imw) / 32.0f );
89 | double fmh2 = Math.ceil(((float) imh) / 32.0f );
90 | double fmw3 = Math.ceil(((float) imw) / 64.0f );
91 | double fmh3 = Math.ceil(((float) imh) / 64.0f );
92 |
93 | int totalnum = 2*(((int)fmh1)*((int)fmw1)+((int)fmh2)*((int)fmw2)+((int)fmh3)*((int)fmw3));
94 | float maxcls = 0.0f;
95 | float maxx = 0.0f;
96 | float maxy = 0.0f;
97 | float maxw = 0.0f;
98 | float maxh = 0.0f;
99 | float[] faceconf = new float[totalnum];
100 | int[] faceidx = new int[totalnum];
101 | int clsnum = 0;
102 | int maxidx = 0;
103 | facebbox[] fbbox = new facebbox[totalnum];
104 | for (int i = 0; i < facebox.length; i = i+4) {
105 | int clsidx = (int) (i/4);
106 | float clsconf = facecls[2 *clsidx+1];
107 | facebbox boxtmp = new facebbox();
108 | boxtmp.score = clsconf;
109 | boxtmp.x1 = facebox[i];
110 | boxtmp.y1 = facebox[i + 1];
111 | boxtmp.x2 = facebox[i + 2];
112 | boxtmp.y2 = facebox[i + 3];
113 | fbbox[clsidx] = boxtmp;
114 | if(clsconf > 0.2){
115 | faceconf[clsnum] = clsconf;
116 | faceidx[clsnum] = clsidx;
117 | clsnum +=1;
118 | }
119 | if (clsconf > maxcls) {
120 | maxcls = clsconf;
121 | maxidx = clsidx;
122 | }
123 | }
124 | System.out.println("MAX :"+maxcls);
125 | System.out.println("MAX idx:"+maxidx);
126 | //
127 | // // ************************************* PriorBox ***********************************//
128 | facebbox[] Anchors = FaceUtils.getAnchors(imw,imh);
129 |
130 | // //***************************** decode bbox from anchor and pred *********************************//
131 | // ************************************ 按照置信度降序排列 **************************************** //
132 | float[] PredConfOr = new float[clsnum];
133 | int[] PredBoxX = new int[clsnum];
134 | int[] PredBoxY = new int[clsnum];
135 | int[] PredBoxW = new int[clsnum];
136 | int[] PredBoxH = new int[clsnum];
137 |
138 | Bitmap bitmap2 = mergebitmap.copy(Bitmap.Config.ARGB_8888, true);
139 |
140 | Canvas canvas = new Canvas(bitmap2);
141 | Paint paint = new Paint();
142 | paint.setColor(Color.RED);
143 | paint.setStyle(Paint.Style.STROKE);
144 | paint.setStrokeWidth(3);
145 |
146 | for(int k=0;k 0.4){}
212 | // }
213 | //
214 | // }
215 |
216 |
217 | ImageView imageView = findViewById(R.id.image);
218 | imageView.setImageBitmap(bitmap2);
219 | String className = "置信度:"+maxcls+"\n时间 : " + infertime + " ms";
220 | // showing className on UI
221 | TextView textView = findViewById(R.id.text);
222 | textView.setText(className);
223 | }
224 |
225 | public static float max(float [] array){
226 | float max=0;
227 | int i=0;
228 | for(i=0;imax){
230 | max=array[i];
231 | }
232 | }
233 | return max;
234 | }
235 |
236 |
237 | }
238 |
--------------------------------------------------------------------------------
/app/src/main/java/org/pytorch/helloworld/facebbox.java:
--------------------------------------------------------------------------------
1 | package org.pytorch.helloworld;
2 |
3 | public class facebbox {
4 | float score = 0;
5 | float x1;
6 | float y1;
7 | float x2;
8 | float y2;
9 | }
10 |
11 | class landmarks{
12 | int x1;
13 | int y1;
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Pytorch Hello World
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 |
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.5.0'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | jcenter()
16 |
17 | }
18 | }
19 |
20 | task clean(type: Delete) {
21 | delete rootProject.buildDir
22 | }
23 |
--------------------------------------------------------------------------------
/demo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/demo.jpg
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | android.useAndroidX=true
2 | android.enableJetifier=true
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midasklr/facedetection_android.pytorch/153962bcb43d22695544d788aa91d6e8eb101cda/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Oct 01 13:22:43 PDT 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | rootProject.name='HelloWorldApp'
3 |
--------------------------------------------------------------------------------
/trace_model.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torchvision
3 |
4 | model = torchvision.models.resnet18(pretrained=True)
5 | model.eval()
6 | example = torch.rand(1, 3, 224, 224)
7 | traced_script_module = torch.jit.trace(model, example)
8 | traced_script_module.save("app/src/main/assets/model.pt")
--------------------------------------------------------------------------------