資料介紹
描述
在科羅拉多州和其他擁有大量野生動物種群的州,人類與野生動物之間的沖突并不少見(城鎮(zhèn)中的熊和駝鹿、涉及麋鹿的交通事故等)
我決定通過創(chuàng)建一個檢測運動、拍照并使用機器學習算法分析它以采取某種行動(嚇跑它、點亮標志、通知當局)。此外,該設備跟蹤環(huán)境數(shù)據(jù),以幫助研究人員跟蹤可能導致更多野生動物遭遇的遷徙模式和條件,它還檢測野火以防止不必要的破壞。

分類
該項目的主要重點是機器學習野生動物分類。我通過訓練 TensorFlow 來使用來自 Google 圖片的數(shù)據(jù)來識別四種特定的動物物種,從而實現(xiàn)了這一點。所有的初始訓練都是在計算機上使用為 TensorFlow 和一千多張野生動物圖片預先配置的 docker 機器圖像完成的。一旦 TensorFlow 被訓練,圖形文件被優(yōu)化以在移動設備上運行,然后它可以被用來在 Android Things 設備上運行,方法是拍攝一張圖像,調(diào)整它的大小,然后通過 TensorFlow 運行它以確定該圖像是否包含一個我們預先訓練的分類,以及到什么置信水平。
一旦確定了動物,就必須對這些數(shù)據(jù)進行處理。根據(jù)您的情況,您可以使用額外的硬件來閃光、播放聲音或做任何其他事情。對于這個原型,我將 Android Things 連接到 Firebase 后端,以便簡單地保存圖像和分類信息。

?

將信息存儲在 Firebase 上后,您可以創(chuàng)建一個輔助應用程序來接收有關動物存在的通知,或者只是存儲該數(shù)據(jù)以用于研究目的。
此外,如果您希望無需檢查 Firebase 即可看到結果,您可以在此項目中添加 LCD 屏幕。您可以在此處找到 Gautier Mechling為 1601 系列 LCD 屏幕提供的易于使用的驅(qū)動程序。
創(chuàng)建 TensorFlow 分類文件
您要做的第一件事是確保 TensorFlow 在您的計算機上并且可以正常工作。這可能相當復雜,我發(fā)現(xiàn)在生成訓練文件的整個過程中使其正常工作的最簡單方法是安裝和使用Docker。該程序?qū)⒃试S您在計算機上運行為 TensorFlow 預配置的虛擬機。
一旦你安裝了 Docker 并讓它在你的計算機上運行,??你應該打開它的首選項并為你的虛擬機設置內(nèi)存使用。我將我的內(nèi)存設置為使用 7 GB 內(nèi)存,這可能超出了您的需要,但我花了幾天時間試圖讓 TensorFlow 正確創(chuàng)建所需的訓練圖表而不會崩潰,然后我才意識到虛擬機內(nèi)存不足。

一旦你安裝了 Docker 并在你的機器上啟動它,你需要從終端運行它并下載一個鏡像。對于此示例,我在 macOS 下運行,因此對于您的平臺,命令可能會有所不同。
docker run -it -v $HOME/tf_files:/tf_files gcr.io/tensorflow/tensorflow:latest-develcd /tensorflowgit pullgit checkout v1.0.1
		當一切都完成設置后,您應該在終端中出現(xiàn)如下提示:
root@1643721c503b:/tensorflow#
		此時,您需要一組圖像來訓練 TensorFlow。我使用Fatkun Batch Download Image Chrome 插件從 Google 搜索中批量下載返回的圖像。安裝插件后,您可以搜索要分類的任何內(nèi)容并開始選擇要保存的圖像。

為了使命名更容易,您可能還需要進入“更多選項”部分,讓插件在下載圖像時重命名它們。

接下來,您需要將正在使用的圖像移動到主目錄下的tf_files文件夾中,這是我們在初始化 docker 機器時創(chuàng)建的文件夾。對于此示例,我的圖像目錄稱為TensorFlowTrainingImages 。每個可分類項目都應該在該目錄中有自己的文件夾,如下所示。

設置好目錄后,您可以從 Docker 終端使用以下命令開始重新訓練:
python tensorflow/examples/image_retraining/retrain.py \  
--bottleneck_dir=/tf_files/bottlenecks \  
--how_many_training_steps 3000 \  
--model_dir=/tf_files/inception \  
--output_graph=/tf_files/graph.pb \  
--output_labels=/tf_files/labels.txt \  
--image_dir /tf_files/TensorFlowTrainingImages
		上面的命令會生成bottlenecks ,本質(zhì)上是最終分類數(shù)據(jù)傳遞使用的數(shù)據(jù),以及用于分類的圖形和標簽文件。
從現(xiàn)在開始,我們使用 TensorFlow 運行的操作可能需要幾分鐘到一個多小時,具體取決于您計算機的速度。當重新訓練命令運行時,您應該會在終端中看到很多類似于以下內(nèi)容的輸出:
Step 130: Train accuracy = 95.0%2017-04-12 18:21:28.495779: 
Step 130: Cross entropy = 0.2503392017-04-12 18:21:28.748928: 
Step 130: Validation accuracy = 92.0% (N=100) 
		生成瓶頸后,您將擁有一個graph.pb文件和一個代表您的數(shù)據(jù)的labels.txt文件。雖然這些格式在您的計算機上運行分類時效果很好,但它們在放入 Android 應用程序時往往不起作用。您將需要優(yōu)化它們。
			首先運行/configure 命令。接受所有默認值。
配置完成后,運行以下命令來設置優(yōu)化工具。這一步在我的機器上完成了大約一個小時。
bazel build tensorflow/python/tools:optimize_for_inference
		構建優(yōu)化工具后,您可以使用它通過 bazel 優(yōu)化您的圖形文件。
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
		現(xiàn)在您的優(yōu)化圖已經(jīng)生成,您可以在您的主目錄的tf_files文件夾中找到它和您的標簽。

一旦你有了優(yōu)化的圖表,你就可以將它包含在你的 Android Things 項目中以與之交互。如果您查看該項目的源代碼,您可以看到使用 Camera2 API 獲取圖像并將其傳遞給TensorFlowImageClassifier.java進行分類的 Java 代碼。您還可以找到將分類圖像上傳到 Firebase 的代碼,如下所示
private void uploadAnimal(Bitmap bitmap, final Detection detectedAnimal) { 
   ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
   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(new OnFailureListener() { 
       @Override 
       public void onFailure(@NonNull Exception exception) { 
       } 
   }).addOnSuccessListener(new OnSuccessListener() { 
        @Override 
       public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { 
           handleNotificationForImage(taskSnapshot.getDownloadUrl(), 
                                      detectedAnimal); 
       } 
   }); 
} 
		環(huán)境傳感器
雖然能夠識別野生動物很棒,但這里有機會做更多的事情。如果這些設備之一設置在荒野中,您還可以添加傳感器來保存天氣信息并將其報告給您的后端。對于我的原型,我包括了一個濕度傳感器、溫度和壓力傳感器、一個火焰探測器(理論上當周圍沒有人時通知某人野火)、一個空氣質(zhì)量傳感器和一個紫外線傳感器。其中一些在附加到 Android Things 方面有其獨特的挑戰(zhàn),我將在下面介紹。
數(shù)字傳感器
連接到野生動物探測器的最簡單的傳感器是火焰探測器和運動探測器。這些傳感器在低電平空閑,但在檢測到火焰或運動時切換到高電平。使用 Android Things 的外圍 I/O API,這些傳感器是最容易支持的,因為設備只需要監(jiān)聽狀態(tài)的變化。
對 HC SR501 和火焰探測器的支持都遵循這個類的模式
@SuppressWarnings({"unused", "WeakerAccess"})
public class HCSR501 implements AutoCloseable {
   public enum State {
       STATE_HIGH,
       STATE_LOW;
   }
   public interface OnMotionDetectedEventListener {
       void onMotionDetectedEvent(State state);
   }
   private Gpio mMotionDetectorGpio;
   private OnMotionDetectedEventListener mOnMotionDetectedEventListener;
   private boolean mLastState;
   public HCSR501(String pin) throws IOException {
       PeripheralManagerService pioService = new PeripheralManagerService();
       Gpio HCSR501Gpio = pioService.openGpio(pin);
       try {
           connect(HCSR501Gpio);
       } catch( IOException | RuntimeException e ) {
           close();
           throw e;
       }
   }
   private void connect(Gpio HCSR501Gpio) throws IOException {
       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);
   }
   private void performMotionEvent(State state) {
       if( mOnMotionDetectedEventListener != null ) {
           mOnMotionDetectedEventListener.onMotionDetectedEvent(state);
       }
   }
   private GpioCallback mInterruptCallback = new GpioCallback() {
       @Override
       public boolean onGpioEdge(Gpio gpio) {
           try {
               if( gpio.getValue() != mLastState ) {
                   mLastState = gpio.getValue();
                   performMotionEvent(mLastState ? State.STATE_HIGH : State.STATE_LOW);
               }
           } catch( IOException e ) {
           }
           return true;
       }
   };
   public void setOnMotionDetectedEventListener(OnMotionDetectedEventListener listener) {
       mOnMotionDetectedEventListener = listener;
   }
   @Override
   public void close() throws IOException {
       mOnMotionDetectedEventListener = null;
       if (mMotionDetectorGpio != null) {
           mMotionDetectorGpio.unregisterGpioCallback(mInterruptCallback);
           try {
               mMotionDetectorGpio.close();
           } finally {
               mMotionDetectorGpio = null;
           }
       }
   }
}
		模擬傳感器
Android Things 的模擬傳感器有點棘手。雖然設備可能具有板載模數(shù)轉(zhuǎn)換器 (ADC),但它并未在 Android Things 平臺上啟用。為了解決這個問題,我使用了 MCP3008 ADC 芯片來讀取模擬輸入并將其轉(zhuǎn)換為可以在 Android Things 板上讀取的 int。這是通過一種快速而骯臟的“bit banged”方法完成的,因此您可以更改引腳以匹配您可用的任何內(nèi)容。使用 ADC,我能夠添加對空氣質(zhì)量傳感器和紫外線傳感器的支持。以下代碼是我用于 MCP3008 的代碼,并且在我使用過的多個 Android Things 項目中被證明是有價值的。
public class MCP3008 {
   private final String csPin;
   private final String clockPin;
   private final String mosiPin;
   private final String misoPin;
   private Gpio mCsPin;
   private Gpio mClockPin;
   private Gpio mMosiPin;
   private Gpio mMisoPin;
   public MCP3008(String csPin, String clockPin, String mosiPin, String misoPin) {
       this.csPin = csPin;
       this.clockPin = clockPin;
       this.mosiPin = mosiPin;
       this.misoPin = misoPin;
   }
   public void register() throws IOException {
       PeripheralManagerService service = new PeripheralManagerService();
       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);
   }
   public int readAdc(int channel) throws IOException {
       if( channel < 0 || channel > 7 ) {
           throw new IOException("ADC channel must be between 0 and 7");
       }
       initReadState();
       initChannelSelect(channel);
       return getValueFromSelectedChannel();
   }
   private int getValueFromSelectedChannel() throws IOException {
       int value = 0x0;
       for( int i = 0; i < 12; i++ ) {
           toggleClock();
           value <<= 0x1;
           if( mMisoPin.getValue() ) {
               value |= 0x1;
           }
       }
       mCsPin.setValue(true);
       value >>= 0x1; // first bit is 'null', so drop it
       return value;
   }
   private void initReadState() throws IOException {
       mCsPin.setValue(true);
       mClockPin.setValue(false);
       mCsPin.setValue(false);
   }
   private void initChannelSelect(int channel) throws IOException {
       int commandout = channel;
       commandout |= 0x18; // start bit + single-ended bit
       commandout <<= 0x3; // we only need to send 5 bits
       for( int i = 0; i < 5; i++ ) {
           if ( ( commandout & 0x80 ) != 0x0 ) {
               mMosiPin.setValue(true);
           } else {
               mMosiPin.setValue(false);
           }
           commandout <<= 0x1;
           toggleClock();
       }
   }
   private void toggleClock() throws IOException {
       mClockPin.setValue(true);
       mClockPin.setValue(false);
   }
   public void unregister() {
       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 濕度傳感器使用以納秒為間隔觸發(fā)的信號協(xié)議,但 Android 平臺僅支持低至毫秒。因此,Android Things 無法直接支持 DHT11。但是,有一種解決方法。使用帶有 Arduino 的 ATMega328p,我能夠?qū)⑿畔?DHT11 讀取到 Arduino 芯片,并使用 I2C 將該信息發(fā)送到 Android Things 設備。

您可以通過在 Android 中打開與該地址的連接來使用自定義地址讀取 I2C
PeripheralManagerService service = new PeripheralManagerService();
mHumidity = service.openI2cDevice(BoardDefaults.getHumidityI2cBus(), 0x08);
		在上面的示例中,我們使用的自定義地址是8 。在 ATMega328p 上運行的 Arduino 代碼中,您可以將該地址與 Wire 庫一起使用。
#import  
#include  
 
dht11 DHT11;
 
#define DHT11PIN 13
 
uint8_t humidity;
 
void setup() {
 Wire.begin(8);                // join i2c bus with address #8
 Wire.onRequest(requestEvent); // register event
}
 
void loop() {
 int chk = DHT11.read(DHT11PIN);
 humidity = DHT11.humidity;
 delay(1000);
}
 
void requestEvent() {
 Wire.write(humidity);
}
		預先編寫的驅(qū)動程序
雖然添加對數(shù)字 I/O 的支持很容易,但還有一件事更容易:使用已經(jīng)編寫的代碼。對于 BMP280,我能夠從 Google 的官方驅(qū)動程序庫中引入一個預先編寫的驅(qū)動程序,讓我無需太多工作或時間就可以從該環(huán)境傳感器讀取信息。您可以在此處找到 Google 預先編寫的示例,因為其中有一些可能對您使用 Android Things 組合在一起的任何項目有用。這些驅(qū)動程序很容易進入您的項目,就像將它們添加到您的 gradle 依賴項中一樣
dependencies {
   compile 'com.google.android.things.contrib:driver-bmx280:0.2'
   provided 'com.google.android.things:androidthings:0.4-devpreview'
}
		對于這個項目,我還使用 GPS 驅(qū)動程序?qū)⑽恢脭?shù)據(jù)添加到 Firebase,盡管您可以從您使用的任何網(wǎng)絡連接中檢索該數(shù)據(jù)。
網(wǎng)絡連接
在當前狀態(tài)下,野生動物探測器只是使用無線網(wǎng)絡連接互聯(lián)網(wǎng)。雖然這不是最實用的,特別是考慮到它很可能在沒有現(xiàn)成的無線連接的區(qū)域使用,但可以輕松修改它以支持蜂窩連接或任何其他更合適的連接。
相機
這里的相機有點棘手。目前 Android Things 不完全支持 USB 攝像頭,但您可以將它們視為 UART 設備。如果您不想為您的相機編寫驅(qū)動程序,您也可以使用藍牙相機,因為 Android Things 確實支持藍牙連接。如果您將 Raspberry Pi 與 Android Things 一起使用,則可以使用標準的帶狀電纜攝像頭,使用 Android 的攝像頭 API,無需太多麻煩。
更多細節(jié)
雖然這個項目有很多事情要做,但可以在附加的源項目中找到更多詳細信息。如上所述,一旦您生成了 TensorFlow 圖,您應該能夠下載源代碼并將圖文件替換為您嘗試檢測的任何內(nèi)容。對于 Firebase 支持,您還需要創(chuàng)建自己的免費Firebase 項目并將憑據(jù)復制到項目中。
- 圣誕節(jié)運動探測器開源項目
 - 圣誕老人探測器開源分享
 - 野生動物驅(qū)蟲劑傳感器開源硬件
 - 煙霧和氣體探測器開源項目
 - Lane Tech HS PCL RAGE探測器開源分享
 - WAiT:野生動物追蹤器
 - 激光雷達入侵探測器開源分享
 - 瀕臨滅絕鳥類探測器開源分享
 - Xiraffe桅桿上的智能野生動物觀測站
 - 脈沖微處理器金屬探測器開源設計
 - 555定時器構成的野生動物驅(qū)避傳感器
 - BT智能手機探測器開源項目
 - 智能金屬探測器MOLE開源項目
 - 蓋革探測器開源項目
 - 基于GPRS的溫度遠程監(jiān)測系統(tǒng)設計 97次下載
 
- 熱解粒子探測器與什么相似 403次閱讀
 - 被動紅外探測器和主動紅外探測器的區(qū)別 1394次閱讀
 - 金屬探測器電路圖 帶Arduino的金屬探測器設計 2500次閱讀
 - 探索紅外熱成像探測器的基礎原理 897次閱讀
 - 金屬探測器電路圖分享 7837次閱讀
 - 氣體探測器怎么接線 3.3w次閱讀
 - 紅外線探測器距離_紅外線探測器安裝 1.4w次閱讀
 - 金屬探測器怎么用_金屬探測器的使用方法 6.1w次閱讀
 - 半導體探測器的工作原理_半導體探測器應用領域 1.5w次閱讀
 - 火焰探測器接線圖_火焰探測器設置要求 4.7w次閱讀
 - 火焰探測器保護半徑_火焰探測器適用場所 1.1w次閱讀
 - 剩余電流探測器原理_剩余電流探測器的應用 1w次閱讀
 - 如何制作一個金屬探測器? 5.2w次閱讀
 - 火焰探測器工作原理 5.2w次閱讀
 - 自制高頻振蕩金屬探測器 1.5w次閱讀
 
下載排行
本周
- 1山景DSP芯片AP8248A2數(shù)據(jù)手冊
 - 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開發(fā)指南
 - 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數(shù)字電路基礎pdf(下載)
 - 未知 | 13750次下載 | 免費
 - 7電子制作實例集錦 下載
 - 未知 | 8113次下載 | 免費
 - 8《LED驅(qū)動電路設計》 溫德爾著
 - 0.00 MB | 6656次下載 | 免費
 
總榜
- 1matlab軟件下載入口
 - 未知 | 935054次下載 | 免費
 - 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
 - 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次下載 | 免費
 
	                電子發(fā)燒友App
	            
	        
	        
          
        
        
	                    
                        
                        
                        
                        
                        


創(chuàng)作
發(fā)文章
發(fā)帖  
提問  
發(fā)資料
發(fā)視頻
上傳資料賺積分
           
            
            
                
            
評論