借助OpenCv4的dnn模块
    已完成对各部分代码的注释

    1. #pragma once
    2. #include<opencv2\opencv.hpp>
    3. #include<opencv2\dnn.hpp>
    4. #include<fstream>
    5. #include<iostream>
    6. using namespace std;
    7. using namespace cv;
    8. using namespace cv::dnn;
    9. int main()
    10. {
    11. //---------------------------------------加载类别---------------------------------------
    12. ifstream classNamesFile("D:/OpenCV/model/coco.names");
    13. //ifstream默认以输入方式打开文件,
    14. vector<string> classNamesVec;
    15. if (classNamesFile.is_open())
    16. {
    17. string className = "";
    18. while (std::getline(classNamesFile, className))
    19. classNamesVec.push_back(className);
    20. //getline()中读入结束的回车后,结束符不放入缓存区,会将读入的\n直接去除
    21. }
    22. //输出网络内容
    23. for (int i = 0; i < classNamesVec.size(); i++) {
    24. cout << i + 1 << "\t" << classNamesVec[i].c_str() << endl;
    25. }
    26. //---------------------------------------模型设置---------------------------------------
    27. //训练好的模型路径
    28. String cfg = "D:/OpenCV/model/yolov4.cfg";
    29. String weight = "D:/OpenCV/model/yolov4.weights";
    30. //模型读入
    31. dnn::Net net = readNetFromDarknet(cfg, weight);
    32. //预处理读取的图像,并将图像读入网络
    33. Mat frame = imread("D:/OpenCV/data/faces.jpg");
    34. imshow("【输入图像】", frame);
    35. //规范化
    36. Mat inputBlob = blobFromImage(frame, 1.0 / 255, Size(608, 608), Scalar());
    37. net.setInput(inputBlob);
    38. //获取未连接输出层,用于网络的向前计算
    39. std::vector<String> outNames = net.getUnconnectedOutLayersNames();
    40. for (int i = 0; i < outNames.size(); i++) {
    41. cout << "output layer name : " << outNames[i].c_str() << endl;
    42. }
    43. //完成神经网络向前计算
    44. std::vector<Mat> outs;
    45. net.forward(outs, outNames);
    46. //---------------------------------------目标检测---------------------------------------
    47. //需要的变量
    48. float* data;
    49. Mat scores;
    50. vector<Rect> boxes;
    51. vector<int> classIds;
    52. vector<float> confidences;
    53. int centerX, centerY, width, height, left, top;
    54. float confidenceThreshold = 0.2;
    55. double confidence;
    56. Point classIdPoint;
    57. //找出所有的目标及其位置
    58. for (size_t i = 0; i < outs.size(); ++i) {
    59. data = (float*)outs[i].data;
    60. for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols) {
    61. scores = outs[i].row(j).colRange(5, outs[i].cols);
    62. minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
    63. if (confidence > confidenceThreshold) {
    64. centerX = (int)(data[0] * frame.cols);
    65. centerY = (int)(data[1] * frame.rows);
    66. width = (int)(data[2] * frame.cols);
    67. height = (int)(data[3] * frame.rows);
    68. left = centerX - width / 2;
    69. top = centerY - height / 2;
    70. classIds.push_back(classIdPoint.x);
    71. confidences.push_back((float)confidence);
    72. boxes.push_back(Rect(left, top, width, height));
    73. }
    74. }
    75. }
    76. //执行非最大抑制,
    77. //去掉重叠率大于nmsThreshold的候选框
    78. vector<int> indices;
    79. NMSBoxes(boxes, confidences, 0.3, 0.2, indices);
    80. //---------------------------------------效果展示---------------------------------------
    81. Scalar rectColor, textColor; //box 和 text 的颜色
    82. Rect box, textBox;
    83. int idx;
    84. String className;
    85. Size labelSize;
    86. for (size_t i = 0; i < indices.size(); ++i) {
    87. idx = indices[i];
    88. className = classNamesVec[classIds[idx]];
    89. labelSize = getTextSize(className, FONT_HERSHEY_SIMPLEX, 0.5, 1, 0);
    90. box = boxes[idx];
    91. textBox = Rect(Point(box.x - 1, box.y),
    92. Point(box.x + labelSize.width, box.y - labelSize.height));
    93. rectColor = Scalar(idx * 11 % 256, idx * 22 % 256, idx * 33 % 256);
    94. textColor = Scalar(255 - idx * 11 % 256, 255 - idx * 22 % 256, 255 - idx * 33 % 256);
    95. rectangle(frame, box, rectColor, 2, 8, 0);
    96. rectangle(frame, textBox, rectColor, -1, 8, 0);
    97. putText(frame, className.c_str(), Point(box.x, box.y - 2), FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1, 8);
    98. }
    99. imshow("【OpenCV - YOLO】", frame);
    100. waitKey(0);
    101. return 0;
    102. }

    海参识别

    1. using namespace std;
    2. using namespace cv;
    3. using namespace cv::dnn;
    4. int main()
    5. {
    6. //---------------------------------------加载类别---------------------------------------
    7. ifstream classNamesFile("D:/OpenCV/model/yoloA/obj.names");
    8. //ifstream默认以输入方式打开文件,
    9. vector<string> classNamesVec;
    10. if (classNamesFile.is_open())
    11. {
    12. string className = "";
    13. while (std::getline(classNamesFile, className))
    14. classNamesVec.push_back(className);
    15. //getline()中读入结束的回车后,结束符不放入缓存区,会将读入的\n直接去除
    16. }
    17. //输出网络内容
    18. for (int i = 0; i < classNamesVec.size(); i++) {
    19. cout << i + 1 << "\t" << classNamesVec[i].c_str() << endl;
    20. }
    21. //---------------------------------------模型设置---------------------------------------
    22. //训练好的模型路径
    23. String cfg = "D:/OpenCV/model/yoloA/yolov4-tiny-obj.cfg";
    24. String weight = "D:/OpenCV/model/yoloA/yolov4-tiny-obj_7000.weights";
    25. //模型读入
    26. dnn::Net net = readNetFromDarknet(cfg, weight);
    27. //预处理读取的图像,并将图像读入网络
    28. Mat frame = imread("D:/OpenCV/image/haishen.jpg");
    29. imshow("【输入图像】", frame);
    30. //规范化
    31. Mat inputBlob = blobFromImage(frame, 1.0 / 255, Size(608, 608), Scalar());
    32. net.setInput(inputBlob);
    33. //获取未连接输出层,用于网络的向前计算
    34. std::vector<String> outNames = net.getUnconnectedOutLayersNames();
    35. for (int i = 0; i < outNames.size(); i++) {
    36. cout << "output layer name : " << outNames[i].c_str() << endl;
    37. }
    38. //完成神经网络向前计算
    39. std::vector<Mat> outs;
    40. net.forward(outs, outNames);
    41. //---------------------------------------目标检测---------------------------------------
    42. //需要的变量
    43. float* data;
    44. Mat scores;
    45. vector<Rect> boxes;
    46. vector<int> classIds;
    47. vector<float> confidences;
    48. int centerX, centerY, width, height, left, top;
    49. float confidenceThreshold = 0.2;
    50. double confidence;
    51. Point classIdPoint;
    52. //找出所有的目标及其位置
    53. for (size_t i = 0; i < outs.size(); ++i) {
    54. data = (float*)outs[i].data;
    55. for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols) {
    56. scores = outs[i].row(j).colRange(5, outs[i].cols);
    57. minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
    58. if (confidence > confidenceThreshold) {
    59. centerX = (int)(data[0] * frame.cols);
    60. centerY = (int)(data[1] * frame.rows);
    61. width = (int)(data[2] * frame.cols);
    62. height = (int)(data[3] * frame.rows);
    63. left = centerX - width / 2;
    64. top = centerY - height / 2;
    65. classIds.push_back(classIdPoint.x);
    66. confidences.push_back((float)confidence);
    67. boxes.push_back(Rect(left, top, width, height));
    68. }
    69. }
    70. }
    71. //执行非最大抑制,
    72. //去掉重叠率大于nmsThreshold的候选框
    73. vector<int> indices;
    74. NMSBoxes(boxes, confidences, 0.3, 0.2, indices);
    75. //---------------------------------------效果展示---------------------------------------
    76. Scalar rectColor, textColor; //box 和 text 的颜色
    77. Rect box, textBox;
    78. int idx;
    79. String className;
    80. Size labelSize;
    81. for (size_t i = 0; i < indices.size(); ++i) {
    82. idx = indices[i];
    83. className = classNamesVec[classIds[idx]];
    84. labelSize = getTextSize(className, FONT_HERSHEY_SIMPLEX, 0.5, 1, 0);
    85. box = boxes[idx];
    86. textBox = Rect(Point(box.x - 1, box.y),
    87. Point(box.x + labelSize.width, box.y - labelSize.height));
    88. rectColor = Scalar(idx * 11 % 256, idx * 22 % 256, idx * 33 % 256);
    89. textColor = Scalar(255 - idx * 11 % 256, 255 - idx * 22 % 256, 255 - idx * 33 % 256);
    90. rectangle(frame, box, rectColor, 2, 8, 0);
    91. rectangle(frame, textBox, rectColor, -1, 8, 0);
    92. putText(frame, className.c_str(), Point(box.x, box.y - 2), FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1, 8);
    93. }
    94. imshow("【OpenCV - YOLO】", frame);
    95. waitKey(0);
    96. return 0;
    97. }