DarkNet(2)--修改Python调用接口,支持输入numpy图片

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lwplwf/article/details/84566954

DarkNet源码中提供的接口,用Python处理一张图片的时候,只能传入图片路径,见python/darknet.py的demo。

if __name__ == "__main__":
    net = load_net("cfg/tiny-yolo.cfg", "tiny-yolo.weights", 0)
    meta = load_meta("cfg/coco.data")
    r = detect(net, meta, "data/dog.jpg") // 传入图片路径
    print r

然后:

def detect(net, meta, image, thresh=.5, hier_thresh=.5, nms=.45):
    im = load_image(image, 0, 0) // 调load_image函数
    ...

即就是调load_image函数加载图片得到IMAGE对象(这个IMAGE是Darknet中自定义的结构体类型):

load_image = lib.load_image_color
load_image.argtypes = [c_char_p, c_int, c_int]
load_image.restype = IMAGE
class IMAGE(Structure):
    _fields_ = [("w", c_int),
                ("h", c_int),
                ("c", c_int),
                ("data", POINTER(c_float))]

下面来修改DarkNet源码,来支持加载numpy图片。

1.修改image.c文件

找个位置添加加下面代码(我放到了1042行):

#ifdef NUMPY
image ndarray_to_image(unsigned char* src, long* shape, long* strides)
{
    int h = shape[0]; 
    int w = shape[1]; 
    int c = shape[2]; 
    int step_h = strides[0]; 
    int step_w = strides[1]; 
    int step_c = strides[2]; 
    image im = make_image(w, h, c); 
    int i, j, k; 
    int index1, index2 = 0;

    for(i = 0; i < h; ++i){
        for(k= 0; k < c; ++k){
            for(j = 0; j < w; ++j){
                index1 = k*w*h + i*w + j;
                index2 = step_h*i + step_w*j + step_c*k;
                // fprintf(stderr, "w=%d h=%d c=%d step_w=%d step_h=%d step_c=%d \n", w, h, c, step_w, step_h, step_c); 
                // fprintf(stderr, "im.data[%d]=%u data[%d]=%f \n", index1, src[index2], index2, src[index2]/255.); 
                im.data[index1] = src[index2]/255.;
            }
        }
    }
    rgbgr_image(im);

    return im;        
}
#endif

2.修改image.h文件

添加下面代码(我放在了47行):

#ifdef NUMPY
image ndarray_to_image(unsigned char* src, long* shape, long* strides);
#endif

3.修改Makefile文件

(1)最前面添加NUMPY=1

GPU=0
CUDNN=0
OPENCV=0
OPENMP=0
NUMPY=1
DEBUG=0

(2)在大概50行找个地方添加:

ifeq ($(NUMPY), 1) 
COMMON+= -DNUMPY -I/usr/include/python2.7/ -I/usr/lib/python2.7/dist-packages/numpy/core/include/numpy/ 
CFLAGS+= -DNUMPY 
endif

4.重新编译DarkNet

make clean
make all -j16

5.修改demo

(1)添加函数:

def nparray_to_image(img): 
    data = img.ctypes.data_as(POINTER(c_ubyte)) 
    image = ndarray_image(data, img.ctypes.shape, img.ctypes.strides) 
    return image

(2)添加:

ndarray_image = lib.ndarray_to_image 
ndarray_image.argtypes = [POINTER(c_ubyte), POINTER(c_long), POINTER(c_long)] 
ndarray_image.restype = IMAGE

完整demo示例:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os
sys.path.append(os.path.join(os.getcwd(),'python/'))
# import pdb

from ctypes import *
import math
import random
import numpy as np
from PIL import Image


class IMAGE(Structure):
    _fields_ = [("w", c_int),
                ("h", c_int),
                ("c", c_int),
                ("data", POINTER(c_float))]

def nparray_to_image(img): 
    data = img.ctypes.data_as(POINTER(c_ubyte)) 
    image = ndarray_image(data, img.ctypes.shape, img.ctypes.strides) 
    return image

lib = CDLL("libdarknet.so", RTLD_GLOBAL)
lib.network_width.argtypes = [c_void_p]
lib.network_width.restype = c_int
lib.network_height.argtypes = [c_void_p]
lib.network_height.restype = c_int

load_net = lib.load_network
load_net.argtypes = [c_char_p, c_char_p, c_int]
load_net.restype = c_void_p

load_image = lib.load_image_color
load_image.argtypes = [c_char_p, c_int, c_int]
load_image.restype = IMAGE

ndarray_image = lib.ndarray_to_image 
ndarray_image.argtypes = [POINTER(c_ubyte), POINTER(c_long), POINTER(c_long)] 
ndarray_image.restype = IMAGE

predict_image = lib.network_predict_image
predict_image.argtypes = [c_void_p, IMAGE]
predict_image.restype = POINTER(c_float)

free_image = lib.free_image
free_image.argtypes = [IMAGE]


def MGN(net, image_path):

    # PIL Image
    image = Image.open(image_path) # RGB
    image = image.resize((128, 384))
    image = np.array(image)
    image = image / 255.0

    # image = load_image(image_path, 0, 0) # 由路径加载得到IMAGE
    im = nparray_to_image(image) #  由numpy转换得到IMAGE

    out = predict_image(net, im)

    res = []
    for i in range(2048):
        res.append(out[i])
        print(i, out[i])
    
    free_image(im)
    return res

if __name__ == '__main__':
    net = load_net("cfg/MGN.cfg", "backup/MGN.weights", 0)
    test_img = "data/test.jpg"
    
    res = MGN(net, test_img)
    print(len(res))
    print("Done!")
    

6.Reference

https://blog.csdn.net/phinoo/article/details/83009061
https://github.com/pjreddie/darknet/issues/289

猜你喜欢

转载自blog.csdn.net/lwplwf/article/details/84566954