Docker學習紀錄-在Docker中使用darknet並與python串接
實作流程
git clone Darknet github
1
$ git clone https://github.com/AlexeyAB/darknet.git
進入 darknet 修改 Makefile
- 將
GPU, CUDNN, CUDNN_HALF, OPENCV
依照自己的需求做修改,由於要與python串接必須要將LIBSO
設為1,產生libdarknet.so
- 由於dakrnet的Makefile中,在編譯時會使用到CUDA code, 所以要將
ARCH
這個flag與你最常使用的GPU做匹配,這樣會加快runtime,詳細說明可參考NVIDIA GPU的架构代号,在Matching CUDA arch and CUDA gencode for various NVIDIA architectures中可以找到自己的GPU所使用的架構,Makefile裡都有附只需要將自己的GPU架構反註解就行了
- 將
取得yolov4的weights檔
1
$ wget https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights
編寫Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30#這次環境以ubuntu20.04、cuda11.2.0、cudnn8的image為例
FROM nvidia/cuda:11.2.0-cudnn8-devel-ubuntu20.04
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
#安裝darknet的必要依賴
RUN echo "45.43.38.82 developer.download.nvidia.cn" >> /etc/hosts && \
apt-get update && \
apt-get upgrade -y && \
apt-get install -y build-essential libopencv-dev\
cmake python3-opencv python3-dev nano
#這邊安裝vim,只是為了後續方便直接在container內做修改
RUN apt-get install -y vim
#安裝python
RUN apt update \
&& apt install -y --no-install-recommends python3 python3-pip \
&& ln -sf python3 /usr/bin/python \
&& ln -sf pip3 /usr/bin/pip \
&& pip install --upgrade pip \
&& pip install wheel setuptools
#在container中建立資料夾,並將本地端的darknet複製到container,並且編譯
RUN mkdir -p /workfolder/ \
&& mkdir -p /workfolder/darknet
COPY ./darknet /workfolder/darknet
WORKDIR /workfolder/darknet
RUN make
WORKDIR /workfolder/
CMD ["/bin/bash"]建立image
1
$ sudo docker image build -t yolo:v01 .
設定xhost +local:docker
- 設定x視窗的權限,允許docker使用linux GUI介面,以用來顯示圖片
- 在 local:docker 前加一個加號(+),代表允許接受由 local:docker 所傳來的 X 繪圖指令。
運行image
1
$ sudo docker run --rm --gpus all -it --network=host -e DISPLAY=$DISPLAY yolo:v01
--network
:可以設定在執行 Docker Container 要使用哪一種的網路模式,網路模式有 none、container、host、bridge、overlay… 等等的模式,它們是透過使用 Linux 的 libnetwork 所建立出來的網路模式-e DISPLAY=$DISPLAY
,設定要將畫面呈現到何處,允許docker使用GUI,以用來顯示圖片
先測試darknet的主要執行檔
- 由於image在build時,已經編譯過了,運行image後,可以在darknet的資料夾裡ls,確認裡面是否有
libdarknet.so
以及darknet
的主程式 - 補充:
- darknet: AlexeyAB/darknet 的主要執行檔。
- darknet_image.py, darknet.py, darknet_video.py:透過呼叫 libdarknet.so ,可以在 Python 中直接調用 AlexeyAB/darknet 的一些主要功能,如訓練、測試、載入網路結構等。
- libdarknet.so: AlexeyAB/darknet 使用 c 語言所撰寫的共享函式庫,可供其他程式語言呼叫。
- 測試指令
1
$ ./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights -ext_output data/dog.jpg
- 由於image在build時,已經編譯過了,運行image後,可以在darknet的資料夾裡ls,確認裡面是否有
python串接
- 由於有了
libdarknet.so
檔案,我們可以直接引用darknet.py裡面所提供的函式直接做使用,如此一來就可以自己實作了 - 以下為參考程式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46import cv2
import darknet
cfg_path = './cfg/yolov4.cfg'
data_path = './cfg/coco.data'
weight_path = 'yolov4.weights'
network, class_names, class_colors = darknet.load_network(cfg_path,
data_path,
weight_path)
width = darknet.network_width(network)
height = darknet.network_height(network)
def darknet_helper(img, width, height):
darknet_image = darknet.make_image(width, height, 3)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_resized = cv2.resize(img_rgb, (width, height),
interpolation=cv2.INTER_LINEAR)
# get image ratios to convert bounding boxes to proper size
img_height, img_width, _ = img.shape
width_ratio = img_width / width
height_ratio = img_height / height
# run model on darknet style image to get detections
darknet.copy_image_from_bytes(darknet_image, img_resized.tobytes())
detections = darknet.detect_image(network, class_names, darknet_image)
darknet.free_image(darknet_image)
return detections, width_ratio, height_ratio
# run test on person.jpg image that comes with repository
image = cv2.imread("./data/dog.jpg")
detections, width_ratio, height_ratio = darknet_helper(image, width, height)
for label, confidence, bbox in detections:
left, top, right, bottom = darknet.bbox2points(bbox)
left, top, right, bottom = int(left * width_ratio), int(top * height_ratio), int(right * width_ratio), int(bottom * height_ratio)
cv2.rectangle(image, (left, top), (right, bottom), class_colors[label], 2)
cv2.putText(image, "{} [{:.2f}]".format(label, float(confidence)),
(left, top - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
class_colors[label], 2)
while True:
cv2.imshow('predictions',image)
key = cv2.waitKey(90)
if key == ord('q'): # Esc
print('break')
break
- 由於有了
Reference
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment