利用OpenCV 4.2的GPU

2024-09-30 06:18:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将虚拟机的GPU与OpenCV库(4.2)和Python 3.7一起使用

我已使用CUDA安装opencv,以下命令返回1:

import cv2
count = cv2.cuda.getCudaEnabledDeviceCount()
print(count)

我尝试在使用和不使用GPU的情况下运行代码:

start = time.time()
network = cv.dnn.readNetFromDarknet(config_path, weights_path)
if IS_CUDA:
    network.setPreferableBackend(cv.dnn.DNN_BACKEND_CUDA)
    network.setPreferableTarget(cv.dnn.DNN_TARGET_CUDA)
my_function(network, frame)
end = time.time()
print(end - start)

但运行时间是相同的

我的问题:使用setPreferableBackend()和setPreferableTarget()是否足以利用GPU的能力


Tags: pathgputimecountnetworkcv2startcv
2条回答

这应该足以使它使用CUDA,你应该看到一个明显的加速。检查任务管理器的“性能”选项卡,查看是否正在使用Nvidia GPU。我不知道在我的函数()的幕后发生了什么,所以我无法判断您使用它的方式是否有所不同

当我想要快速设置Yolo网络时,我通常会复制这个类

import cv2
import numpy as np

class Yolo:
    def __init__(self, cfg, weights, names, conf_thresh, nms_thresh, use_cuda = False):
        # save thresholds
        self.ct = conf_thresh;
        self.nmst = nms_thresh;

        # create net
        self.net = cv2.dnn.readNet(weights, cfg);
        print("Finished: " + str(weights));
        self.classes = [];
        file = open(names, 'r');
        for line in file:
            self.classes.append(line.strip());

        # use gpu + CUDA to speed up detections
        if use_cuda:
            self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA);
            self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA);

        # get output names
        layer_names = self.net.getLayerNames();
        self.output_layers = [layer_names[i[0]-1] for i in self.net.getUnconnectedOutLayers()];

    # runs detection on the image and draws on it
    def detect(self, img, target_id = None):
        # get detection stuff
        b, c, ids, idxs = self.get_detection_data(img, target_id);

        # draw result
        img = self.draw(img, b, c, ids, idxs);
        return img, len(idxs);

    # returns boxes, confidences, class_ids, and indexes (indices?)
    def get_detection_data(self, img, target_id = None):
        # get output
        layer_outputs = self.get_inf(img);

        # get dims
        height, width = img.shape[:2];

        # filter thresholds and target
        b, c, ids, idxs = self.thresh(layer_outputs, width, height, target_id);
        return b, c, ids, idxs;

    # runs the network on an image
    def get_inf(self, img):
        # construct a blob
        blob = cv2.dnn.blobFromImage(img, 1 / 255.0, (416,416), swapRB=True, crop=False);

        # get response
        self.net.setInput(blob);
        layer_outputs = self.net.forward(self.output_layers);
        return layer_outputs;

    # filters the layer output by conf, nms and id
    def thresh(self, layer_outputs, width, height, target_id = None):
        # some lists
        boxes = [];
        confidences = [];
        class_ids = [];

        # each layer outputs
        for output in layer_outputs:
            for detection in output:
                # get id and confidence
                scores = detection[5:];
                class_id = np.argmax(scores);
                confidence = scores[class_id];

                # filter out low confidence
                if confidence > self.ct:
                    # filter by target_id if set
                    if target_id is None or class_id == target_id:
                        # scale bounding box back to the image size
                        box = detection[0:4] * np.array([width, height, width, height]);
                        (cx, cy, w, h) = box.astype('int');

                        # grab the top-left corner of the box
                        tx = int(cx - (w / 2));
                        ty = int(cy - (h / 2));

                        # update lists
                        boxes.append([tx,ty,int(w),int(h)]);
                        confidences.append(float(confidence));
                        class_ids.append(class_id);

        # apply NMS
        idxs = cv2.dnn.NMSBoxes(boxes, confidences, self.ct, self.nmst);
        return boxes, confidences, class_ids, idxs;

    # draw detections on image
    def draw(self, img, boxes, confidences, class_ids, idxs):
        # check for zero
        if len(idxs) > 0:
            # loop over indices
            for i in idxs.flatten():
                # extract the bounding box coords
                (x,y) = (boxes[i][0], boxes[i][1]);
                (w,h) = (boxes[i][2], boxes[i][3]);

                # draw a box
                cv2.rectangle(img, (x,y), (x+w,y+h), (0,0,255), 2);

                # draw text
                text = "{}: {:.4}".format(self.classes[class_ids[i]], confidences[i]);
                cv2.putText(img, text, (x, y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 2);
        return img;

你可以这样使用它

import cv2
import numpy as np

# this is the "yolo.py" file, I assume it's in the same folder as this program
from yolo import Yolo

# these are the filepaths of the yolo files
weights = "yolov3-tiny.weights";
config = "yolov3-tiny.cfg";
labels = "yolov3.txt";

# init yolo network
target_class_id = 79; # toothbrush
conf_thresh = 0.4; # less == more boxes (but more false positives)
nms_thresh = 0.4; # less == more boxes (but more overlap)
net = Yolo(config, weights, labels, conf_thresh, nms_thresh, use_cuda = True);

# open video capture
cap = cv2.VideoCapture(0); # probably laptop webcam

# loop
done = False;
while not done:
    # get frame
    ret, frame = cap.read();
    if not ret:
        done = cv2.waitKey(1) == ord('q');
        continue;

    # draw detection
    # frame, _ = net.detect(frame, target_id=target_class_id); # use this to filter by a single class_id
    frame, _ = net.detect(frame); # use this to not filter by class_id

    # show
    cv2.imshow("Marked", frame);
    done = cv2.waitKey(1) == ord('q');

编辑:哦,好的,哈哈。我找到了我的安装说明,第一条说明是:

  1. 跟随PyImageSearch的博客安装带有cuda支持的opencv

网址是:

https://www.pyimagesearch.com/2020/02/03/how-to-use-opencvs-dnn-module-with-nvidia-gpus-cuda-and-cudnn/

不确定这会有多大帮助,但我显然认为教程已经足够清楚了,我不需要为这一步做任何额外的注释或更正

首先,在运行代码之前,您必须检查您的工作环境

您使用的是什么虚拟机?通常,虚拟机不支持GPU虚拟化。您必须添加PCI直通才能获得此功能

如果为true,您是否可以首先通过运行nvidia-smi(在您喜爱的bash/cmd环境中)来检查nvidia驱动程序,以检查您的设备是否已成功检测到

然后通过在python shell cv2.cuda.getCudaEnabledDeviceCount()中运行来检查opencv python是否支持gpu

如果结果为0,并且nvidia smi检测到您的gpu,则必须在特定gpu模型的支持下编译python opencv控制盘,并将其安装到python环境中

相关问题 更多 >

    热门问题