【Windows+Cygwin+Darknet+OpenCV】简易上手实现YOLOv3目标检测

YOLO(You only look once)是github上很火的一个目标检测算法。它的官网提供了很方便的用C语言编写的程序Darknet。 但是官网提供的很方便的编译方法是基于Linux和Mac系统的。我这次来讲讲我是如何在自己windows系统下配置Darknet模块的。 注:我这次是下了Cygwin来模拟Linux系统,因为不想下体积占据几个G的Visual Studio来进行编译,Cygwin安装包本身只有1.3M大小。 如果有Visual Studio,可以参照AlexeyAB版本进行配置。

官网图

基础配置流程

配置过程参照官网:https://pjreddie.com/darknet/yolo/

(1) 将github上的https://github.com/pjreddie/darknet 整个项目下载到本地电脑。 注:此处建议使用下载.zip压缩包的方式,不是直接用git clone到本地文件夹,不然可能后面会遇到couldn’t open file: data/coco.names的问题。 (2) 切换到darknet文件夹,使用make命令编译C语言源文件。 此时,Windows系统下在cmd命令行会报错无法使用make命令。因为make是linux系统下编译源文件使用的命令。官网也有注明这些命令只在Linux和Mac系统上测试过,未在windows系统下测试。 所以,下载Cygwin软件实现在windows平台模拟linux系统操作命令,而后可以使用make命令编译源码,生成darknet.exe可执行文件。安装配置Cygwin 参照这篇博客以及其下面的问答:https://blog.csdn.net/chunleixiahe/article/details/55666792

在Cygwin编译成功

(3) 下载别人已训练好的yolov3.weights模型权重文件,放于darknet根目录下。 官网链接(下载较慢):https://pjreddie.com/darknet/yolo/ 百度云链接:https://pan.baidu.com/s/1CVgvP4hQQvDNbKmXhmkxqw 提取码:jnhn (4) 使用命令./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg完成测试。因为没有配置OpenCV,图片结果不会直接显示的屏幕上,而是存于默认文件夹的根目录predictions.jpg。 但是此时默认的程序不会将置信度显示在图片上,只打印于命令行,图片会存于根目录下predictions.jpg

官方测试图片结果不含置信度

(5) 为实现将预测的置信度显示于检测结果图片上,更改默认darknet文件夹下的src/image.c文件draw_detections函数。 参照:https://blog.csdn.net/qq_34795071/article/details/86665620

int i,j;

for(i = 0; i < num; ++i){
    char labelstr[4096] = {0};
    int class = -1;
char possible[10];//存放检测的置信值
    for(j = 0; j < classes; ++j){
  sprintf(possible,"%.2f",dets[i].prob[j]);//置信值截取小数点后两位赋给possible
        if (dets[i].prob[j] > thresh){
            if (class < 0) {
                strcat(labelstr, names[j]);
        strcat(labelstr, possible);//标签中加入置信值
                class = j;
            } else {
                strcat(labelstr, ", ");
                strcat(labelstr, names[j]);
        strcat(labelstr, possible);//标签中加入置信值
            }
            printf("%s: %.0f%%\n", names[j], dets[i].prob[j]*100);
        }
    }

(6) 删除掉原编译好的darknet.exe, libdarknet.a, libdarknet.so,重新使用make编译源文件,再执行上述检测语句,即可存储含有置信度的图片。

dog_predictions

(7) 若想更改检测的默认置信度,在检测命令后添加 -thresh <数值>。 ./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg -thresh 0.4

至此已经完成了最基础的Darknet配置来实现YOLOv3算法。

OpenCV拓展实现实时目标检测

(1) 安装OpenCV,拓展可支持的图片类型,并且将结果自动弹窗显示: OpenCV(Windows版本的即可)安装完毕后,需要再次使用Cygwin下载Linux支持的OpenCV相应文件,并将darknet根目录下Makefile用文本打开,开头部分设为OPENCV=1,才可成功编译可支持OpenCVdarknet.exe。 编译完基于OpenCV的可执行程序后,不能如原来一样在命令行直接输入检测语句,不然会出现无法展示的报错,配置并启动Xterm才可以解决。

opencv配置后在命令行弹框报错

Cygwin输入export DISPLAY=:0.0startxwin &即可启动Xterm,然后输入相应命令,即可出现弹框,如下所示。

在Xterm成功显示至窗口屏幕.PNG

Xterm使用两则小贴士:(1)鼠标中键实现“粘贴”;(2)ctrl+右键可以改字号。 (2) 参照这篇博客【python+OpenCV+YOLOv3打开笔记本摄像头模型检测】的代码,使用python程序,通过OpenCV调用摄像头实现实时检测。 这篇文章调用的是电脑自带摄像头,我通过给安卓手机下载IP Webcam软件,实现调用手机摄像头的实时目标检测。 具体代码如下:

import numpy as np
import cv2
import os

def video_demo():
    # 加载已经训练好的模型路径,可以是绝对路径或者相对路径
    weightsPath = "../yolov3.weights"
    configPath = "../cfg/yolov3.cfg"
    labelsPath = "../data/coco.names"
    # 初始化一些参数
    LABELS = open(labelsPath).read().strip().split("\n")  # 物体类别
    COLORS = np.random.randint(0, 255, size=(len(LABELS), 3), dtype="uint8")  # 颜色
    boxes = []
    confidences = []
    classIDs = []
    net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)
    # 读入待检测的图像
    # 0是代表摄像头编号,只有一个的话默认为0

    url = 'http://192.168.0.103:8080/video'##手机ip cam地址
    # url='D:\darknet-master\\airplane.avi'#本地视频
    capture = cv2.VideoCapture(url)
    while (True):
        ref, image = capture.read()
        (H, W) = image.shape[:2]
        # 得到 YOLO需要的输出层
        ln = net.getLayerNames()
        ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
        # 从输入图像构造一个blob,然后通过加载的模型,给我们提供边界框和相关概率
        blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416), swapRB=True, crop=False)
        net.setInput(blob)
        layerOutputs = net.forward(ln)
        # 在每层输出上循环
        for output in layerOutputs:
            # 对每个检测进行循环
            for detection in output:
                scores = detection[5:]
                classID = np.argmax(scores)
                confidence = scores[classID]
                # 过滤掉那些置信度较小的检测结果
                if confidence > 0.5:
                    # 框后接框的宽度和高度
                    box = detection[0:4] * np.array([W, H, W, H])
                    (centerX, centerY, width, height) = box.astype("int")
                    # 边框的左上角
                    x = int(centerX - (width / 2))
                    y = int(centerY - (height / 2))
                    # 更新检测出来的框
                    boxes.append([x, y, int(width), int(height)])
                    confidences.append(float(confidence))
                    classIDs.append(classID)
        # 极大值抑制
        idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.2, 0.3)
        if len(idxs) > 0:
            for i in idxs.flatten():
                (x, y) = (boxes[i][0], boxes[i][1])
                (w, h) = (boxes[i][2], boxes[i][3])
                # 在原图上绘制边框和类别
                color = [int(c) for c in COLORS[classIDs[i]]]
                cv2.rectangle(image, (x, y), (x + w, y + h), color, 2)
                text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i])
                cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
        cv2.imshow("Video", image)
        # 等待1ms显示图像
        c = cv2.waitKey(1)
        if c & 0xFF == ord('q'):  # 键盘输入英文字母q键退出视频
            break

cv2.destroyAllWindows()  # 销毁所有窗口
video_demo()

下面放一下我实时检测的画面:

接入手机摄像头实时检测.jpg

电脑实时检测示意画面.jpg

配置Darknet走过的一些弯路

(1) 下载CUDA实现GPU运算: 需要自己的显卡比较好,同时配置CUDA、CUDNN均需匹配版本号正确,这两个软件体积也特别大。配置这个很麻烦,Darknet官网也说明了这个安装很麻烦,所以不是长久专门使用,不必配置了。 但是没有GPU真的处理视频很卡。。。 (2) 一开始的make编译Makefile失败,尝试使用windows系统下的Visual Studio中的nmake等方式失败,尝试用MinGW也失败,最终使用Cygwin模拟linux成功。 (3) 基于已有的程序,安装完OpenCV后在模拟Linux系统下的视频流的目标侦测目前还是遇到一些问题,无法正常按帧检测,并实时在屏幕上显示检测结果。花费了2天时间进行尝试,还是没有解决这个bug,暂时放弃。有解决的朋友可以告诉我一下。 报错: (darknet:3866):GLib-GObject-CRITICAL **: g_object_set: assertion 'G_IS_OBJECT (object)' failed

视频报错.png

所以才最后转投了python程序去调用OpenCV做视频检测,如果你只想做图片检测,按照我上面的做法没问题。 (4) 所以当我看到最后的别人的博客调用python程序,去查src的源码实现YOLOv3,不需要配置keras和tensorflow,其实以后自己也可以这样做。自己当初放弃AlexeyAB版本的python接口是因为它还是需要导入windows编译过后的dll模块,所以放弃。不过,有兴趣的朋友还是可以一试。

打赏
  • © 2020-2022 Eva Ren
  • Powered by Hexo Theme Ayer
    • 本站总访问量
    • 本页面总访问量
  • 载入运行时间...

请我喝杯咖啡吧~

支付宝
微信