YOLOv4 Object Detection using OpenCV

YOLO (You Only Look Once) is an object detection algorithm that allows to detect objects in an images in near real-time. YOLOv4 is 4th version of YOLO which introduced in April 2020.

This tutorial gives example how to use pre-trained YOLOv4 model to detect objects in an image using OpenCV.

Prepare environment

Before starting, download YOLOv4 network configuration (yolov4.cfg) and weights (yolov4.weights) from releases page of AlexeyAB/darknet repository.

Model was trained on COCO dataset which consists of 80 object categories. Download coco.names file which contains class names.

Code

We read an image and class names. Next, we read network configuration and pre-trained weights. We initialize detection model and set input parameters. 1/255 scale factor defines that pixel values will be scaled from 0 to 1. Given image will be resized to the size of 416×416 without cropping. The swapRB parameter defines that first and last channels will be swapped because OpenCV uses BGR.

We detect objects in an image. Confidence score threshold (in our case 0.6) used to filter boxes by confidence scores. The most appropriate boxes are selected by using non-maximum suppression (NMS). NMS is controlled by threshold (0.4 in our case).

Finally, we draw bounding boxes along with class labels and scores on an image.

import cv2

img = cv2.imread('test.jpg')

with open('coco.names', 'r') as f:
    classes = f.read().splitlines()

net = cv2.dnn.readNetFromDarknet('yolov4.cfg', 'yolov4.weights')

model = cv2.dnn_DetectionModel(net)
model.setInputParams(scale=1 / 255, size=(416, 416), swapRB=True)

classIds, scores, boxes = model.detect(img, confThreshold=0.6, nmsThreshold=0.4)

for (classId, score, box) in zip(classIds, scores, boxes):
    cv2.rectangle(img, (box[0], box[1]), (box[0] + box[2], box[1] + box[3]),
                  color=(0, 255, 0), thickness=2)

    text = '%s: %.2f' % (classes[classId[0]], score)
    cv2.putText(img, text, (box[0], box[1] - 5), cv2.FONT_HERSHEY_SIMPLEX, 1,
                color=(0, 255, 0), thickness=2)

cv2.imshow('Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace dnn;

int main()
{
    Mat img = imread("test.jpg");

    std::vector<std::string> classes;
    std::ifstream file("coco.names");
    std::string line;
    while (std::getline(file, line)) {
        classes.push_back(line);
    }

    Net net = readNetFromDarknet("yolov4.cfg", "yolov4.weights");

    DetectionModel model = DetectionModel(net);
    model.setInputParams(1 / 255.0, Size(416, 416), Scalar(), true);

    std::vector<int> classIds;
    std::vector<float> scores;
    std::vector<Rect> boxes;
    model.detect(img, classIds, scores, boxes, 0.6, 0.4);

    for (int i = 0; i < classIds.size(); i++) {
        rectangle(img, boxes[i], Scalar(0, 255, 0), 2);

        char text[100];
        snprintf(text, sizeof(text), "%s: %.2f", classes[classIds[i]].c_str(), scores[i]);
        putText(img, text, Point(boxes[i].x, boxes[i].y - 5), cv::FONT_HERSHEY_SIMPLEX, 1,
                Scalar(0, 255, 0), 2);
    }

    imshow("Image", img);
    waitKey(0);
    destroyAllWindows();

    return 0;
}
package app;

import org.opencv.core.*;
import org.opencv.dnn.DetectionModel;
import org.opencv.dnn.Dnn;
import org.opencv.dnn.Net;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

public class Main
{
    static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }

    public static void main(String[] args) throws IOException
    {
        Mat img = Imgcodecs.imread("test.jpg");

        List<String> classes = Files.readAllLines(Paths.get("coco.names"));

        Net net = Dnn.readNetFromDarknet("yolov4.cfg", "yolov4.weights");

        DetectionModel model = new DetectionModel(net);
        model.setInputParams(1 / 255.0, new Size(416, 416), new Scalar(0), true);

        MatOfInt classIds = new MatOfInt();
        MatOfFloat scores = new MatOfFloat();
        MatOfRect boxes = new MatOfRect();
        model.detect(img, classIds, scores, boxes, 0.6f, 0.4f);

        for (int i = 0; i < classIds.rows(); i++) {
            Rect box = new Rect(boxes.get(i, 0));
            Imgproc.rectangle(img, box, new Scalar(0, 255, 0), 2);

            int classId = (int) classIds.get(i, 0)[0];
            double score = scores.get(i, 0)[0];
            String text = String.format("%s: %.2f", classes.get(classId), score);
            Imgproc.putText(img, text, new Point(box.x, box.y - 5),
                    Imgproc.FONT_HERSHEY_SIMPLEX, 1, new Scalar(0, 255, 0), 2);
        }

        HighGui.imshow("Image", img);
        HighGui.waitKey(0);
        HighGui.destroyAllWindows();

        System.exit(0);
    }
}

Here is result:

YOLOv4 object detection using OpenCV

Leave a Comment

Your email address will not be published. Required fields are marked *