Darknet (二) YOLO 基于 CentOS GPU 的部署使用

来源:互联网 发布:用友致远软件 编辑:程序博客网 时间:2024/06/11 06:40

一 . 编译 darknet 库文件

建立根目录 gpu_based 作为这里的整体根目录:

# cd ~/

# mkdir gpu_based



二 . 编译 darknet 库文件

1. 下载 darknet , 用于编译 GPU 版本的 darknet :
# cd ~/gpu_based
# git clone https://github.com/pjreddie/darknet
# cd darknet

2. 修改配置 Makefile, 并进行编译

修改下面这行
GPU=0 

为下面这行

GPU=1 

表示使用 GPU,然后执行编译命令
# make


这个时候如果出现错误 “ nvcc: command not found ”, 表示找不到 nvcc 这个命令。而我们发现 /usr/local/cuda/bin 目录下有 nvcc 这个可执行文件。
我们继续修改 Makefile 

修改下面这行

NVCC=nvcc 

为下面这行

NVCC=/usr/local/cuda/bin/nvcc
再执行编译命令
# make 


这个时候如果出现错误 “ ... cannot find -lcuda ”, 表示没有找到 lcuda. 这个库, 我们查找使用这个库的地方 " -L/usr/local/cuda/lib64 -lcuda -lcudart -lcublas -lcurand -lstdc++ ", 表示在 /usr/local/cuda/lib64 这个目录下面没有找到 lcuda 这个库文件,然后我们继续修改 Makefile 
修改下面这行
LDFLAGS+= -L/usr/local/cuda/lib64 -lcuda -lcudart -lcublas -lcurand
为下面两行
LDFLAGS+= -L/usr/local/cuda/lib64/stubs -lcuda
LDFLAGS+= -L/usr/local/cuda/lib64 -lcudart -lcublas -lcurand
再执行编译命令
# make


这个时候, 应该会编译生成 libdarknet.a , 大小为 1.5M , CPU 模式的 libdarknet.a 大小为 485K 。显然 GPU 模式包含更多的信息 。



三 . 建立 YOLO 图片识别工程

1. 建立工程目录和文件
# cd ~/gpu_based
# mkdir project
# cd project 

# touch yolo_gpu.py


2. 添加如下代码到代码文件 yolo_gpu.py

#coding:utf-8from ctypes import *import mathimport randomimport osfrom PIL import Imagedef sample(probs):    s = sum(probs)    probs = [a/s for a in probs]    r = random.uniform(0, 1)    for i in range(len(probs)):        r = r - probs[i]        if r <= 0:            return i    return len(probs)-1def c_array(ctype, values):    return (ctype * len(values))(*values)class BOX(Structure):    _fields_ = [("x", c_float),                ("y", c_float),                ("w", c_float),                ("h", c_float)]class IMAGE(Structure):    _fields_ = [("w", c_int),                ("h", c_int),                ("c", c_int),                ("data", POINTER(c_float))]class METADATA(Structure):    _fields_ = [("classes", c_int),                ("names", POINTER(c_char_p))]# YOLO classclass YOLO(object):    def __init__(self):        self.lib = CDLL("data/libdarknet.so", RTLD_GLOBAL)        self.lib.network_width.argtypes = [c_void_p]        self.lib.network_width.restype = c_int        self.lib.network_height.argtypes = [c_void_p]        self.lib.network_height.restype = c_int        self.predict = self.lib.network_predict_p        self.predict.argtypes = [c_void_p, POINTER(c_float)]        self.predict.restype = POINTER(c_float)        self.make_boxes = self.lib.make_boxes        self.make_boxes.argtypes = [c_void_p]        self.make_boxes.restype = POINTER(BOX)        self.free_ptrs = self.lib.free_ptrs        self.free_ptrs.argtypes = [POINTER(c_void_p), c_int]        self.num_boxes = self.lib.num_boxes        self.num_boxes.argtypes = [c_void_p]        self.num_boxes.restype = c_int        self.make_probs = self.lib.make_probs        self.make_probs.argtypes = [c_void_p]        self.make_probs.restype = POINTER(POINTER(c_float))        self.detect = self.lib.network_predict_p        self.detect.argtypes = [c_void_p, IMAGE, c_float, c_float, c_float, POINTER(BOX), POINTER(POINTER(c_float))]        self.reset_rnn = self.lib.reset_rnn        self.reset_rnn.argtypes = [c_void_p]        self.load_net = self.lib.load_network_p        self.load_net.argtypes = [c_char_p, c_char_p, c_int]        self.load_net.restype = c_void_p        self.free_image = self.lib.free_image        self.free_image.argtypes = [IMAGE]        self.letterbox_image = self.lib.letterbox_image        self.letterbox_image.argtypes = [IMAGE, c_int, c_int]        self.letterbox_image.restype = IMAGE        self.load_meta = self.lib.get_metadata        self.lib.get_metadata.argtypes = [c_char_p]        self.lib.get_metadata.restype = METADATA        self.load_image = self.lib.load_image_color        self.load_image.argtypes = [c_char_p, c_int, c_int]        self.load_image.restype = IMAGE        self.predict_image = self.lib.network_predict_image        self.predict_image.argtypes = [c_void_p, IMAGE]        self.predict_image.restype = POINTER(c_float)        self.network_detect = self.lib.network_detect        self.network_detect.argtypes = [c_void_p, IMAGE, c_float, c_float, c_float, POINTER(BOX), POINTER(POINTER(c_float))]        self.net = self.load_net("data/yolo.cfg", "data/yolo.weights", 0)        self.meta = self.load_meta("data/coco.data")    def classify(self, im):        out = predict_image(net, im)        res = []        for i in range(self.meta.classes):            res.append((self.meta.names[i], out[i]))        res = sorted(res, key=lambda x: -x[1])        return res    def detect_image(self, image):        im = self.load_image(image, 0, 0)        boxes = self.make_boxes(self.net)        probs = self.make_probs(self.net)        num =   self.num_boxes(self.net)        thresh = .5        hier_thresh = .5        nms = .45        self.network_detect(self.net, im, thresh, hier_thresh, nms, boxes, probs)        res = []        for j in range(num):            for i in range(self.meta.classes):                if probs[j][i] > 0:                    res.append((self.meta.names[i], probs[j][i], (boxes[j].x, boxes[j].y, boxes[j].w, boxes[j].h)))        res = sorted(res, key=lambda x: -x[1])        self.free_image(im)        self.free_ptrs(cast(probs, POINTER(c_void_p)), num)        return res    def split_image(self, input_image, output_path, infos):        # 处理切分信息        image_count = len(infos)        split_info = []        for i in range(0, image_count):            info = infos[i]            if len(info) < 3:                continue            image_name = str(i) + "_" + info[0] + "_" + str(int(info[1] * 100))            image_metric = (int(info[2][0] - info[2][2] / 2.0),                            int(info[2][1] - info[2][3] / 2.0),                            int(info[2][0] + info[2][2] / 2.0),                            int(info[2][1] + info[2][3] / 2.0))            split_info.append((image_name, image_metric))        # 切分图片        img = Image.open(input_image)        for info in split_info:            crop_img = img.crop(info[1])            crop_img.save(os.path.join(output_path, info[0]+".jpeg"))    # end class YOLO         if __name__ == "__main__":    print('start')    yolo = YOLO()    input_image = "*****************/cpu_based/project/test_image/input/2.jpeg"    infos = yolo.detect_image(input_image)    print infos    output_path = "*****************/cpu_based/project/test_image/output/2"    yolo.split_image(input_image, output_path, infos)    print('end')

3. 建立工程数据目录,并copy步骤一中的一些文件以及make生成的一些文件

# cd ~/gpu_based/project
# mkdir data
拷贝代码所需要的 darknet 中模型文件过来 :
cp ../darknet/data/coco.names ./data/
cp ../darknet/cfg/coco.data ./data/
cp ../darknet/cfg/yolo.cfg ./data/
cp ../darknet/libdarknet.so ./data/

4. 下载 YOLO 预训练的模型, 放置到 data 目录中 :
# wget https://pjreddie.com/media/files/yolo.weights
# mv yolo.weights ./data/

5. 建立测试图片目录
# cd ~/gpu_based/project
# mkdir test_image
# cd test_image
# mkdir in
# mkdir out

6. 测试
放置一张待识别的图片(1.jpg)到input目录 ,
修改 main 函数中,变量 input_images 和 变量 output_path 的值 ,
执行 python yolo_gpu.py
如果能正常输出,则完毕。

如果出现错误 " OSError: /lib64/libc.so.6: version `GLIBC_2.18' not found ", 说明需要 2.18 的 glibc 库 , 而系统不能够提供,继续后续步骤。


7. CentOS 上查看 glibc 的版本
[******90 ~]$ /lib64/libc.so.6
GNU C Library (GNU libc) stable release version 2.17, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.8.5 20150623 (Red Hat 4.8.5-11).
Compiled on a Linux 3.10.0 system on 2017-06-20.
Available extensions:
The C stubs add-on version 2.1.2.
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
RT using linux kernel aio
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.

由上可知,glic 的版本为 2.17 



8. 这个时候我们编译一个自己版本的 python , 暂时安装在目录 ~/yolo_gpu/jiang

8.1 # cd ~/yolo_gpu/jiang
将 python 源码 Python-2.7.13.tgz 放在此目录下,进行解压缩
# tar -xvf Python-2.7.13.tgz
# ls 
Python-2.7.13 Python-2.7.13.tgz

8.2 指定编译使用的 gcc PATH
Centos 上安装一个 linuxbrew ,
然后 linuxbrew 安装 gcc , 这个 gcc 新版本应该就满足需求了
然后指定用新的 gcc 来编译安装 python .
export PATH=~/.linuxbrew/Cellar/gcc/5.3.0/bin:$PATH

8.3 Makefile 相关

建立 python 安装目录
# mkdir python
进行 configure 配置
# cd Python-2.7.13
# ./configure --prefix=/home/JiangMengYa/work/object_detection_1_by_yolo_gpu/jiang/python --enable-unicode=ucs4
然后 
# make -j && make install 
如果需要安装第三方python库,则指定 target 
pip install --target=/home/JiangMengYa/work/object_detection_1_by_yolo_gpu/jiang/python/lib/python2.7/site-packages pillow

8.3 再测试 
# cd ~/yolo_gpu/
# LD_LIBRARY_PATH=/usr/lib64/nvidia/:/usr/local/cuda-8.0/lib64/ ./jiang/python/bin/python yolo_gpu.py
( 具体版本路径按照自己的进行修改即可 )
Should be OK !


输出 : 
start.
layer     filters    size              input                output
    0 conv     32  3 x 3 / 1   608 x 608 x   3   ->   608 x 608 x  32
    1 max          2 x 2 / 2   608 x 608 x  32   ->   304 x 304 x  32
    2 conv     64  3 x 3 / 1   304 x 304 x  32   ->   304 x 304 x  64
    3 max          2 x 2 / 2   304 x 304 x  64   ->   152 x 152 x  64
    4 conv    128  3 x 3 / 1   152 x 152 x  64   ->   152 x 152 x 128
    5 conv     64  1 x 1 / 1   152 x 152 x 128   ->   152 x 152 x  64
    6 conv    128  3 x 3 / 1   152 x 152 x  64   ->   152 x 152 x 128
    7 max          2 x 2 / 2   152 x 152 x 128   ->    76 x  76 x 128
    8 conv    256  3 x 3 / 1    76 x  76 x 128   ->    76 x  76 x 256
    9 conv    128  1 x 1 / 1    76 x  76 x 256   ->    76 x  76 x 128
   10 conv    256  3 x 3 / 1    76 x  76 x 128   ->    76 x  76 x 256
   11 max          2 x 2 / 2    76 x  76 x 256   ->    38 x  38 x 256
   12 conv    512  3 x 3 / 1    38 x  38 x 256   ->    38 x  38 x 512
   13 conv    256  1 x 1 / 1    38 x  38 x 512   ->    38 x  38 x 256
   14 conv    512  3 x 3 / 1    38 x  38 x 256   ->    38 x  38 x 512
   15 conv    256  1 x 1 / 1    38 x  38 x 512   ->    38 x  38 x 256
   16 conv    512  3 x 3 / 1    38 x  38 x 256   ->    38 x  38 x 512
   17 max          2 x 2 / 2    38 x  38 x 512   ->    19 x  19 x 512
   18 conv   1024  3 x 3 / 1    19 x  19 x 512   ->    19 x  19 x1024
   19 conv    512  1 x 1 / 1    19 x  19 x1024   ->    19 x  19 x 512
   20 conv   1024  3 x 3 / 1    19 x  19 x 512   ->    19 x  19 x1024
   21 conv    512  1 x 1 / 1    19 x  19 x1024   ->    19 x  19 x 512
   22 conv   1024  3 x 3 / 1    19 x  19 x 512   ->    19 x  19 x1024
   23 conv   1024  3 x 3 / 1    19 x  19 x1024   ->    19 x  19 x1024
   24 conv   1024  3 x 3 / 1    19 x  19 x1024   ->    19 x  19 x1024
   25 route  16
   26 conv     64  1 x 1 / 1    38 x  38 x 512   ->    38 x  38 x  64
   27 reorg              / 2    38 x  38 x  64   ->    19 x  19 x 256
   28 route  27 24
   29 conv   1024  3 x 3 / 1    19 x  19 x1280   ->    19 x  19 x1024
   30 conv    425  1 x 1 / 1    19 x  19 x1024   ->    19 x  19 x 425
   31 detection
mask_scale: Using default '1.000000'
Loading weights from cfg/yolo.weights...Done!
[('person', 0.7448253035545349, (424.37799072265625, 212.38552856445312, 49.312339782714844, 55.479007720947266)), ('person', 0.6640925407409668, (499.82525634765625, 213.6302032470703, 51.024715423583984, 47.674110412597656)), ('bus', 0.5649107694625854, (464.27740478515625, 256.5011901855469, 209.6267547607422, 204.2769775390625)), ('car', 0.5556832551956177, (117.6370849609375, 200.8371124267578, 217.79855346679688, 187.41673278808594)), ('person', 0.5407413840293884, (145.47210693359375, 170.56631469726562, 53.51741409301758, 36.210628509521484))]
end.



原创粉丝点击