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
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.