修改./darknet/Makefile
GPU=1 CUDNN=1 CUDNN_HALF=0 OPENCV=1 AVX=0 OPENMP=0 LIBSO=1 # 设为1,编译生成so ZED_CAMERA=0 # ZED SDK 3.0 and above ZED_CAMERA_v2_8=0 # ZED SDK 2.Xmake编译,或者make -j8
darkne目录下,已有示例 ./darknet/darknet.py ./darknet/darknet_video.py 看着复杂,简化封装一下,如下:
#!/usr/bin/python # -*- coding:utf-8 -*- from ctypes import * import math,os,sys,cv2 homePath = os.path.expanduser('~') darknetPath = os.path.join(homePath, 'darknet') class BOX(Structure): _fields_ = [("x", c_float), ("y", c_float), ("w", c_float), ("h", c_float)] class DETECTION(Structure): _fields_ = [("bbox", BOX), ("classes", c_int), ("prob", POINTER(c_float)), ("mask", POINTER(c_float)), ("objectness", c_float), ("sort_class", c_int), **("uc", POINTER(c_float)), # YOLOv3和YOLOv4不同处,YOLOv4需要,v3不需要** **("points", c_int)] # YOLOv3和YOLOv4不同处,YOLOv4需要,v3不需要** ] 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))] class darknetDetect: def __init__(self, weight_path, cfg_path, data_path): self.libdarknetPath = os.path.join(darknetPath, 'libdarknet.so') self.lib = CDLL(self.libdarknetPath) self.get_network_boxes = self.lib.get_network_boxes self.get_network_boxes.argtypes = [c_void_p, c_int, c_int, c_float, c_float, POINTER(c_int), c_int, POINTER(c_int)] self.get_network_boxes.restype = POINTER(DETECTION) self.free_detections = self.lib.free_detections self.free_detections.argtypes = [POINTER(DETECTION), c_int] self.load_net = self.lib.load_network self.load_net.argtypes = [c_char_p, c_char_p, c_int] self.load_net.restype = c_void_p self.do_nms_obj = self.lib.do_nms_obj self.do_nms_obj.argtypes = [POINTER(DETECTION), c_int, c_int, c_float] self.free_image = self.lib.free_image self.free_image.argtypes = [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_data = self.lib.load_image_cv_data self.load_image_data.argtypes = [c_char_p, c_int, c_int] self.load_image_data.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) if sys.version_info.major != 2: cfg_path = cfg_path.encode() weight_path = weight_path.encode() data_path = data_path.encode() self.net = self.load_net(cfg_path, weight_path, 0) self.meta = self.load_meta(data_path) def detect(self, img, thresh=.5, hier_thresh=.5, nms=.45): data_ctypes_ptr = cast(img.ctypes.data, POINTER(c_char)) im = self.load_image_data(data_ctypes_ptr, img.shape[1], img.shape[0]) num = c_int(0) pnum = pointer(num) self.predict_image(self.net, im) dets = self.get_network_boxes(self.net, im.w, im.h, thresh, hier_thresh, None, 0, pnum) num = pnum[0] if (nms): self.do_nms_obj(dets, num, self.meta.classes, nms); res = [] for j in range(num): for i in range(self.meta.classes): if dets[j].prob[i] > 0: box = dets[j].bbox l = box.x / img.shape[1] t = box.y / img.shape[0] r = box.w / img.shape[1] b = box.h / img.shape[0] res.append((l, t, r, b, dets[j].prob[i], i, self.meta.names[i])) self.free_image(im) self.free_detections(dets, num) return res if __name__ == "__main__": pass官方demo和命令行,都是输入图像路径,如果想使用Mat类型,需要修改一下源码再编译,修改如下 ./darknet/image_opencv.cpp
extern "C" image load_image_cv_data(unsigned char *data, int w, int h) { cv::Mat src(cv::Size(w, h), CV_8UC3, data); if (!src.data) { return make_image(10, 10, 3); } return mat_to_image(src); }YOLOv4和YOLOv3有些不一样,后续还要加RGB2BGR
extern "C" image load_image_cv_data(unsigned char *data, int w, int h) { cv::Mat src(cv::Size(w, h), CV_8UC3, data); if (!src.data) { return make_image(10, 10, 3); } cv::Mat dst; cv::cvtColor(src, dst, cv::COLOR_RGB2BGR); # 就是这样rgb2bgr return mat_to_image(src); }编译后,就可以使用以上代码使用了。