Skip to content

Commit 4913c64

Browse files
add mobilenet c++ sample (#171)
* add mobilenet c++ sample * review 1 * use blobFromImageWithParams * change int in dnn::Backend, dnn::Target * review 2 * review 3 * add include for labels imagenet1k * samples::findfile * Add -v option. 100 inferences max with a video when -v=false
1 parent 76c97b2 commit 4913c64

File tree

4 files changed

+1192
-0
lines changed

4 files changed

+1192
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
cmake_minimum_required(VERSION 3.2)
2+
set(project_name "opencv_zoo_image_classification_mobilenet")
3+
4+
PROJECT (${project_name})
5+
6+
set(OPENCV_VERSION "4.7.0")
7+
set(OPENCV_INSTALLATION_PATH "" CACHE PATH "Where to look for OpenCV installation")
8+
find_package(OpenCV ${OPENCV_VERSION} REQUIRED HINTS ${OPENCV_INSTALLATION_PATH})
9+
# Find OpenCV, you may need to set OpenCV_DIR variable
10+
# to the absolute path to the directory containing OpenCVConfig.cmake file
11+
# via the command line or GUI
12+
13+
file(GLOB SourceFile
14+
"demo.cpp")
15+
# If the package has been found, several variables will
16+
# be set, you can find the full list with descriptions
17+
# in the OpenCVConfig.cmake file.
18+
# Print some message showing some of them
19+
message(STATUS "OpenCV library status:")
20+
message(STATUS " config: ${OpenCV_DIR}")
21+
message(STATUS " version: ${OpenCV_VERSION}")
22+
message(STATUS " libraries: ${OpenCV_LIBS}")
23+
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
24+
25+
# Declare the executable target built from your sources
26+
add_executable(${project_name} ${SourceFile})
27+
28+
# Link your application with OpenCV libraries
29+
target_link_libraries(${project_name} PRIVATE ${OpenCV_LIBS})

models/image_classification_mobilenet/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Results of accuracy evaluation with [tools/eval](../../tools/eval).
1717

1818
## Demo
1919

20+
### Python
21+
2022
Run the following command to try the demo:
2123

2224
```shell
@@ -29,6 +31,24 @@ python demo.py --input /path/to/image --model v2
2931
python demo.py --help
3032
```
3133

34+
### C++
35+
36+
Install latest OpenCV and CMake >= 3.24.0 to get started with:
37+
38+
```shell
39+
# A typical and default installation path of OpenCV is /usr/local
40+
cmake -B build -D OPENCV_INSTALLATION_PATH=/path/to/opencv/installation .
41+
cmake --build build
42+
43+
# detect on camera input
44+
./build/opencv_zoo_image_classification_mobilenet
45+
# detect on an image
46+
./build/opencv_zoo_image_classification_mobilenet -m=/path/to/model -i=/path/to/image -v
47+
# get help messages
48+
./build/opencv_zoo_image_classification_mobilenet -h
49+
```
50+
51+
3252
## License
3353

3454
All files in this directory are licensed under [Apache 2.0 License](./LICENSE).
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#include <vector>
2+
#include <string>
3+
#include <utility>
4+
5+
#include <opencv2/opencv.hpp>
6+
#include "labelsimagenet1k.h"
7+
8+
using namespace std;
9+
using namespace cv;
10+
using namespace dnn;
11+
12+
vector< pair<dnn::Backend, dnn::Target> > backendTargetPairs = {
13+
std::make_pair<dnn::Backend, dnn::Target>(dnn::DNN_BACKEND_OPENCV, dnn::DNN_TARGET_CPU),
14+
std::make_pair<dnn::Backend, dnn::Target>(dnn::DNN_BACKEND_CUDA, dnn::DNN_TARGET_CUDA),
15+
std::make_pair<dnn::Backend, dnn::Target>(dnn::DNN_BACKEND_CUDA, dnn::DNN_TARGET_CUDA_FP16),
16+
std::make_pair<dnn::Backend, dnn::Target>(dnn::DNN_BACKEND_TIMVX, dnn::DNN_TARGET_NPU),
17+
std::make_pair<dnn::Backend, dnn::Target>(dnn::DNN_BACKEND_CANN, dnn::DNN_TARGET_NPU) };
18+
19+
20+
std::string keys =
21+
"{ help h | | Print help message. }"
22+
"{ model m | image_classification_mobilenetv1_2022apr.onnx | Usage: Set model type, defaults to image_classification_mobilenetv1_2022apr.onnx (v1) }"
23+
"{ input i | | Path to input image or video file. Skip this argument to capture frames from a camera.}"
24+
"{ initial_width | 0 | Preprocess input image by initial resizing to a specific width.}"
25+
"{ initial_height | 0 | Preprocess input image by initial resizing to a specific height.}"
26+
"{ rgb | true | swap R and B plane.}"
27+
"{ crop | false | Preprocess input image by center cropping.}"
28+
"{ vis v | true | Usage: Specify to open a new window to show results.}"
29+
"{ backend bt | 0 | Choose one of computation backends: "
30+
"0: (default) OpenCV implementation + CPU, "
31+
"1: CUDA + GPU (CUDA), "
32+
"2: CUDA + GPU (CUDA FP16), "
33+
"3: TIM-VX + NPU, "
34+
"4: CANN + NPU}";
35+
36+
37+
int main(int argc, char** argv)
38+
{
39+
CommandLineParser parser(argc, argv, keys);
40+
41+
parser.about("Use this script to run classification deep learning networks in opencv Zoo using OpenCV.");
42+
if (parser.has("help"))
43+
{
44+
parser.printMessage();
45+
return 0;
46+
}
47+
48+
int rszWidth = parser.get<int>("initial_width");
49+
int rszHeight = parser.get<int>("initial_height");
50+
bool swapRB = parser.get<bool>("rgb");
51+
bool crop = parser.get<bool>("crop");
52+
bool vis = parser.get<bool>("vis");
53+
String model = parser.get<String>("model");
54+
int backendTargetid = parser.get<int>("backend");
55+
56+
if (model.empty())
57+
{
58+
CV_Error(Error::StsError, "Model file " + model + " not found");
59+
}
60+
vector<string> labels = getLabelsImagenet1k();
61+
62+
Net net = readNet(samples::findFile(model));
63+
net.setPreferableBackend(backendTargetPairs[backendTargetid].first);
64+
net.setPreferableTarget(backendTargetPairs[backendTargetid].second);
65+
//! [Open a video file or an image file or a camera stream]
66+
VideoCapture cap;
67+
if (parser.has("input"))
68+
cap.open(samples::findFile(parser.get<String>("input")));
69+
else
70+
cap.open(0);
71+
if (!cap.isOpened())
72+
CV_Error(Error::StsError, "Cannot opend video or file");
73+
Mat frame, blob;
74+
static const std::string kWinName = model;
75+
int nbInference = 0;
76+
while (waitKey(1) < 0)
77+
{
78+
cap >> frame;
79+
if (frame.empty())
80+
{
81+
cout << "Frame is empty" << endl;
82+
waitKey();
83+
break;
84+
}
85+
86+
if (rszWidth != 0 && rszHeight != 0)
87+
{
88+
resize(frame, frame, Size(rszWidth, rszHeight));
89+
}
90+
Image2BlobParams paramMobilenet;
91+
paramMobilenet.datalayout = DNN_LAYOUT_NCHW;
92+
paramMobilenet.ddepth = CV_32F;
93+
paramMobilenet.mean = Scalar(123.675, 116.28, 103.53);
94+
paramMobilenet.scalefactor = Scalar(1 / (255. * 0.229), 1 / (255. * 0.224), 1 / (255. * 0.225));
95+
paramMobilenet.size = Size(224, 224);
96+
paramMobilenet.swapRB = swapRB;
97+
if (crop)
98+
paramMobilenet.paddingmode = DNN_PMODE_CROP_CENTER;
99+
else
100+
paramMobilenet.paddingmode = DNN_PMODE_NULL;
101+
//! [Create a 4D blob from a frame]
102+
blobFromImageWithParams(frame, blob, paramMobilenet);
103+
104+
//! [Set input blob]
105+
net.setInput(blob);
106+
Mat prob = net.forward();
107+
108+
//! [Get a class with a highest score]
109+
Point classIdPoint;
110+
double confidence;
111+
minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
112+
int classId = classIdPoint.x;
113+
std::string label = format("%s: %.4f", (labels.empty() ? format("Class #%d", classId).c_str() :
114+
labels[classId].c_str()),
115+
confidence);
116+
if (vis)
117+
{
118+
putText(frame, label, Point(0, 55), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
119+
imshow(kWinName, frame);
120+
}
121+
else
122+
{
123+
cout << label << endl;
124+
nbInference++;
125+
if (nbInference > 100)
126+
{
127+
cout << nbInference << " inference made. Demo existing" << endl;
128+
break;
129+
}
130+
}
131+
}
132+
return 0;
133+
}

0 commit comments

Comments
 (0)