@@ -43,9 +43,11 @@ public class MainActivity extends Activity implements Runnable {
4343 private ImageView mImageView ;
4444 private Button mButtonXnnpack ;
4545 private ProgressBar mProgressBar ;
46+ private android .widget .TextView mInferenceTimeText ;
4647 private Bitmap mBitmap = null ;
4748 private Module mModule = null ;
4849 private String mImagename = "corgi.jpeg" ;
50+ private long mInferenceTime = 0 ;
4951
5052 private final ArrayList <String > mImageFiles = new ArrayList <>();
5153
@@ -57,9 +59,31 @@ public class MainActivity extends Activity implements Runnable {
5759 // see http://host.robots.ox.ac.uk:8080/pascal/VOC/voc2007/segexamples/index.html for the list of
5860 // classes with indexes
5961 private static final int CLASSNUM = 21 ;
60- private static final int DOG = 12 ;
61- private static final int PERSON = 15 ;
62- private static final int SHEEP = 17 ;
62+
63+ // Colors for all 21 PASCAL VOC classes
64+ private static final int [] CLASS_COLORS = {
65+ 0x00000000 , // 0: Background (transparent)
66+ 0xFFE6194B , // 1: Aeroplane (red)
67+ 0xFF3CB44B , // 2: Bicycle (green)
68+ 0xFFFFE119 , // 3: Bird (yellow)
69+ 0xFF4363D8 , // 4: Boat (blue)
70+ 0xFFF58231 , // 5: Bottle (orange)
71+ 0xFF911EB4 , // 6: Bus (purple)
72+ 0xFF46F0F0 , // 7: Car (cyan)
73+ 0xFFF032E6 , // 8: Cat (magenta)
74+ 0xFFBCF60C , // 9: Chair (lime)
75+ 0xFFFABEBE , // 10: Cow (pink)
76+ 0xFF008080 , // 11: Dining Table (teal)
77+ 0xFF00FF00 , // 12: Dog (bright green)
78+ 0xFF9A6324 , // 13: Horse (brown)
79+ 0xFFFFD8B1 , // 14: Motorbike (peach)
80+ 0xFFFF0000 , // 15: Person (red)
81+ 0xFF800000 , // 16: Potted Plant (maroon)
82+ 0xFF0000FF , // 17: Sheep (blue)
83+ 0xFF808000 , // 18: Sofa (olive)
84+ 0xFFE6BEFF , // 19: Train (lavender)
85+ 0xFFAA6E28 , // 20: TV/Monitor (tan)
86+ };
6387
6488 private void checkAndRequestStoragePermission () {
6589 if (ContextCompat .checkSelfPermission (this , Manifest .permission .READ_EXTERNAL_STORAGE )
@@ -198,6 +222,7 @@ protected void onCreate(Bundle savedInstanceState) {
198222 mImageView = findViewById (R .id .imageView );
199223 mButtonXnnpack = findViewById (R .id .xnnpackButton );
200224 mProgressBar = findViewById (R .id .progressBar );
225+ mInferenceTimeText = findViewById (R .id .inferenceTimeText );
201226
202227 populateImagePathFromAssets ();
203228 showImage ();
@@ -223,10 +248,9 @@ public void onClick(View v) {
223248 mButtonXnnpack .setOnClickListener (
224249 new View .OnClickListener () {
225250 public void onClick (View v ) {
226- mModule .destroy ();
227- mModule = Module .load ("/data/local/tmp/dl3_xnnpack_fp32.pte" );
228251 mButtonXnnpack .setEnabled (false );
229252 mProgressBar .setVisibility (ProgressBar .VISIBLE );
253+ mInferenceTimeText .setVisibility (View .INVISIBLE );
230254 mButtonXnnpack .setText (getString (R .string .run_model ));
231255
232256 Thread thread = new Thread (MainActivity .this );
@@ -262,32 +286,38 @@ public void run() {
262286 boolean imageSegementationSuccess = false ;
263287 final long startTime = SystemClock .elapsedRealtime ();
264288 Tensor outputTensor = mModule .forward (EValue .from (inputTensor ))[0 ].toTensor ();
265- final long inferenceTime = SystemClock .elapsedRealtime () - startTime ;
266- Log .d ("ImageSegmentation" , "inference time (ms): " + inferenceTime );
289+ mInferenceTime = SystemClock .elapsedRealtime () - startTime ;
290+ Log .d ("ImageSegmentation" , "inference time (ms): " + mInferenceTime );
267291
268292 final float [] scores = outputTensor .getDataAsFloatArray ();
269293 int width = mBitmap .getWidth ();
270294 int height = mBitmap .getHeight ();
271295
296+ // Get original pixels for blending
297+ int [] originalPixels = new int [width * height ];
298+ mBitmap .getPixels (originalPixels , 0 , width , 0 , 0 , width , height );
299+
272300 int [] intValues = new int [width * height ];
273301 for (int j = 0 ; j < height ; j ++) {
274302 for (int k = 0 ; k < width ; k ++) {
275- int maxi = 0 , maxj = 0 , maxk = 0 ;
303+ int maxi = 0 ;
276304 double maxnum = -Double .MAX_VALUE ;
277305 for (int i = 0 ; i < CLASSNUM ; i ++) {
278306 float score = scores [i * (width * height ) + j * width + k ];
279307 if (score > maxnum ) {
280308 maxnum = score ;
281309 maxi = i ;
282- maxj = j ;
283- maxk = k ;
284310 }
285311 }
286- if (maxi == PERSON ) intValues [maxj * width + maxk ] = 0xFFFF0000 ; // R
287- else if (maxi == DOG ) intValues [maxj * width + maxk ] = 0xFF00FF00 ; // G
288- else if (maxi == SHEEP ) intValues [maxj * width + maxk ] = 0xFF0000FF ; // B
289- else intValues [maxj * width + maxk ] = 0xFF000000 ;
290- if (maxi == PERSON || maxi == DOG || maxi == SHEEP ) {
312+ int pixelIndex = j * width + k ;
313+ int classColor = CLASS_COLORS [maxi ];
314+
315+ if (maxi == 0 ) {
316+ // Background: show original image
317+ intValues [pixelIndex ] = originalPixels [pixelIndex ];
318+ } else {
319+ // Blend segmentation color with original at 50% opacity
320+ intValues [pixelIndex ] = blendColors (originalPixels [pixelIndex ], classColor , 0.5f );
291321 imageSegementationSuccess = true ;
292322 }
293323 }
@@ -310,12 +340,14 @@ public void run() {
310340 runOnUiThread (
311341 () -> {
312342 if (showUserIndicationOnImgSegFail ) {
313- Toast .makeText (this , "ImageSegmentation Failed " , Toast .LENGTH_SHORT ).show ();
343+ Toast .makeText (this , "No objects detected " , Toast .LENGTH_SHORT ).show ();
314344 }
315345 mImageView .setImageBitmap (transferredBitmap );
316346 mButtonXnnpack .setEnabled (true );
317347 mButtonXnnpack .setText (R .string .run_xnnpack );
318348 mProgressBar .setVisibility (ProgressBar .INVISIBLE );
349+ mInferenceTimeText .setText ("Inference: " + mInferenceTime + " ms" );
350+ mInferenceTimeText .setVisibility (View .VISIBLE );
319351 });
320352 }
321353
@@ -326,4 +358,18 @@ public void run() {
326358 }
327359 });
328360 }
361+
362+ // Blend two colors with given alpha for the overlay
363+ private int blendColors (int background , int foreground , float alpha ) {
364+ int bgR = (background >> 16 ) & 0xFF ;
365+ int bgG = (background >> 8 ) & 0xFF ;
366+ int bgB = background & 0xFF ;
367+ int fgR = (foreground >> 16 ) & 0xFF ;
368+ int fgG = (foreground >> 8 ) & 0xFF ;
369+ int fgB = foreground & 0xFF ;
370+ int r = (int ) (bgR * (1 - alpha ) + fgR * alpha );
371+ int g = (int ) (bgG * (1 - alpha ) + fgG * alpha );
372+ int b = (int ) (bgB * (1 - alpha ) + fgB * alpha );
373+ return 0xFF000000 | (r << 16 ) | (g << 8 ) | b ;
374+ }
329375}
0 commit comments