研究一下

// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.package com.tencent.yolov5ncnn;import android.app.Activity;
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.media.ExifInterface;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;//AppCompatActivity 和 Activity 的区别主要体现在app运行后的界面(app name显示或者不显示),对程序本身没有影响。
//AppCompatActivity是继承自v4包的FragmentAvtivity,并且加入了很多新特性。这个可以很好的兼容老设备。
public class MainActivity extends Activity
{// public声明,在这种情况下,类对所有类都可见。// private修饰符指定该成员只能在其自己的类中访问。// protected修饰符指定该成员只能在其自己的包(如package-private)中访问,此外还可以由另一个包中的该类的子类访问。// static声明的成员变量为静态成员变量,也成为类变量。类变量的生命周期和类相同,在整个应用程序执行期间都有效。// 被final修饰的类不可以被继承、被final修饰的方法不可以被重写、被final修饰的变量不可以被改变// 被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变 的private static final int SELECT_IMAGE = 1;private ImageView imageView;private Bitmap bitmap = null;private Bitmap yourSelectedImage = null;// new运算符实例化一个类对象,通过给这个对象分配内存并返回一个指向该内存的引用。new运算符也调用了对象的构造函数。// 由new运算符返回的引用可以不需要被赋值给变量。它也可以直接使用在一个表达式中。例如: int age = new Person().age;// 这里引用了YoloV5Ncnn.java文件中的函数private YoloV5Ncnn yolov5ncnn = new YoloV5Ncnn();/** Called when the activity is first created. */// @Override简单理解就是这个句话下边的方法是继承父类的方法,对其覆盖@Override// void代表的意思是什么也不返回// onCreate()函数是在activity初始化的时候调用的,它主要做这个activity启动时一些必要的初始化工作// 子类在重写onCreate()方法的时候必须调用父类的onCreate()方法,即super.onCreate(),否则会抛出异常。// Bundle 是一个可以存储任何混合类型的列表,与 Set、Array 相比:Bundle 的各项数据类型不一样,而 Set、Array 各项数据类型必须一样。public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);// R.layout.main是个布局文件即控件都是如何摆放如何显示的// setContentView就是设置一个Activity的显示界面,这句话就是设置所再的Activity采用R.layout下的main布局文件进行布局setContentView(R.layout.main);// 1、在java语言中boolean类型只有两个值,没有其他值:true和false。不像c或者c++,c语言中1和0也可以表示布尔类型。// boolean使用在逻辑判断当中,通常放在条件的位置上(充当条件)。// 将Assets中的文件加载到yolov5ncnn_jni.cpp中,对模型进行初始化boolean ret_init = yolov5ncnn.Init(getAssets());if (!ret_init){// Log用来在调试代码时查看调试信息,有.v、.d、.i、.w、.e,不同的对应输出信息的不同级别// Log.e为红色,可以想到error错误,这里仅显示红色的错误信息,这些错误就需要我们认真的分析,查看栈的信息了。Log.e("MainActivity", "yolov5ncnn Init failed");}// 在代码中访问指定的组件时,用findViewByIdimageView = (ImageView) findViewById(R.id.imageView);// 选图按钮Button buttonImage = (Button) findViewById(R.id.buttonImage);// setOnClickListener为点击事件监听器buttonImage.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// Intent对Android的核心和灵魂,是四大组件之间的桥梁// 打开文件Intent i = new Intent(Intent.ACTION_PICK);// 打开我们的相册i.setType("image/*");// startActivityForResult在Activity中得到新打开Activity 关闭后返回的数据// 在一个主界面(主Activity)上能连接往许多不同子功能模块(子Activity上去)// 当子模块的事情做完之后就回到主界面,或许还同时返回一些子模块完成的数据交给主Activity处理。// 这样的数据交流就要用到回调函数onActivityResult。//<1>startActivityForResult(Intent intent, int requestCode);//**第一个参数:一个Intent对象//第二个参数:如果> = 0,当Activity结束时requestCode将归还在onActivityResult()中。以便确定返回的数据是从哪个Activity中返回**// 这里能够得到打开的相册返回的图片startActivityForResult(i, SELECT_IMAGE);}});// 检测按钮Button buttonDetect = (Button) findViewById(R.id.buttonDetect);buttonDetect.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {if (yourSelectedImage == null)return;YoloV5Ncnn.Obj[] objects = yolov5ncnn.Detect(yourSelectedImage, false);showObjects(objects);}});//Button buttonDetectGPU = (Button) findViewById(R.id.buttonDetectGPU);buttonDetectGPU.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {if (yourSelectedImage == null)return;YoloV5Ncnn.Obj[] objects = yolov5ncnn.Detect(yourSelectedImage, true);showObjects(objects);}});}// 画出检测出的目标框private void showObjects(YoloV5Ncnn.Obj[] objects){if (objects == null){// bitmap显示在界面中imageView.setImageBitmap(bitmap);return;}// draw objects on bitmap// Alpha为透明度值// ARGB_8888,图片中每个像素用四个字节(32位)存储,Alpha,R,G,B四个通道每个通道用8位表示Bitmap rgba = bitmap.copy(Bitmap.Config.ARGB_8888, true);// 不同的颜色列表final int[] colors = new int[] {Color.rgb( 54,  67, 244),Color.rgb( 99,  30, 233),Color.rgb(176,  39, 156),Color.rgb(183,  58, 103),Color.rgb(181,  81,  63),Color.rgb(243, 150,  33),Color.rgb(244, 169,   3),Color.rgb(212, 188,   0),Color.rgb(136, 150,   0),Color.rgb( 80, 175,  76),Color.rgb( 74, 195, 139),Color.rgb( 57, 220, 205),Color.rgb( 59, 235, 255),Color.rgb(  7, 193, 255),Color.rgb(  0, 152, 255),Color.rgb( 34,  87, 255),Color.rgb( 72,  85, 121),Color.rgb(158, 158, 158),Color.rgb(139, 125,  96)};// Canvas绘制图形Canvas canvas = new Canvas(rgba);// Paint画图方法// 这里画框Paint paint = new Paint();// 设置画笔样式,取值有//Paint.Style.FILL :填充内部//Paint.Style.FILL_AND_STROKE :填充内部和描边//Paint.Style.STROKE :仅描边paint.setStyle(Paint.Style.STROKE);// setStrokeWidth设置画笔宽度paint.setStrokeWidth(4);// 设置白底Paint textbgpaint = new Paint();// 给画笔设置颜色值textbgpaint.setColor(Color.WHITE);// 填充内部textbgpaint.setStyle(Paint.Style.FILL);// 写黑字Paint textpaint = new Paint();textpaint.setColor(Color.BLACK);// 设置文字大小textpaint.setTextSize(26);// 设置开始绘图点位置textpaint.setTextAlign(Paint.Align.LEFT);// 循环画框、写字for (int i = 0; i < objects.length; i++){paint.setColor(colors[i % 19]);// 画目标矩形框canvas.drawRect(objects[i].x, objects[i].y, objects[i].x + objects[i].w, objects[i].y + objects[i].h, paint);// draw filled text inside image{// 要打印的文字String text = objects[i].label + " = " + String.format("%.1f", objects[i].prob * 100) + "%";// textpaint.measureText计算文本尺寸float text_width = textpaint.measureText(text);// 文本的高度float text_height = - textpaint.ascent() + textpaint.descent();// 文字框的x,y坐标float x = objects[i].x;float y = objects[i].y - text_height;// 如果文字的y坐标小于0if (y < 0)y = 0;// 如果文字的x坐标大于画布的宽度if (x + text_width > rgba.getWidth())x = rgba.getWidth() - text_width;// 画文字矩形框,在白底上canvas.drawRect(x, y, x + text_width, y + text_height, textbgpaint);// 在白底上写黑字canvas.drawText(text, x, y - textpaint.ascent(), textpaint);}}// bitmap显示在界面中imageView.setImageBitmap(rgba);}@Override// onActivityResult(int requestCode, int resultCode, Intent data)//**第一个参数:这个整数requestCode提供给onActivityResult,是以便确认返回的数据是从哪个Activity返回的。//这个requestCode和startActivityForResult中的requestCode相对应。//第二个参数:这整数resultCode是由子Activity通过其setResult()方法返回。//第三个参数:一个Intent对象,带有返回的数据。**// data为返回的图片protected void onActivityResult(int requestCode, int resultCode, Intent data){super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK && null != data) {Uri selectedImage = data.getData();try{// 如果requestCode返回为1,就说明打开相册之后if (requestCode == SELECT_IMAGE) {// 对图片进行uri解码bitmap = decodeUri(selectedImage);yourSelectedImage = bitmap.copy(Bitmap.Config.ARGB_8888, true);// bitmap显示在界面中imageView.setImageBitmap(bitmap);}}// 异常处理// FileNotFoundException e文件不存在的错误catch (FileNotFoundException e){Log.e("MainActivity", "FileNotFoundException");return;}}}// throws关键字主要用于方法声明上,指的是当方法之中出现异常后交由被调用处处理。// 如果出现异常,这些异常只是被抛出,方法本身不对其做出处理,而是传给上级处理。private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException{// Decode image sizeBitmapFactory.Options o = new BitmapFactory.Options();// inJustDecodeBounds 如果设置为true,并不会把图像的数据完全解码,亦即decodeXyz()返回值为null,但是Options的outAbc中解出了图像的基本信息。o.inJustDecodeBounds = true;// 想访问内容提供者的共享数据,一定要借助getContentResolver类,通过Context中的getContentResolver()来获取该类的实例// bitmap加载方式BitmapFactory.decodeStreamBitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o);// The new size we want to scale tofinal int REQUIRED_SIZE = 640;// Find the correct scale value. It should be the power of 2.int width_tmp = o.outWidth, height_tmp = o.outHeight;// scale为采样率int scale = 1;while (true) {if (width_tmp / 2 < REQUIRED_SIZE|| height_tmp / 2 < REQUIRED_SIZE) {break;}width_tmp /= 2;height_tmp /= 2;scale *= 2;}// Decode with inSampleSizeBitmapFactory.Options o2 = new BitmapFactory.Options();// inSampleSize的原理就是在该值个像素中选择一个像素点;假设inSampleSize为4,生成的bitmap的大小就是原图的四分之一大小o2.inSampleSize = scale;// 采样率压缩Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o2);// Rotate according to EXIFint rotate = 0;try{// ExifInterface类主要描述多媒体文件比如JPG格式图片的一些附加信息,比如拍照的设备厂商,当时的日期时间,曝光时间,快门速度等。ExifInterface exif = new ExifInterface(getContentResolver().openInputStream(selectedImage));// TAG_ORIENTATION标签方向int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);switch (orientation) {case ExifInterface.ORIENTATION_ROTATE_270:rotate = 270;break;case ExifInterface.ORIENTATION_ROTATE_180:rotate = 180;break;case ExifInterface.ORIENTATION_ROTATE_90:rotate = 90;break;}}catch (IOException e){Log.e("MainActivity", "ExifInterface IOException");}Matrix matrix = new Matrix();// 对像素值进行变换的可选矩阵matrix.postRotate(rotate);// Bitmap.createBitmap返回一个不可变的源位图的位图的子集// filter如果为true,源图要被过滤。该参数仅在matrix包含了超过一个翻转才有效return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);}}

Android studio学习(一)相关推荐

  1. Android Studio --- [学习笔记]TCP(第2弹)、GridView、ScrollView

    说明 这篇主要接上一篇Android Studio - > [学习笔记]RadioButton.CheckBox.ImageView.ListView.TCP的三次握手 对上面回答的细解,并用J ...

  2. Android Studio --- [学习笔记]RadioButton、CheckBox、ImageView、ListView、TCP的三次握手

    说明 源代码 在2.x里有TCP的三次挥手与四次握手,先对它进行简单的回答(百度).预计在下一篇里,会继续说明TCP 接上一篇: Android Studio - > [学习笔记]Button. ...

  3. Android Studio 学习实例记录-手电筒

    Android Studio 学习实例记录-手电筒 刚安装好Android Studio3.1.2,上网搜了一个实例进行实践学习,仅用这篇文章来记录学习过程 MainActivity.java的源码来 ...

  4. 安卓开发Android studio学习笔记12:读取解析XML(案例演示)

    Android studio学习笔记 第一步:配置Student.XML 第二步:配置activity_main.xml 第三步:配置student.xml 第四步:配置Student用户类 第五步: ...

  5. android studio gradle 添加jar,android studio学习----通过gradle来导入jar包

    转载地址:http://www.th7.cn/Program/Android/201507/495477.shtml File->Project Structure 可以打开下面的图: 1.通过 ...

  6. Android Studio学习记录之简单的页面切换及宫格菜单

    Android Studio学习记录之简单的页面切换及宫格菜单 之前上课听老师讲的一些东西自己其实并没有消化,今天把不懂的都去网上搜了一下,有了一种恍然大悟的感觉,包括很多方方面面的东西.有些东西听说 ...

  7. 【Android Studio学习】第二篇、APP实现画简易的波形图

    目录 第一部分.前言 1.效果展示 2.参考博客 3.实现方式 第二部分.详细步骤 1.添加波形函数的依赖 2.添加一个管理类 3.修改activity_main.xml文件的代码 4.修改MainA ...

  8. android studio 学习入门篇

    开发第一应用 可以开发属于自己的应用,是否有点小激动?好吧!让我们开始,首先点击Start a new Android Studio Project创建工程: 接下来需要输入应用名称(第一个字母要大写 ...

  9. Android Studio 学习资料大全

    Android Studio / Gradle学习资源 在说设置之前,先上点学习Android Studio和Gradle的学习资源. 官方教程 developer.android.com上的Andr ...

  10. 【安卓开发】android studio 学习入门篇

    以下内容转载自:https://blog.csdn.net/myosotis5/article/details/79208707 (为防止链接失效,特备份文章内容,侵删) 开发第一应用 可以开发属于自 ...

最新文章

  1. 魔性“合成大西瓜”背后,我用 350 行代码解开了碰撞之谜!
  2. 火星坐标、百度坐标、WGS84坐标转换代码(JS、python版)
  3. linux opengl 实例,一篇文章入门Ubuntu的OpenGL开发
  4. 基于zookeeper实现的分布式锁
  5. 如何检测C语言中的内存漏洞(leak)?
  6. 请领导批阅文件怎么说_请领导吃饭,不要对外说,职场员工为何如此保密?
  7. [网络流24题]圆桌问题
  8. wp8 应用推荐photobeamer
  9. 参与全国软考调查问卷,赢精彩大奖
  10. bigsur正式版clover引导_迟来的OC引导版本升级教程,让大家在更新mac OS Big Sur的时候变得更轻松...
  11. AllWinner T113 升级篇
  12. python学习日常-----作业(4)
  13. IT牛博客:送给想成为下一个牛人的你
  14. 基于华为云ECS的目标检测与识别的昇腾AI开发体验【华为云至简致远】
  15. 《袁老师访谈录》第一期|吴恩柏教授/香港科大协理副校长:【成功,说到底要非常专注!】...
  16. 【剑指offer】解题思路 53-68
  17. 主流Web架构相互比较
  18. 快递100API 手机H5使用
  19. windows下载安装mysql教程
  20. ios15html2canvas截图空白怎么解决

热门文章

  1. java模板引擎性能,内容太过真实
  2. [绍棠] 关于 @synchronized
  3. 深度学习(波士顿房价预测)
  4. 最新cocos2d-x 3.0博客教学 小游戏[史上最坑爹的游戏] 004第三关:让坦克过桥
  5. JavaScript 脚本
  6. springboot整合security(一)入门
  7. msvcp120.dll丢失的最新解决方法
  8. swf文件格式分析(一)
  9. vfifo控制mig_浅析Xilinx家DDR控制器MIG的使用
  10. 道路交通安全违法行为记分分值(转载)