本文总结了使用yolo过程中出现的一些问题,在网络上找到了相关的解决方案。
一般来说,模型训练好了,也可以使用shell命令进行预测了,下一步该在业务里面使用别的语言来调用了,我们这里使用python来调用yolo模型。
为了提高识别效率,当然不能直接在python里面来调用shell,这样的话每次调用都会重新加载一次模型,你想想有多慢?
darknet官方项目提供了python调用yolo模型的示例,也就是使用python与C交互,加载模型后就可以进行预测了,最后返回预测的坐标(其实返回的是中心点坐标和box的高宽)。
我们直接看到最后的代码部分:
if __name__ == "__main__":
#net = load_net("cfg/densenet201.cfg", "/home/pjreddie/trained/densenet201.weights", 0)
#im = load_image("data/wolf.jpg", 0, 0)
#meta = load_meta("cfg/imagenet1k.data")
#r = classify(net, meta, im)
#print r[:10]
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
我们只需要在load_net,load_meta里面填上相关参数,最后调用detect方法就可以进行识别了。
当然,我们可以在一个web项目中,提前把load_net,load_meta加载好,最后每次调用api的时候,执行detect方法就可以了。
上面也提到了,python调用模型后返回的结果是并不是预测的box四个点的坐标,而是中心点坐标和box的高宽。
从detect函数里面的这一段代码可以看出来(b.x, b.y, b.w, b.h)
:
res = []
for j in range(num):
for i in range(meta.classes):
if dets[j].prob[i] > 0:
b = dets[j].bbox
res.append((meta.names[i], dets[j].prob[i], (b.x, b.y, b.w, b.h)))
得到中心点坐标和box高宽后,经过简单的计算,就可以得到四个角点的坐标了
# 结果r是四个元素的数组 (中心点x,中心点y,宽,高)
x, y, w, h = r
a = x - (h/2)
c = x + (h/2)
b = y - (w/2)
d = y + (w/2)
参考链接:https://github.com/pjreddie/darknet/issues/243
你可能发现了,darknet.py用python3执行会报错ctypes.ArgumentError
。
Traceback (most recent call last):
File "python/darknet.py", line 151, in
net = load_net("cfg/tiny-yolo.cfg", "tiny-yolo.weights", 0)
ctypes.ArgumentError: argument 1: : wrong type
解决方案如下:把配置相关的参数使用bytes类型传入,而不是string
net = load_net("cfg/tiny-yolo.cfg".encode('utf-8'), "tiny-yolo.weights".encode('utf-8'), 0)
meta = load_meta("cfg/coco.data".encode('utf-8'))
r = detect(net, meta, "data/dog.jpg".encode('utf-8'))
现在就可以使用python3执行了~
参考链接:https://github.com/pjreddie/darknet/issues/241
实现加载模型、坐标预测工作后,接下来是标记图片、切割图片、预测分类和接口开发等工作。后续有空会把demo贴上来。