Darknet (一) YOLO 基于 CentOS CPU 的部署使用

一 . 编译 darknet 库文件

1. 建立目录 darknet_cpu , 用于编译 darknet:
# cd ~/
# mkdir darknet_cpu
# cd darknet_cpu

2. 下载 darknet , 并编译 :
# git clone https://github.com/pjreddie/darknet
# cd darknet
# make
编译生成 libdarknet.a




二 . 建立 YOLO 图片识别工程

1. 建立工程结构根目录
# cd ~/
# mkdir yolo_cpu
# cd yolo_cpu

2. 建立代码文件 yolo_cpu.py ,其内容为 

#coding:utf-8

from ctypes import *
import math
import random
import os
from PIL import Image

def 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)-1

def 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 class
class 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生成的一些文件
# mkdir data
拷贝所需要的 darknet 中一些文件过来 :
# cp ~/darknet_cpu/darknet/data/coco.names ./data/
# cp ~/darknet_cpu/darknet/cfg/coco.data ./data/
# cp ~/darknet_cpu/darknet/cfg/yolo.cfg ./data/
# cp ~/darknet_cpu/darknet/libdarknet.so ./data/

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

5. 建立测试图片目录
# cd ~/yolo_cpu
# mkdir test_image
# cd test_image
# mkdir input
# mkdir output

6. 测试

放置一张待识别的图片(1.jpg)到input目录 ,

修改 main 函数中,变量 input_images 的值为待识别的图片,修改变量 output_path 的值为图片识别的输出目录 。

执行 : 

# python yolo_cpu.py

输出 :

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 data/yolo.weights...Done!

[('person', 0.7448363900184631, (424.3780822753906, 212.38539123535156, 49.31261444091797, 55.47972869873047)), ('person', 0.6640895009040833, (499.8251647949219, 213.63003540039062, 51.0251579284668, 47.67637634277344)), ('bus', 0.5649385452270508, (464.278076171875, 256.50067138671875, 209.6256561279297, 204.27801513671875)), ('car', 0.5558193325996399, (117.63778686523438, 200.83546447753906, 217.797607421875, 187.41815185546875)), ('person', 0.5407586097717285, (145.47283935546875, 170.5668182373047, 53.51567840576172, 36.21089553833008))]

end.



猜你喜欢

转载自blog.csdn.net/jiangmengya1/article/details/78192052