###### tags: `Construction`
## 示意圖

## 推流
```bash=
$ gst-launch-1.0 -v v4l2src device=/dev/video0 ! video/x-raw,format=YUY2,width=1280,height=720,framerate=10/1 ! videoconvert ! x264enc bitrate=2000 ! h264parse ! flvmux ! rtmpsink location=rtmp://192.168.0.126:1935/live/stream
$ gst-launch-1.0 -v v4l2src device=/dev/video0 ! videoconvert ! videoscale ! video/x-raw,width=640,height=480 ! x264enc tune=zerolatency bitrate=1500 key-int-max=30 ! mpegtsmux ! udpsink host=192.168.0.152 port=1935
```
檢查
```cpp=
$ cd /usr/local/nginx/html/hls
```
## 小小解釋
名詞解釋 Web Server,他對於PC iPhone這些請求者他是Server,但對每個樹梅派(獲取畫面)Web Server同時也是Client,對其他樹梅派請求畫面,是對Server(樹梅派)來請求。 但為了避免搞混,統稱Web Server 為 Server,有畫面的樹梅派是Client。
### 設定這個 Web Server 樹梅派需要先安裝 NGINX。
目前是在處理這裡

1. 安裝所需的依賴:
首先,您需要安裝一些必要的Requirement。
```c++=
# bash 終端機畫面
sudo apt update && sudo apt upgrade -y
sudo apt install nginx -y
```
2. 下載NGINX和RTMP模組:
```c++=
# bash 下載並且解壓縮
cd ~
wget http://nginx.org/download/nginx-1.18.0.tar.gz
tar -zxvf nginx-1.18.0.tar.gz
git clone https://github.com/arut/nginx-rtmp-module.git
```
3. 編譯和安裝:
```c++=
# bash 新增必要rtmp模組 沒有NGINX他無法認出RTMP的串流 進而無法處理
如果編譯出錯 可以先試試安裝這個
sudo apt-get update
sudo apt-get install libpcre3 libpcre3-dev
sudo apt-get install libssl-dev
cd nginx-1.18.0
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module
make
sudo make install
```
4. 配置NGINX以支持RTMP和HLS:
編輯NGINX的配置文件:
```c++=
# bash 開啟編輯文字工具修改NGINX conf參數 要讓他把RTMP的串流轉向成HLS (m3u8描述檔)
sudo nano /usr/local/nginx/conf/nginx.conf
或
sudo vim /usr/local/nginx/conf/nginx.conf
```
在http部分,加入HLS配置:
```javascript!=
# 原始檔案 會有很多註解掉的功能都不要管
http {
server {
listen 80; # HTTP port
server_name 192.168.0.126; # 替換為你的Domain IP
location / {
root /usr/local/nginx/html;
index index.html; #這個index.html 要放在/usr/local/nginx/html 底下
}
# 增加HLS播放路径
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /usr/local/nginx/html;
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *; # 允許跨域訪問
}
}
}
```
在文件的底部,加入RTMP配置:
```javascript!=
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
hls on;
hls_path /tmp/hls; #最後你需要確認你的本機有這個資料夾否則會無法寫入
hls_fragment 5s; # HLS切片时长
hls_playlist_length 30s; # HLS播放列表时长
}
}
}
```
保存並退出編輯器。
5. 啟動NGINX:
```bash!=
sudo /usr/local/nginx/sbin/nginx
```
或是您已經安裝好並且已經運行了 那可以重新reload。
```bash!=
sudo /usr/local/nginx/sbin/nginx -s reload
sudo /usr/local/nginx/sbin/nginx -s stop
```
### 設定個別裝有CAM的Rpi 樹梅派需要安裝 FFmpeg。
6. 推流到NGINX:
使用OBS或其他任何RTMP源,設置您的推流URL為:
```bash!=
rtmp://[你的樹梅派IP]/live/[流名稱]
```
例如使用OBS 我就會把URL填入rtmp://192.168.0.126/live/
金鑰填 stream
其中192.168.0.126是我Web Server的本機IP,通常不會一樣所以要記得改ㄛ。
如果是停車位旁邊的樹梅派,就使用ffmpeg推流,只要確保ffmpeg有正常安裝,並且推h264的串流給Web Server,就可以在第7步看到畫面了。
ffmpeg 我覺得類似 OBS,可以這樣去理解他。
7. 觀看串流:
您可以使用VLC或其他HLS支持的播放器,並打開以下URL來觀看流:
```bash=
http://[你的樹梅派IP]/hls/[流名稱].m3u8
```
8. 小小說明
說明一下 NGINX 如果不懂原理可以看一下這個,他是一個反向代理的伺服器,當然他也可以作為一個HTTP的伺服器。
想像一下你去一家餐廳吃飯,這家餐廳特別忙碌,所以他們有一名「接待員」站在門口幫你接受訂單,然後再將你的訂單轉告給內部的廚師。在這個情境中,「接待員」其實就像是 NGINX 反向代理伺服器。
隱藏內部結構:就像你不需要知道餐廳有幾位廚師,或他們如何工作,反向代理會隱藏你的內部伺服器結構,使外部用戶只知道反向代理的存在。
負載平衡:如果餐廳內有多位廚師,接待員可以根據各位廚師的忙碌程度,決定將訂單給哪位廚師。同理,當有很多伺服器時,NGINX 可以根據伺服器的負載情況,將用戶的請求導向最適合的伺服器。
加速內容遞送:接待員可能已經知道某些客人常點的餐點,所以他們可以預先準備,從而更快地提供給客人。同樣地,NGINX 可以快取某些內容,當用戶請求這些內容時,可以直接從快取中取得,而不需要重新從伺服器取得。
安全性:如果有些客人的行為不太好,接待員可以決定不讓他們進入餐廳。反向代理也提供類似的功能,如防止惡意攻擊、限制某些請求等。
所以,總結一下,NGINX 反向代理伺服器就像是餐廳的接待員,他站在你的伺服器和用戶之間,幫忙接收和處理用戶的請求,並且提供了許多其他的功能和優點。
這樣就完成惹。
## YOLO detection
### Installation
```bash=
## All the installation done in this video are given below:
## 1. Download yolov5 repository
$ git clone https://github.com/ultralytics/yolov5
## 2.Installing cv2
$ pip3 install opencv-python
## 3. To fix, import error: libcblas.so.3: cannot open shared object file: No such file or directory
$ sudo apt-get install libatlas-base-dev
## 4. To fix, no module name: tqdm
$ pip3 install tqdm
## 5. To fix, no module name: yaml
$ pip3 install pyyaml
## 6. To fix, no module name: matplotlib
$ pip3 install matplotlib
## 7. To fix no module name: pandas
$ pip3 install pandas
## 8. To fix no module name: seaborn
$ pip3 install seaborn
## 9. DistributionNotFound: The 'pycocotools ]=2.0' distribution was not found and is required by the application
$ pip3 install cython
$ pip3 install git+https://github.com/waleedka/coco.git#...
## 10. DistributionNotFound: The 'thop' distribution was not found and is required by the application
$ pip3 install thop
## Execute
$ python3 detect.py --source data/images --weight yolov5s.pt --conf 0.25
$ python3 detect.py --source 0 --weight yolov5s.pt --conf 0.25
```
### Result



## Custom object
https://core-electronics.com.au/guides/object-identify-raspberry-pi/
```bash=
$ sudo apt-get install build-essential cmake pkg-config
$ sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev
$ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
$ sudo apt-get install libxvidcore-dev libx264-dev
$ sudo apt-get install libgtk2.0-dev libgtk-3-dev
$ sudo apt-get install libatlas-base-dev gfortran
$ sudo pip3 install numpy
$ wget -O opencv.zip https://github.com/opencv/opencv/archive/4.4.0.zip
$ wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.4.0.zip
$ unzip opencv.zip
$ unzip opencv_contrib.zip
$ cd ~/opencv-4.4.0/
$ mkdir build
$ cd build
$ cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-4.4.0/modules \
-D BUILD_EXAMPLES=ON ..
$ make -j $(nproc)
$ sudo make install && sudo ldconfig
## Download Attachment - Object_Detection_Files.zip
$ unzip Object_Detection_Files.zip
$ python3 object-ident-2.py
```
### object-ident-2.py code
```bash=
import cv2
#thres = 0.45 # Threshold to detect object
classNames = []
classFile = "/home/eric/test/Object_Detection_Files/coco.names"
with open(classFile,"rt") as f:
classNames = f.read().rstrip("\n").split("\n")
configPath = "/home/eric/test/Object_Detection_Files/ssd_mobilenet_v3_large_coco_2020_01_14.pbtxt"
weightsPath = "/home/eric/test/Object_Detection_Files/frozen_inference_graph.pb"
net = cv2.dnn_DetectionModel(weightsPath,configPath)
net.setInputSize(320,320)
net.setInputScale(1.0/ 127.5)
net.setInputMean((127.5, 127.5, 127.5))
net.setInputSwapRB(True)
def getObjects(img, thres, nms, draw=True, objects=[]):
classIds, confs, bbox = net.detect(img,confThreshold=thres,nmsThreshold=nms)
#print(classIds,bbox)
if len(objects) == 0: objects = classNames
objectInfo =[]
if len(classIds) != 0:
for classId, confidence,box in zip(classIds.flatten(),confs.flatten(),bbox):
className = classNames[classId - 1]
if className in objects:
objectInfo.append([box,className])
if (draw):
cv2.rectangle(img,box,color=(0,255,0),thickness=2)
cv2.putText(img,classNames[classId-1].upper(),(box[0]+10,box[1]+30),
cv2.FONT_HERSHEY_COMPLEX,1,(0,255,0),2)
cv2.putText(img,str(round(confidence*100,2)),(box[0]+200,box[1]+30),
cv2.FONT_HERSHEY_COMPLEX,1,(0,255,0),2)
return img,objectInfo
if _name_ == "__main__":
cap = cv2.VideoCapture(0)
cap.set(3,640)
cap.set(4,480)
#cap.set(10,70)
while True:
success, img = cap.read()
result, objectInfo = getObjects(img,0.45,0.2, objects=['cup'])
#print(objectInfo)
cv2.imshow("Output",img)
cv2.waitKey(1)
```
https://blog.csdn.net/weixin_43694096/article/details/127815800