资料介绍
描述
在科罗拉多州和其他拥有大量野生动物种群的州,人类与野生动物之间的冲突并不少见(城镇中的熊和驼鹿、涉及麋鹿的交通事故等)
我决定通过创建一个检测运动、拍照并使用机器学习算法分析它以采取某种行动(吓跑它、点亮标志、通知当局)。此外,该设备跟踪环境数据,以帮助研究人员跟踪可能导致更多野生动物遭遇的迁徙模式和条件,它还检测野火以防止不必要的破坏。
分类
该项目的主要重点是机器学习野生动物分类。我通过训练TensorFlow来使用来自 Google 图片的数据来识别四种特定的动物物种,从而实现了这一点。所有的初始训练都是在计算机上使用为TensorFlow 和一千多张野生动物图片预先配置的 docker 机器图像完成的。一旦 TensorFlow 被训练,图形文件被优化以在移动设备上运行,然后它可以被用来在AndroidThings 设备上运行,方法是拍摄一张图像,调整它的大小,然后通过 TensorFlow 运行它以确定该图像是否包含一个我们预先训练的分类,以及到什么置信水平。
一旦确定了动物,就必须对这些数据进行处理。根据您的情况,您可以使用额外的硬件来闪光、播放声音或做任何其他事情。对于这个原型,我将 Android Things 连接到 Firebase 后端,以便简单地保存图像和分类信息。
将信息存储在 Firebase 上后,您可以创建一个辅助应用程序来接收有关动物存在的通知,或者只是存储该数据以用于研究目的。
此外,如果您希望无需检查 Firebase 即可看到结果,您可以在此项目中添加 LCD 屏幕。您可以在此处找到 Gautier Mechling为 1601 系列 LCD 屏幕提供的易于使用的驱动程序。
创建 TensorFlow 分类文件
您要做的第一件事是确保 TensorFlow 在您的计算机上并且可以正常工作。这可能相当复杂,我发现在生成训练文件的整个过程中使其正常工作的最简单方法是安装和使用Docker。该程序将允许您在计算机上运行为 TensorFlow 预配置的虚拟机。
一旦你安装了 Docker 并让它在你的计算机上运行,你应该打开它的首选项并为你的虚拟机设置内存使用。我将我的内存设置为使用 7 GB 内存,这可能超出了您的需要,但我花了几天时间试图让 TensorFlow 正确创建所需的训练图表而不会崩溃,然后我才意识到虚拟机内存不足。
一旦你安装了 Docker 并在你的机器上启动它,你需要从终端运行它并下载一个镜像。对于此示例,我在 macOS 下运行,因此对于您的平台,命令可能会有所不同。
docker run -it -v$HOME/tf_files:/tf_files gcr.io/tensorflow/tensorflow:latest-develcd /tensorflowgit pullgit checkout v1.0.1
当一切都完成设置后,您应该在终端中出现如下提示:
root@1643721c503b:/tensorflow#
此时,您需要一组图像来训练 TensorFlow。我使用Fatkun Batch DownloadImage Chrome 插件从 Google 搜索中批量下载返回的图像。安装插件后,您可以搜索要分类的任何内容并开始选择要保存的图像。
为了使命名更容易,您可能还需要进入“更多选项”部分,让插件在下载图像时重命名它们。
接下来,您需要将正在使用的图像移动到主目录下的tf_files文件夹中,这是我们在初始化 docker 机器时创建的文件夹。对于此示例,我的图像目录称为TensorFlowTrainingImages。每个可分类项目都应该在该目录中有自己的文件夹,如下所示。
设置好目录后,您可以从 Docker 终端使用以下命令开始重新训练:
pythontensorflow/examples/image_retraining/retrain.py \--bottleneck_dir=/tf_files/bottlenecks \--how_many_training_steps3000\--model_dir=/tf_files/inception \--output_graph=/tf_files/graph.pb \--output_labels=/tf_files/labels.txt \--image_dir/tf_files/TensorFlowTrainingImages
上面的命令会生成bottlenecks,本质上是最终分类数据传递使用的数据,以及用于分类的图形和标签文件。
从现在开始,我们使用 TensorFlow 运行的操作可能需要几分钟到一个多小时,具体取决于您计算机的速度。当重新训练命令运行时,您应该会在终端中看到很多类似于以下内容的输出:
Step130: Trainaccuracy =95.0%2017-04-1218:21:28.495779:Step130: Cross entropy =0.2503392017-04-1218:21:28.748928:Step130: Validation accuracy =92.0% (N=100)
生成瓶颈后,您将拥有一个graph.pb文件和一个代表您的数据的labels.txt文件。虽然这些格式在您的计算机上运行分类时效果很好,但它们在放入 Android 应用程序时往往不起作用。您将需要优化它们。
首先运行/configure
命令。接受所有默认值。
配置完成后,运行以下命令来设置优化工具。这一步在我的机器上完成了大约一个小时。
bazel build tensorflow/python/tools:optimize_for_inference
构建优化工具后,您可以使用它通过 bazel 优化您的图形文件。
bazel-bin/tensorflow/python/tools/optimize_for_inference \--input=/tf_files/graph.pb \--output=/tf_files/optimized_graph.pb \--input_names=Mul \--output_names=final_result
现在您的优化图已经生成,您可以在您的主目录的tf_files文件夹中找到它和您的标签。
一旦你有了优化的图表,你就可以将它包含在你的 Android Things 项目中以与之交互。如果您查看该项目的源代码,您可以看到使用 Camera2 API获取图像并将其传递给TensorFlowImageClassifier.java进行分类的 Java 代码。您还可以找到将分类图像上传到 Firebase 的代码,如下所示
privatevoiduploadAnimal(Bitmap bitmap,finalDetection detectedAnimal){ByteArrayOutputStream outputStream =newByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.JPEG,100, outputStream);byte[] data = outputStream.toByteArray();FirebaseStorage storage = FirebaseStorage.getInstance();StorageReference storageReference = storage.getReferenceFromUrl(FIREBASE_STORAGE_URL).child(System.currentTimeMillis() +".jpg");UploadTask uploadTask = storageReference.putBytes(data);uploadTask.addOnFailureListener(newOnFailureListener() {@OverridepublicvoidonFailure(@NonNullException exception){}}).addOnSuccessListener(newOnSuccessListener
() {
@OverridepublicvoidonSuccess(UploadTask.TaskSnapshot taskSnapshot){handleNotificationForImage(taskSnapshot.getDownloadUrl(),detectedAnimal);}});}
环境传感器
虽然能够识别野生动物很棒,但这里有机会做更多的事情。如果这些设备之一设置在荒野中,您还可以添加传感器来保存天气信息并将其报告给您的后端。对于我的原型,我包括了一个湿度传感器、温度和压力传感器、一个火焰探测器(理论上当周围没有人时通知某人野火)、一个空气质量传感器和一个紫外线传感器。其中一些在附加到 Android Things 方面有其独特的挑战,我将在下面介绍。
数字传感器
连接到野生动物探测器的最简单的传感器是火焰探测器和运动探测器。这些传感器在低电平空闲,但在检测到火焰或运动时切换到高电平。使用 Android Things 的外围 I/O API,这些传感器是最容易支持的,因为设备只需要监听状态的变化。
对 HC SR501 和火焰探测器的支持都遵循这个类的模式
@SuppressWarnings({"unused", "WeakerAccess"})publicclassHCSR501implementsAutoCloseable{publicenumState {STATE_HIGH,STATE_LOW;}publicinterfaceOnMotionDetectedEventListener{voidonMotionDetectedEvent(State state);}privateGpio mMotionDetectorGpio;privateOnMotionDetectedEventListener mOnMotionDetectedEventListener;privatebooleanmLastState;publicHCSR501(String pin)throwsIOException{PeripheralManagerService pioService =newPeripheralManagerService();Gpio HCSR501Gpio = pioService.openGpio(pin);try{connect(HCSR501Gpio);}catch( IOException | RuntimeException e ) {close();throwe;}}privatevoidconnect(Gpio HCSR501Gpio)throwsIOException{mMotionDetectorGpio = HCSR501Gpio;mMotionDetectorGpio.setDirection(Gpio.DIRECTION_IN);mMotionDetectorGpio.setEdgeTriggerType(Gpio.EDGE_BOTH);mLastState = mMotionDetectorGpio.getValue();mMotionDetectorGpio.setActiveType(mLastState ? Gpio.ACTIVE_HIGH : Gpio.ACTIVE_LOW);mMotionDetectorGpio.registerGpioCallback(mInterruptCallback);}privatevoidperformMotionEvent(State state){if( mOnMotionDetectedEventListener !=null) {mOnMotionDetectedEventListener.onMotionDetectedEvent(state);}}privateGpioCallback mInterruptCallback =newGpioCallback() {@OverridepublicbooleanonGpioEdge(Gpio gpio){try{if( gpio.getValue() != mLastState ) {mLastState = gpio.getValue();performMotionEvent(mLastState ? State.STATE_HIGH : State.STATE_LOW);}}catch( IOException e ) {}returntrue;}};publicvoidsetOnMotionDetectedEventListener(OnMotionDetectedEventListener listener){mOnMotionDetectedEventListener = listener;}@Overridepublicvoidclose()throwsIOException{mOnMotionDetectedEventListener =null;if(mMotionDetectorGpio !=null) {mMotionDetectorGpio.unregisterGpioCallback(mInterruptCallback);try{mMotionDetectorGpio.close();}finally{mMotionDetectorGpio =null;}}}}
vwin 传感器
Android Things 的模拟传感器有点棘手。虽然设备可能具有板载模数转换器(ADC),但它并未在 Android Things 平台上启用。为了解决这个问题,我使用了 MCP3008 ADC芯片来读取模拟输入并将其转换为可以在 Android Things 板上读取的 int。这是通过一种快速而肮脏的“bit banged”方法完成的,因此您可以更改引脚以匹配您可用的任何内容。使用 ADC,我能够添加对空气质量传感器和紫外线传感器的支持。以下代码是我用于 MCP3008 的代码,并且在我使用过的多个 Android Things 项目中被证明是有价值的。
publicclassMCP3008{privatefinalStringcsPin;privatefinalStringclockPin;privatefinalStringmosiPin;privatefinalStringmisoPin;privateGpio mCsPin;privateGpio mClockPin;privateGpio mMosiPin;privateGpio mMisoPin;publicMCP3008(StringcsPin,StringclockPin,StringmosiPin,StringmisoPin){this.csPin = csPin;this.clockPin = clockPin;this.mosiPin = mosiPin;this.misoPin = misoPin;}publicvoidregister()throws IOException{PeripheralManagerService service =newPeripheralManagerService();mClockPin = service.openGpio(clockPin);mCsPin = service.openGpio(csPin);mMosiPin = service.openGpio(mosiPin);mMisoPin = service.openGpio(misoPin);mClockPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);mCsPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);mMosiPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);mMisoPin.setDirection(Gpio.DIRECTION_IN);}publicintreadAdc(intchannel)throws IOException{if( channel <0|| channel >7) {thrownewIOException("ADC channel must be between 0 and 7");}initReadState();initChannelSelect(channel);returngetValueFromSelectedChannel();}privateintgetValueFromSelectedChannel()throws IOException{intvalue =0x0;for(inti =0; i <12; i++ ) {toggleClock();value <<=0x1;if( mMisoPin.getValue() ) {value |=0x1;}}mCsPin.setValue(true);value >>=0x1;// first bit is 'null', so drop itreturnvalue;}privatevoidinitReadState()throws IOException{mCsPin.setValue(true);mClockPin.setValue(false);mCsPin.setValue(false);}privatevoidinitChannelSelect(intchannel)throws IOException{intcommandout = channel;commandout |=0x18;// start bit + single-ended bitcommandout <<=0x3;// we only need to send 5 bitsfor(inti =0; i <5; i++ ) {if( ( commandout &0x80) !=0x0) {mMosiPin.setValue(true);}else{mMosiPin.setValue(false);}commandout <<=0x1;toggleClock();}}privatevoidtoggleClock()throws IOException{mClockPin.setValue(true);mClockPin.setValue(false);}publicvoidunregister(){if( mCsPin != null ) {try{mCsPin.close();}catch( IOException ignore ) {// do nothing}}if( mClockPin != null ) {try{mClockPin.close();}catch( IOException ignore ) {// do nothing}}if( mMisoPin != null ) {try{mMisoPin.close();}catch( IOException ignore ) {// do nothing}}if( mMosiPin != null ) {try{mMosiPin.close();}catch( IOException ignore ) {// do nothing}}}}
不支持的硬件
不幸的是,DHT11 湿度传感器使用以纳秒为间隔触发的信号协议,但 Android 平台仅支持低至毫秒。因此,Android Things 无法直接支持 DHT11。但是,有一种解决方法。使用带有Arduino的 ATMega328p,我能够将信息从 DHT11 读取到 Arduino 芯片,并使用 I²C 将该信息发送到 Android Things 设备。
您可以通过在 Android 中打开与该地址的连接来使用自定义地址读取 I²C
PeripheralManagerServiceservice= new PeripheralManagerService();mHumidity = service.openI2cDevice(BoardDefaults.getHumidityI2cBus(), 0x08);
在上面的示例中,我们使用的自定义地址是8。在 ATMega328p 上运行的 Arduino 代码中,您可以将该地址与 Wire 库一起使用。
#import
#include
dht11 DHT11;#defineDHT11PIN 13uint8_thumidity;voidsetup(){Wire.begin(8);// join i2c bus with address #8Wire.onRequest(requestEvent);// register event}voidloop(){intchk = DHT11.read(DHT11PIN);humidity = DHT11.humidity;delay(1000);}voidrequestEvent(){Wire.write(humidity);}
预先编写的驱动程序
虽然添加对数字 I/O 的支持很容易,但还有一件事更容易:使用已经编写的代码。对于 BMP280,我能够从 Google 的官方驱动程序库中引入一个预先编写的驱动程序,让我无需太多工作或时间就可以从该环境传感器读取信息。您可以在此处找到 Google 预先编写的示例,因为其中有一些可能对您使用 Android Things 组合在一起的任何项目有用。这些驱动程序很容易进入您的项目,就像将它们添加到您的 gradle 依赖项中一样
dependencies{compile'com.google.android.things.contrib:driver-bmx280:0.2'provided'com.google.android.things:androidthings:0.4-devpreview'}
对于这个项目,我还使用 GPS 驱动程序将位置数据添加到 Firebase,尽管您可以从您使用的任何网络连接中检索该数据。
网络连接
在当前状态下,野生动物探测器只是使用无线网络连接互联网。虽然这不是最实用的,特别是考虑到它很可能在没有现成的无线连接的区域使用,但可以轻松修改它以支持蜂窝连接或任何其他更合适的连接。
相机
这里的相机有点棘手。目前 Android Things 不完全支持USB摄像头,但您可以将它们视为UART设备。如果您不想为您的相机编写驱动程序,您也可以使用蓝牙相机,因为 Android Things 确实支持蓝牙连接。如果您将 Raspberry Pi 与 Android Things 一起使用,则可以使用标准的带状电缆摄像头,使用 Android 的摄像头 API,无需太多麻烦。
更多细节
虽然这个项目有很多事情要做,但可以在附加的源项目中找到更多详细信息。如上所述,一旦您生成了 TensorFlow 图,您应该能够下载源代码并将图文件替换为您尝试检测的任何内容。对于 Firebase 支持,您还需要创建自己的免费Firebase 项目并将凭据复制到项目中。
- 圣诞节运动探测器开源项目0次下载
- 圣诞老人探测器开源分享0次下载
- 野生动物驱虫剂传感器开源硬件0次下载
- 烟雾和气体探测器开源项目0次下载
- DULI通用图像损伤探测器开源分享0次下载
- 带警报系统的室温探测器开源分享0次下载
- WAiT:野生动物追踪器2次下载
- 激光雷达入侵探测器开源分享6次下载
- 濒临灭绝鸟类探测器开源分享0次下载
- Xiraffe桅杆上的智能野生动物观测站0次下载
- 555定时器构成的野生动物驱避传感器3次下载
- 智能金属探测器MOLE开源项目21次下载
- 盖革探测器开源项目4次下载
- 关于硅蓝光探测器在医疗监测中的应用1次下载
- 基于GPRS的温度远程监测系统设计97次下载
- 金属探测器电路图分享924次阅读
- 基于零维材料的光电探测器原子结构808次阅读
- 气体探测器怎么接线2.8w次阅读
- 红外线探测器距离_红外线探测器安装1.2w次阅读
- 金属探测器怎么用_金属探测器的使用方法5.8w次阅读
- 半导体探测器的工作原理_半导体探测器应用领域1.4w次阅读
- 闪烁探测器探测原理_闪烁探测器的结构组成1.5w次阅读
- 热释电红外探测器的测量原理解析4430次阅读
- 剩余电流探测器原理_剩余电流探测器的应用8816次阅读
- 热探测器有哪些_热探测器的工作原理1w次阅读
- 如何制作一个金属探测器?4.9w次阅读
- 火焰探测器工作原理4.8w次阅读
- Festo以大自然为灵感设计各种仿生动物机器人 并且非常逼真8219次阅读
- 金属探测器电路分析9175次阅读
- 自制高频振荡金属探测器1.3w次阅读
下载排行
本周
- 1山景DSP芯片AP8248A2数据手册
- 1.06 MB |532次下载 |免费
- 2RK3399完整板原理图(支持平板,盒子VR)
- 3.28 MB |339次下载 |免费
- 3TC358743XBG评估板参考手册
- 1.36 MB |330次下载 |免费
- 4DFM软件使用教程
- 0.84 MB |295次下载 |免费
- 5元宇宙深度解析—未来的未来-风口还是泡沫
- 6.40 MB |227次下载 |免费
- 6迪文DGUS开发指南
- 31.67 MB |194次下载 |免费
- 7元宇宙底层硬件系列报告
- 13.42 MB |182次下载 |免费
- 8FP5207XR-G1中文应用手册
- 1.09 MB |178次下载 |免费
本月
- 1OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB |234315次下载 |免费
- 2555集成电路应用800例(新编版)
- 0.00 MB |33566次下载 |免费
- 3接口电路图大全
- 未知 |30323次下载 |免费
- 4开关电源设计实例指南
- 未知 |21549次下载 |免费
- 5电气工程师手册免费下载(新编第二版pdf电子书)
- 0.00 MB |15349次下载 |免费
- 6数字电路基础pdf(下载)
- 未知 |13750次下载 |免费
- 7电子制作实例集锦 下载
- 未知 |8113次下载 |免费
- 8《LED驱动电路设计》 温德尔著
- 0.00 MB |6656次下载 |免费
总榜
- 1matlab软件下载入口
- 未知 |935054次下载 |免费
- 2protel99se软件下载(可英文版转中文版)
- 78.1 MB |537798次下载 |免费
- 3MATLAB 7.1 下载 (含软件介绍)
- 未知 |420027次下载 |免费
- 4OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB |234315次下载 |免费
- 5Altium DXP2002下载入口
- 未知 |233046次下载 |免费
- 6电路仿真软件multisim 10.0免费下载
- 340992 |191187次下载 |免费
- 7十天学会AVR单片机与C语言视频教程 下载
- 158M |183279次下载 |免费
- 8proe5.0野火版下载(中文版免费下载)
- 未知 |138040次下载 |免费
评论
查看更多