首先,感谢zhigang师兄提供的机器学习结果,他的GitHub地址:https://github.com/gloomyfish1998/opencv_tutorial
点击打开链接 总共是完成了20种对象的机器学习,与之配套的文章在这里http://mp.weixin.qq.com/s/95hftpJfSDIMlMVOC7iq4g,
点击打开链接,是的,微信公众号上的文章。对应的英文文献 You Only Look Once:Unified, Real-Time Object Detection,也就是千年圈内大热的YOLO检测。
资源地址:https://download.csdn.net/download/qq_15522447/10351828 点击打开链接
开始调试之前,要在VS2013配置openCV331环境,配置环境这种东西还是要实际的操作多次,才能算的上是掌握,如果非要加一个次数期限,就是5次。网上充斥着环境配置的各种文章,请自行百度吧。
话不多说,先上对象检测运行效果
环境配置完成后,就简单建一个控制台应用程序吧。
1. 导入头文件
资源地址:https://download.csdn.net/download/qq_15522447/10351828 点击打开链接
开始调试之前,要在VS2013配置openCV331环境,配置环境这种东西还是要实际的操作多次,才能算的上是掌握,如果非要加一个次数期限,就是5次。网上充斥着环境配置的各种文章,请自行百度吧。
话不多说,先上对象检测运行效果
环境配置完成后,就简单建一个控制台应用程序吧。
1. 导入头文件
#include <vector>
#include <string>
#include <opencv.hpp>
#include <opencv2\dnn.hpp>
#include <opencv2\objdetect.hpp>
#include <opencv2\world.hpp>
#include <opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
using namespace dnn;
2. 主函数
string modelConfiguration ="F:/opencv_tutorial-master/data/models/yolov2-tiny-voc/yolov2-tiny-voc.cfg";
string modelBinary ="F:/opencv_tutorial-master/data/models/yolov2-tiny-voc/yolov2-tiny-voc.weights";
Net net = readNetFromDarknet(modelConfiguration, modelBinary);
if(net.empty())
{
printf("Could not load net...\n");
return 0;
}
vector<string> classNamesVec;
ifstream classNamesFile("F:/opencv_tutorial-master/data/models/yolov2-tiny-voc/voc.names");
if(classNamesFile.is_open())
{
string className = "";
while(getline(classNamesFile, className))
classNamesVec.push_back(className);
}
// 加载图像
Mat frame = imread("F:/opencv_tutorial-master/race.jpg");
frame = objectDetection(frame, net, classNamesVec);
imshow("检测结果", frame);
waitKey();
return 0;
3. 相关函数及实现
Mat objectDetection(Mat frame, Net net, vector<string> classNamesVec);
Mat objectDetection(Mat frame, Net net, vector<string> classNamesVec)
{
Mat inputBlob = blobFromImage(frame, 1 / 255.F, Size(416, 416), Scalar(), true, false);
net.setInput(inputBlob, "data");
// 检测
Mat detectionMat = net.forward("detection_out");
ostringstream ss;
// 输出结果
for (int i = 0; i < detectionMat.rows; i++)
{
const int probability_index = 5;
const int probability_size = detectionMat.cols - probability_index;
float *prob_array_ptr = &detectionMat.at<float>(i, probability_index);
size_t objectClass = max_element(prob_array_ptr, prob_array_ptr + probability_size) - prob_array_ptr;
float confidence = detectionMat.at<float>(i, (int)objectClass + probability_index);
if (confidence > confidenceThreshold)
{
float x = detectionMat.at<float>(i, 0);
float y = detectionMat.at<float>(i, 1);
float width = detectionMat.at<float>(i, 2);
float height = detectionMat.at<float>(i, 3);
int xLeftBottom = static_cast<int>((x - width / 2) * frame.cols);
int yLeftBottom = static_cast<int>((y - height / 2) * frame.rows);
int xRightTop = static_cast <int>((x + width / 2) * frame.cols);
int yRightTop = static_cast <int>((y + height / 2) * frame.rows);
Rect object(xLeftBottom, yLeftBottom, xRightTop - xLeftBottom, yRightTop - yLeftBottom);
rectangle(frame, object, Scalar(0, 0, 255), 2, 8);
if (objectClass < classNamesVec.size())
{
ss.str("");
ss << confidence;
String conf(ss.str());
String label = String(classNamesVec[objectClass]) + ": " + conf;
int baseLine = 0;
Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
rectangle(frame, Rect(Point(xLeftBottom, yLeftBottom), Size(labelSize.width, labelSize.height + baseLine)), Scalar(255, 255, 255), CV_FILLED);
putText(frame, label, Point(xLeftBottom, yLeftBottom + labelSize.height), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0));
}
}
}
return frame;
}
4. 置信度阈值
float confidenceThreshold = 0.25;
原图与对象检测结果
检测结果图中 ,红色方框为对象结果对象的定位,左上角标签文字为检测结果,结果后的数值表示置信度。显然,机器学习将图中的那个逗比看成了飞机,不过还是蛮厉害的,确实如同是一架飞机,机器学习做了抽象推理,哈哈!这个对象检测方法有很多可以优化的地方,连续运行时速度较慢,会造成画面卡顿,fighting!!!