首次使用YOLO目标检测,OpenCV读入图片后触发TypeError问题
解决YOLO Darknet与OpenCV图像格式不兼容导致的TypeError
看起来你踩了Darknet Python绑定的一个常见坑——你传入detect函数的是OpenCV读取的numpy数组,但Darknet的load_image接口根本不支持这种格式。从报错信息里的ctypes.ArgumentError就能看出来:它期望的是图像路径字符串或者Darknet自己的image结构体,而不是numpy.ndarray。
下面给你两种针对性的解决方案,根据你的需求选就行:
方案1:直接传图像路径(最简单快捷)
如果你的预处理操作可以调整到Darknet加载图像之后,或者根本不需要提前预处理,直接把图像路径传给detect函数就好,完全绕开格式问题:
def ocr_function(image_path): # 把参数改成图像路径,和内部变量统一 start = time() try: ocr_threshold = 0.4 ocr_weights = b'data/ocr/ocr-net.weights' ocr_netcfg = b'data/ocr/ocr-net.cfg' ocr_dataset = b'data/ocr/ocr-net.data' ocr_net = dn.load_net(ocr_netcfg, ocr_weights, 0) ocr_meta = dn.load_meta(ocr_dataset) print("performing OCR at: ", os.getcwd()) print("\tScanning %s" % image_path) # 直接传路径给detect,不需要cv2.imread R,(width,height) = detect(ocr_net, ocr_meta, image_path, thresh=ocr_threshold, nms=None) if len(R): L = dknet_label_conversion(R,width,height) L = nms(L,.45) L.sort(key=lambda x: x.tl()[0]) lp_str = ''.join([chr(l.cl()) for l in L]) print ('\t\tLP: %s' % lp_str)
方案2:把OpenCV图像转成Darknet兼容格式(适合需要预处理的场景)
如果你必须用OpenCV做预处理(比如你的preprocess函数依赖numpy数组),那就需要把处理后的numpy图像转换成Darknet能识别的image结构体。我帮你写了个转换函数,直接用就行:
def cv2_to_darknet(image): # OpenCV读的是BGR,Darknet用的是RGB,必须转颜色空间 image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) height, width, channel = image_rgb.shape # 创建Darknet的image结构体,然后把numpy数据拷贝进去 darknet_image = dn.make_image(width, height, channel) dn.copy_image_from_bytes(darknet_image, image_rgb.tobytes()) return darknet_image def ocr_function(image_path): start = time() try: ocr_threshold = 0.4 ocr_weights = b'data/ocr/ocr-net.weights' ocr_netcfg = b'data/ocr/ocr-net.cfg' ocr_dataset = b'data/ocr/ocr-net.data' ocr_net = dn.load_net(ocr_netcfg, ocr_weights, 0) ocr_meta = dn.load_meta(ocr_dataset) print("performing OCR at: ", os.getcwd()) print("\tScanning %s" % image_path) # 用OpenCV读取并预处理 image = cv2.imread(image_path) image = preprocess(image) show(image, "provided image") # 转换为Darknet兼容的图像对象 darknet_img = cv2_to_darknet(image) # 传入转换后的图像进行检测 R,(width,height) = detect(ocr_net, ocr_meta, darknet_img, thresh=ocr_threshold, nms=None) # 重要:用完后释放Darknet图像的内存,避免内存泄漏 dn.free_image(darknet_img) if len(R): L = dknet_label_conversion(R,width,height) L = nms(L,.45) L.sort(key=lambda x: x.tl()[0]) lp_str = ''.join([chr(l.cl()) for l in L]) print ('\t\tLP: %s' % lp_str)
额外提醒
- 你代码里有个小bug:函数参数是
image,但内部却用了未定义的image_path,记得把参数名和内部变量统一起来,不然会报变量未定义的错误。 - 颜色空间转换一定要做,不然Darknet检测出来的结果会完全不对(因为BGR和RGB的通道顺序反了)。
- 用
dn.make_image创建的图像对象一定要用dn.free_image释放,不然程序跑久了会内存溢出。
内容的提问来源于stack exchange,提问作者Anant Patankar
相关产品推荐
相关产品推荐

