#include <fstream>
#include <sstream>
#include "common.hpp"
std::string keys =
"{ help h | | Print help message. }"
"{ @alias | | An alias name of model to extract preprocessing parameters from models.yml file. }"
"{ zoo | models.yml | An optional path to file with preprocessing parameters }"
"{ device | 0 | camera device number. }"
"{ input i | | Path to input image or video file. Skip this argument to capture frames from a camera. }"
"{ framework f | | Optional name of an origin framework of the model. Detect it automatically if it does not set. }"
"{ classes | | Optional path to a text file with names of classes. }"
"{ colors | | Optional path to a text file with colors for an every class. "
"An every color is represented with three values from 0 to 255 in BGR channels order. }"
"{ backend | 0 | Choose one of computation backends: "
"0: automatically (by default), "
"1: Halide language (http://halide-lang.org/), "
"2: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), "
"3: OpenCV implementation, "
"4: VKCOM, "
"5: CUDA }"
"{ target | 0 | Choose one of target computation devices: "
"0: CPU target (by default), "
"1: OpenCL, "
"2: OpenCL fp16 (half-float precision), "
"3: VPU, "
"4: Vulkan, "
"6: CUDA, "
"7: CUDA fp16 (half-float preprocess) }";
using namespace dnn;
std::vector<std::string> classes;
std::vector<Vec3b> colors;
void showLegend();
void colorizeSegmentation(
const Mat &score,
Mat &segm);
int main(
int argc,
char** argv)
{
const std::string modelName = parser.get<
String>(
"@alias");
const std::string zooFile = parser.get<
String>(
"zoo");
keys += genPreprocArguments(modelName, zooFile);
parser.about("Use this script to run semantic segmentation deep learning networks using OpenCV.");
if (argc == 1 || parser.has("help"))
{
parser.printMessage();
return 0;
}
float scale = parser.get<float>("scale");
bool swapRB = parser.get<bool>("rgb");
int inpWidth = parser.get<int>("width");
int inpHeight = parser.get<int>("height");
int backendId = parser.get<int>("backend");
int targetId = parser.get<int>("target");
if (parser.has("classes"))
{
std::string file = parser.get<
String>(
"classes");
std::ifstream ifs(file.c_str());
if (!ifs.is_open())
CV_Error(Error::StsError,
"File " + file +
" not found");
std::string line;
while (std::getline(ifs, line))
{
classes.push_back(line);
}
}
if (parser.has("colors"))
{
std::string file = parser.get<
String>(
"colors");
std::ifstream ifs(file.c_str());
if (!ifs.is_open())
CV_Error(Error::StsError,
"File " + file +
" not found");
while (std::getline(ifs, line))
{
std::istringstream colorStr(
line.c_str());
for (int i = 0; i < 3 && !colorStr.eof(); ++i)
colorStr >> color[i];
colors.push_back(color);
}
}
if (!parser.check())
{
parser.printErrors();
return 1;
}
Net net =
readNet(model, config, framework);
net.setPreferableBackend(backendId);
net.setPreferableTarget(targetId);
static const std::string kWinName = "Deep learning semantic segmentation in OpenCV";
if (parser.has("input"))
else
cap.
open(parser.get<
int>(
"device"));
{
cap >> frame;
if (frame.empty())
{
break;
}
net.setInput(blob);
Mat score = net.forward();
colorizeSegmentation(score, segm);
resize(segm, segm, frame.size(), 0, 0, INTER_NEAREST);
std::vector<double> layersTimes;
double t = net.getPerfProfile(layersTimes) / freq;
std::string label =
format(
"Inference time: %.2f ms", t);
if (!classes.empty())
showLegend();
}
return 0;
}
void colorizeSegmentation(
const Mat &score,
Mat &segm)
{
const int rows = score.
size[2];
const int cols = score.
size[3];
const int chns = score.
size[1];
if (colors.empty())
{
colors.push_back(
Vec3b());
for (int i = 1; i < chns; ++i)
{
for (int j = 0; j < 3; ++j)
color[j] = (colors[i - 1][j] + rand() % 256) / 2;
colors.push_back(color);
}
}
else if (chns != (int)colors.size())
{
CV_Error(Error::StsError,
format(
"Number of output classes does not match "
"number of colors (%d != %zu)", chns, colors.size()));
}
for (int ch = 1; ch < chns; ch++)
{
for (int row = 0; row < rows; row++)
{
const float *ptrScore = score.
ptr<
float>(0, ch, row);
uint8_t *ptrMaxCl = maxCl.
ptr<uint8_t>(row);
float *ptrMaxVal = maxVal.ptr<float>(row);
for (int col = 0; col < cols; col++)
{
if (ptrScore[col] > ptrMaxVal[col])
{
ptrMaxVal[col] = ptrScore[col];
ptrMaxCl[col] = (
uchar)ch;
}
}
}
}
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
ptrSegm[col] = colors[ptrMaxCl[col]];
}
}
}
void showLegend()
{
static const int kBlockHeight = 30;
{
const int numClasses = (int)classes.
size();
if ((int)colors.size() != numClasses)
{
CV_Error(Error::StsError,
format(
"Number of output classes does not match "
"number of labels (%zu != %zu)", colors.size(), classes.size()));
}
for (int i = 0; i < numClasses; i++)
{
Mat block = legend.
rowRange(i * kBlockHeight, (i + 1) * kBlockHeight);
putText(block, classes[i],
Point(0, kBlockHeight / 2), FONT_HERSHEY_SIMPLEX, 0.5,
Vec3b(255, 255, 255));
}
}
}
Designed for command line parsing.
Definition utility.hpp:863
n-dimensional dense array class
Definition mat.hpp:828
Mat & setTo(InputArray value, InputArray mask=noArray())
Sets all or some of the array elements to the specified value.
MatSize size
Definition mat.hpp:2176
uchar * data
pointer to the data
Definition mat.hpp:2156
void create(int rows, int cols, int type)
Allocates new array data if needed.
uchar * ptr(int i0=0)
Returns a pointer to the specified matrix row.
Mat rowRange(int startrow, int endrow) const
Creates a matrix header for the specified row span.
bool empty() const
Returns true if the array has no elements.
Template class for specifying the size of an image or rectangle.
Definition types.hpp:335
Template class for short numerical vectors, a partial case of Matx.
Definition matx.hpp:369
Class for video capturing from video files, image sequences or cameras.
Definition videoio.hpp:735
virtual bool open(const String &filename, int apiPreference=CAP_ANY)
Opens a video file or a capturing device or an IP video stream for video capturing.
void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1)
Calculates the weighted sum of two arrays.
std::string String
Definition cvstd.hpp:151
#define CV_32FC1
Definition interface.h:118
unsigned char uchar
Definition interface.h:51
#define CV_8UC1
Definition interface.h:88
#define CV_8UC3
Definition interface.h:90
String format(const char *fmt,...)
Returns a text string formatted using the printf-like expression.
#define CV_Error(code, msg)
Call the error handler.
Definition base.hpp:335
double getTickFrequency()
Returns the number of ticks per second.
#define CV_Assert(expr)
Checks a condition at runtime and throws exception if it fails.
Definition base.hpp:359
Mat blobFromImage(InputArray image, double scalefactor=1.0, const Size &size=Size(), const Scalar &mean=Scalar(), bool swapRB=false, bool crop=false, int ddepth=CV_32F)
Creates 4-dimensional blob from image. Optionally resizes and crops image from center,...
Net readNet(CV_WRAP_FILE_PATH const String &model, CV_WRAP_FILE_PATH const String &config="", const String &framework="")
Read deep learning network represented in one of the supported formats.
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
int waitKey(int delay=0)
Waits for a pressed key.
void namedWindow(const String &winname, int flags=WINDOW_AUTOSIZE)
Creates a window.
void putText(InputOutputArray img, const String &text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=LINE_8, bool bottomLeftOrigin=false)
Draws a text string.
void line(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
Draws a line segment connecting two points.
int main(int argc, char *argv[])
Definition highgui_qt.cpp:3