VS2015+Opencv4.0+Yolo V3

本文參考github的一個(gè)項(xiàng)目ObjectDetection-YOLO方篮,代碼都是參考上面的兽肤,作者環(huán)境是linux叉讥,稍加修改后捶障,在此給出一個(gè)在Win10底下可以運(yùn)行的簡(jiǎn)單的demo是鬼,先說一下運(yùn)行環(huán)境


  1. 需要下載yolov3.weights權(quán)重文件肤舞、yolov3.cfg網(wǎng)絡(luò)構(gòu)建文件、coco.names均蜜、xxx.jpg李剖、xxx.mp4文件以及其他的object_detection_yolo.cpp、object_detection_yolo.py等文件囤耳。
    github下載鏈接
    網(wǎng)盤下載鏈接(推薦) 密碼:gfg1
  2. 配好opencv環(huán)境篙顺,網(wǎng)上教程很多不再贅述。
  3. 運(yùn)行環(huán)境 vs2015+opencv4.0+win10

代碼如下

#include <fstream>
#include <sstream>
#include <iostream>
#include <io.h>
#include<opencv2/core/types_c.h>
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

using namespace cv;
using namespace dnn;
using namespace std;

// Initialize the parameters
float confThreshold = 0.5; // Confidence threshold
float nmsThreshold = 0.4;  // Non-maximum suppression threshold
int inpWidth = 416;  // Width of network's input image
int inpHeight = 416; // Height of network's input image
vector<string> classes;

// Remove the bounding boxes with low confidence using non-maxima suppression
void postprocess(Mat& frame, const vector<Mat>& out);

// Draw the predicted bounding box
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame);

// Get the names of the output layers
vector<String> getOutputsNames(const Net& net);

int main(int argc, char** argv)
{
    String name_file = "coco.names";
    String model_def = "yolov3.cfg";
    String model_weights = "yolov3.weights";

    string imgname = "person";
    string img_path = imgname.append(".jpg");
    
    //read names
    ifstream ifs(name_file.c_str());
    string line;
    while (getline(ifs, line)) classes.push_back(line);

    //inti model
    Net net = readNetFromDarknet(model_def, model_weights);
    net.setPreferableBackend(DNN_BACKEND_OPENCV);
    net.setPreferableTarget(DNN_TARGET_CPU);
    
    //讀圖片
#ifdef Image
    //read image and forward
    Mat frame, blob;

    if ((_access(img_path.c_str(), 0)) == -1)
    {
        cerr << "file:" << img_path.c_str() << "not exist" << endl;
        return -1;
    }
    frame = imread(img_path);

    // Create a 4D blob from a frame.
    blobFromImage(frame, blob, 1 / 255.0, cvSize(inpWidth, inpHeight), Scalar(0, 0, 0), true, false);

    //  vector<Mat> mat_blob;
    //  imagesFromBlob(blob, mat_blob);


    //Sets the input to the network
    net.setInput(blob);

    // Runs the forward pass to get output of the output layers
    vector<Mat> outs;
    net.forward(outs, getOutputsNames(net));

    // Remove the bounding boxes with low confidence
    postprocess(frame, outs);

    // Put efficiency information. The function getPerfProfile returns the overall time for inference(t) and the timings for each of the layers(in layersTimes)
    vector<double> layersTimes;
    double freq = getTickFrequency() / 1000;
    double t = net.getPerfProfile(layersTimes) / freq;
    string label = format("Inference time for a frame : %.2f ms", t);
    putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255));
    imwrite(imgname.append("_label").append(".jpg"), frame);
    imshow("res", frame);
    waitKey(0);

#endif

    //讀視頻
#ifndef Image
    Mat frame, blob;
    VideoCapture cap;
    VideoWriter video;
    string outputFile = "yolo_out_cpp.avi";
    string video_path = "run.mp4";
    int k = 0;
    cap.open(video_path);
    if (!cap.isOpened())//如果視頻不能正常打開則返回
        return 0;

    static const string kWinName = "Deep learning object detection in OpenCV";
    namedWindow(kWinName, WINDOW_NORMAL);
    video.open(outputFile, VideoWriter::fourcc('M', 'J', 'P', 'G'), 28, Size(cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT)));

    // Process frames.
    while (1)
    {
        // get frame from the video
        cap >> frame;

        // Stop the program if reached end of video
        if (frame.empty()) {
            cout << "Done processing !!!" << endl;
            cout << "Output file is stored as " << outputFile << endl;
            waitKey(3000);
            break;
        }
        cout << "處理幀數(shù):" << k << endl;
        blobFromImage(frame, blob, 1 / 255.0, cvSize(inpWidth, inpHeight), Scalar(0, 0, 0), true, false);

        //Sets the input to the network
        net.setInput(blob);

        // Runs the forward pass to get output of the output layers
        vector<Mat> outs;
        net.forward(outs, getOutputsNames(net));

        // Remove the bounding boxes with low confidence
        postprocess(frame, outs);

        // Put efficiency information. The function getPerfProfile returns the overall time for inference(t) and the timings for each of the layers(in layersTimes)
        vector<double> layersTimes;
        double freq = getTickFrequency() / 1000;
        double t = net.getPerfProfile(layersTimes) / freq;
        string label = format("Inference time for a frame : %.2f ms", t);
        putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255));

        // Write the frame with the detection boxes
        Mat detectedFrame;
        frame.convertTo(detectedFrame, CV_8U);
        video.write(detectedFrame);
        imshow(kWinName, frame);
        k++;
    }

    cap.release();
#endif // !Image

    

    return 0;
}





// Get the names of the output layers
vector<String> getOutputsNames(const Net& net)
{
    static vector<String> names;
    if (names.empty())
    {
        //Get the indices of the output layers, i.e. the layers with unconnected outputs
        vector<int> outLayers = net.getUnconnectedOutLayers();

        //get the names of all the layers in the network
        vector<String> layersNames = net.getLayerNames();

        // Get the names of the output layers in names
        names.resize(outLayers.size());
        for (size_t i = 0; i < outLayers.size(); ++i)
            names[i] = layersNames[outLayers[i] - 1];
    }
    return names;
}

// Draw the predicted bounding box
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame)
{
    //Draw a rectangle displaying the bounding box
    rectangle(frame, Point(left, top), Point(right, bottom), Scalar(255, 178, 50), 3);

    //Get the label for the class name and its confidence
    string label = format("%.2f", conf);
    if (!classes.empty())
    {
        CV_Assert(classId < (int)classes.size());
        label = classes[classId] + ":" + label;
    }

    //Display the label at the top of the bounding box
    int baseLine;
    Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
    top = max(top, labelSize.height);
    rectangle(frame, Point(left, top - round(1.5*labelSize.height)), Point(left + round(1.5*labelSize.width), top + baseLine), Scalar(255, 255, 255), FILLED);
    putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 0), 1);
}

// Remove the bounding boxes with low confidence using non-maxima suppression
void postprocess(Mat& frame, const vector<Mat>& outs)
{
    vector<int> classIds;
    vector<float> confidences;
    vector<Rect> boxes;

    for (size_t i = 0; i < outs.size(); ++i)
    {
        // Scan through all the bounding boxes output from the network and keep only the
        // ones with high confidence scores. Assign the box's class label as the class
        // with the highest score for the box.
        float* data = (float*)outs[i].data;
        for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols)
        {
            Mat scores = outs[i].row(j).colRange(5, outs[i].cols);
            Point classIdPoint;
            double confidence;
            // Get the value and location of the maximum score
            minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
            if (confidence > confThreshold)
            {
                int centerX = (int)(data[0] * frame.cols);
                int centerY = (int)(data[1] * frame.rows);
                int width = (int)(data[2] * frame.cols);
                int height = (int)(data[3] * frame.rows);
                int left = centerX - width / 2;
                int top = centerY - height / 2;

                classIds.push_back(classIdPoint.x);
                confidences.push_back((float)confidence);
                boxes.push_back(Rect(left, top, width, height));
            }
        }
    }

    // Perform non maximum suppression to eliminate redundant overlapping boxes with
    // lower confidences
    vector<int> indices;
    NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
    for (size_t i = 0; i < indices.size(); ++i)
    {
        int idx = indices[i];
        Rect box = boxes[idx];
        drawPred(classIds[idx], confidences[idx], box.x, box.y,
            box.x + box.width, box.y + box.height, frame);
    }
}

總結(jié):

  1. 處理圖片簡(jiǎn)單一點(diǎn)充择,處理視頻折騰了好久德玫,一開始配好環(huán)境控制臺(tái)一直黑屏,后來知道其實(shí)就是速度慢點(diǎn)椎麦,示例視頻run.mp4大約5秒宰僧,幀數(shù)約為150張,最后在程序中加了一個(gè)處理幀數(shù)計(jì)數(shù)器K才能看出观挎,以下為運(yùn)行結(jié)果圖


    視頻處理完截圖
  2. 圖片處理結(jié)果圖


    圖片處理結(jié)果
  3. 小伙伴們有什么圖要試驗(yàn)的只要把路徑改一下應(yīng)該就能跑起來琴儿,有什么問題可以在評(píng)論區(qū)交流,
    PS:簡(jiǎn)書好像不能傳視頻键兜,貼一張?zhí)幚砗玫囊曨l截圖
    視頻截圖

    PS-2:已經(jīng)把視頻上傳至b站, 傳送門
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凤类,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子普气,更是在濱河造成了極大的恐慌谜疤,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異夷磕,居然都是意外死亡履肃,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門坐桩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尺棋,“玉大人,你說我怎么就攤上這事绵跷”烀” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵碾局,是天一觀的道長(zhǎng)荆残。 經(jīng)常有香客問我,道長(zhǎng)净当,這世上最難降的妖魔是什么内斯? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮像啼,結(jié)果婚禮上俘闯,老公的妹妹穿的比我還像新娘。我一直安慰自己忽冻,他們只是感情好真朗,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著甚颂,像睡著了一般蜜猾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上振诬,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天蹭睡,我揣著相機(jī)與錄音,去河邊找鬼赶么。 笑死肩豁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辫呻。 我是一名探鬼主播清钥,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼放闺!你這毒婦竟也來了祟昭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤怖侦,失蹤者是張志新(化名)和其女友劉穎篡悟,沒想到半個(gè)月后谜叹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡搬葬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年荷腊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片急凰。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡女仰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出抡锈,到底是詐尸還是另有隱情疾忍,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布企孩,位于F島的核電站锭碳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏勿璃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一推汽、第九天 我趴在偏房一處隱蔽的房頂上張望补疑。 院中可真熱鬧,春花似錦歹撒、人聲如沸莲组。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锹杈。三九已至,卻和暖如春迈着,著一層夾襖步出監(jiān)牢的瞬間竭望,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工裕菠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咬清,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓奴潘,卻偏偏與公主長(zhǎng)得像旧烧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子画髓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349