建置一個不用三百元的無線影像串流主機

文章推薦指數: 80 %
投票人數:10人

安裝ESP32-CAM. 第一次使用時,需要安裝ESP32的libraries,首先打開Arduino IDE後,在「偏好設定」中的「額外的 ... 直接觀看文章 中國樂鑫科技所推出的ESP32和ESP8266都內建32bitsMCPU,屬於價廉物美且方便好用的WIFI模組,這兩者最大的差異,在於ESP32為ESP8266的升級加強版本,其MCU核心數為兩個,還多增加了Bluetooth4.2.3和BLE的支援,GPIO腳位也double到16根。

(詳細的差異比較請參考https://makeradvisor.com/esp32-vs-esp8266/) 如果上面提到的ESP32、ESP8266你聽過,那麼您也應該聽過ESP32-CAM,它是因應物聯網的低成本高性能需求而誔生,ESP32加上二百萬像素camera不到三百元,大大壓低了edge影像端的硬體成本。

規格 內置520KBSRAM,外部4MPSRAM GPIO支援UART/SPI/I2C/PWM/ADC/DA Baundrate:默認值115200bps 內建SD卡匣。

內建一顆補光用LED閃光燈。

建議電源:至少為5V2A,否則圖像上可能會出現水波紋。

5V耗電量:關閉閃光燈:180mA、打開閃光燈:310mA、深度睡眠6mA、Moderm-sleep20mA、Light-睡眠:高達6.7mA@5V。

支援的拍攝尺寸:QQVGA(160×120)、HQVGA(240×176)、QVGA(320×240)、CIF(400×296)、VGA(640×480)、SVGA(800×600)、XVGA(1024×768)、SXGA(1280×1024)、UXGA(1600×1200)   安裝 剛買來的ESP32-CAM,鏡頭與模組是分離的,需要先安裝。

基本上,只要插入再按下即可。

使用USBTTL 由於成本及體積因素,ESP-CAM沒有內建USB燒錄介面,因此必須另外準備USB轉TTL模組,其接法如下: 此外,在上傳code之前,必須先將ID0腳位接地,再按一下reset鍵,才能成功燒錄。

(下圖右的ID0,GND黃圈畫錯了,需再往下一個pin) 安裝ESP32-CAM 第一次使用時,需要安裝ESP32的libraries,首先打開ArduinoIDE後,在「偏好設定」中的「額外的開發管理員模組」中,輸入https://dl.espressif.com/dl/package_esp32_index.json,按確定後便開始下載。

接著,進入開發板管理員。

輸入ESP32關鍵字找到esp32板子,直接安裝。

從工具選項中,選擇板子及設定如下,便完成ESP32-CAM的安裝了。

使用Arduino燒錄 如下方的程序,取出CameraWebServer範例程式。

更改程式中WIFI的連線設定: constchar*ssid=“您的WIFISSID"; constchar*password=“SSID密碼"; 接著,將ESP32-CAM上的GND與ID0對接,再按一下reset鍵,便可開始將code燒錄至ESP32-CAM,燒錄的畫面如下: 燒錄完成後,便可移除ID0與GND的對接。

接著,開啟ArduinoIDE的序列埠監控視窗,再按一下reset鍵,可看到如下的,webserver啟動時的message。

於PC或手機上,開啟瀏覽器進入ESP32-CAM的URL,可看到串流的畫面,由於WIFI與PC皆在相同的區網內,因此就算畫面尺寸設為VGA以上,仍相當順暢。

  使用YOLO偵測ESP32-CAM遠端影像 下面我們進行的測試,是將edge端(ESP32-CAM)的影像,以640×480VGA大小,以影像串流方式傳輸到另一台PC進行即時偵測,使用的是之前訓練好YOLOV3-Tiny的口罩模型。

效果如下,這是在網路穩定且PC端執行YOLOmodel效率不錯的的情況下,影像傳輸的解析度640×480。

不過忘了計算及記錄FPS,感覺上至少有20FPS以上。

  下方為接收ESP32-CAM影像串流的接收及YOLO偵測程式,ESP32-CAM使用的CameraWebServerArduino範例程式,使用80port及81port。

http://{ESP32-CAM的IP}/ 是ESP32-CAM影像串流的設定介面,您可以在此設定影像傳輸的參數,設定後會立即生效,並維持到下次重新開機為止。

如果想要修改預設值,可從Arduino主程式中修改。

http://{ESP32-CAM的IP}:81/stream 是ESP32-CAM影像串流的URL,開機後ESP32-CAM持續的透過此URL串流影像。

注意,此URL限制一次只能有一個連線。

影像串流接收端的YOLO偵測程式 程式中用到的中文字形檔可由此下載:https://github.com/ch-tseng/mytools/raw/master/functions/wt009.ttf yoloOpencv.py:https://raw.githubusercontent.com/ch-tseng/mytools/master/yolo/yoloOpencv.py fromyoloOpencvimportopencvYOLO fromPILimportImageFont,ImageDraw,Image fromurllib.requestimporturlopen importcv2 importimutils importtime importnumpyasnp yolo=opencvYOLO(modeltype="yolov3-tiny",\ objnames="mask_face_outsource_yolov3-tiny/obj.names",\ weights="mask_face_outsource_yolov3-tiny/yolov3-tiny_91000.weights",\ cfg="mask_face_outsource_yolov3-tiny/yolov3-tiny.cfg") labels_tw={"none":"口罩沒有戴好","good":"正確配戴口罩","bad":"沒有戴口罩"} #media="videos/EscapingCoronaVirusАэрофлотAeroflotB777-300ERShanghaiChinatoMoscowRussiaFlightReview" write_video=True record_width,record_height=640,480 video_out="out_o1.avi" output_rotate=True rotate=180 #ESP32-CAM url="http://172.30.17.165:81/stream" CAMERA_BUFFRER_SIZE=4096 #fpscount start=time.time() deffps_count(num_frames): end=time.time() seconds=end-start fps=num_frames/seconds; print("Estimatedframespersecond:{0}".format(fps)) returnfps defprintText(bg,txt,color=(0,255,0,0),size=0.7,pos=(0,0),type="Chinese"): (b,g,r,a)=color if(type=="English"): cv2.putText(bg,txt,pos,cv2.FONT_HERSHEY_SIMPLEX,size,(b,g,r),2,cv2.LINE_AA) else: ##Usesimsum.ttftowriteChinese. fontpath="fonts/wt009.ttf" font=ImageFont.truetype(fontpath,int(size*10*4)) img_pil=Image.fromarray(bg) draw=ImageDraw.Draw(img_pil) draw.text(pos,txt,font=font,fill=(b,g,r,a)) bg=np.array(img_pil) returnbg defread_stream(): globalbts bts+=stream.read(CAMERA_BUFFRER_SIZE) jpghead=bts.find(b'\xff\xd8') jpgend=bts.find(b'\xff\xd9') print("jpghead,jpgend",jpghead,jpgend) img=None height,width=0,0 ifjpghead>-1andjpgend>-1: jpg=bts[jpghead:jpgend+2] bts=bts[jpgend+2:] try: img=cv2.imdecode(np.frombuffer(jpg,dtype=np.uint8),cv2.IMREAD_UNCHANGED) #v=cv.flip(img,0) #h=cv.flip(img,1) #p=cv2.flip(img,-1) #frame=p height,width=img.shape[:2] img=cv2.resize(img,(record_width,record_height)) print(img.shape) except: img=None print("nodatareceived.") returnimg,(width,height) bts=b'' if__name__=="__main__": if(write_videoisTrue): fourcc=cv2.VideoWriter_fourcc(*'MJPG') out=cv2.VideoWriter(video_out,fourcc,20.0,(record_width,record_height)) stream=urlopen(url) frameID=0 img=None whileTrue: img,(width,height)=read_stream() ifimgisnotNone: if(output_rotateisTrue): img=imutils.rotate(img,rotate) yolo.getObject(img,labelWant="",drawBox=True,bold=2,textsize=0.95,bcolor=(255,255,255),tcolor=(0,255,255)) forid,labelinenumerate(yolo.labelNames): x=yolo.bbox[id][0] y=yolo.bbox[id][1] w=yolo.bbox[id][2] h=yolo.bbox[id][3] cx=int(x) if(cx>width):cx=width-60 cy=int(y-h/3) if(cy<0):cy=0 if(label=="bad"): txt_color=(0,0,255,0) elif(label=="none"): txt_color=(255,255,0,0) else: txt_color=(0,255,0,0) txt_size=round(w/250,1) print(labels_tw[label],(w,h)) img=printText(bg=img,txt=labels_tw[label],color=txt_color,size=txt_size,pos=(cx,cy),type="Chinese") cv2.imshow("Frame",img) k=cv2.waitKey(1) ifk&0xFF==ord('q'): cv.destroyAllWindows() if(write_videoisTrue): out.release() break frameID+=1 fps_count(frameID) if(write_videoisTrue): out.write(img) Sharethis:TwitterFacebook請按讚:喜歡正在載入... 文章分頁導航 上一個使用TripleLoss來偵測手勢下一步知識蒸餾KnowledgeDistillation 發表者:chtseng 檢視「chtseng」的全部文章 Flickr相片 更多相片 追蹤 已追蹤 CH.Tseng 加入其他107位關注者 我要註冊 已經有WordPress.com帳號了?立即登入。

CH.Tseng 自訂 追蹤 已追蹤 註冊 登入 複製短網址 回報此內容 以閱讀器檢視 管理訂閱 收合此列 %d位部落客按了讚:



請為這篇文章評分?