Skip to content

Commit dd40e8e

Browse files
author
Aleksei Korobeinikov
authoredJun 7, 2021
Image processing C++ demo (openvinotoolkit#2123)
1 parent 183888b commit dd40e8e

26 files changed

+1110
-430
lines changed
 

‎demos/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ The Open Model Zoo includes the following demos:
2727
- [Human Pose Estimation C++ Demo](./human_pose_estimation_demo/cpp/README.md) - Human pose estimation demo.
2828
- [Human Pose Estimation Python\* Demo](./human_pose_estimation_demo/python/README.md) - Human pose estimation demo.
2929
- [Image Inpainting Python\* Demo](./image_inpainting_demo/python/README.md) - Demo application for GMCNN inpainting network.
30+
- [Image Processing C++ Demo](./image_processing_demo/cpp/README.md) - Demo application for deblurring and enhancing the resolution of the input image.
3031
- [Image Retrieval Python\* Demo](./image_retrieval_demo/python/README.md) - The demo demonstrates how to run Image Retrieval models using OpenVINO™.
3132
- [Image Segmentation C++ Demo](./segmentation_demo/cpp/README.md) - Inference of semantic segmentation networks (supports video and camera inputs).
3233
- [Image Segmentation Python\* Demo](./segmentation_demo/python/README.md) - Inference of semantic segmentation networks (supports video and camera inputs).
@@ -52,7 +53,6 @@ The Open Model Zoo includes the following demos:
5253
- [Single Human Pose Estimation Python\* Demo](./single_human_pose_estimation_demo/python/README.md) - 2D human pose estimation demo.
5354
- [Smart Classroom C++ Demo](./smart_classroom_demo/cpp/README.md) - Face recognition and action detection demo for classroom environment.
5455
- [Sound Classification Python\* Demo](./sound_classification_demo/python/README.md) - Demo application for sound classification algorithm.
55-
- [Super Resolution C++ Demo](./super_resolution_demo/cpp/README.md) - Super Resolution demo (the demo supports only images as inputs). It enhances the resolution of the input image.
5656
- [Text Detection C++ Demo](./text_detection_demo/cpp/README.md) - Text Detection demo. It detects and recognizes multi-oriented scene text on an input image and puts a bounding box around detected area.
5757
- [Text Spotting Python\* Demo](./text_spotting_demo/python/README.md) - The demo demonstrates how to run Text Spotting models.
5858
- [Text-to-speech Python\* Demo](./text_to_speech_demo/python/README.md) - Shows an example of using Forward Tacotron and WaveRNN neural networks for text to speech task.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
// Copyright (C) 2021 Intel Corporation
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writingb software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include "image_model.h"
20+
21+
class DeblurringModel : public ImageModel {
22+
public:
23+
/// Constructor
24+
/// @param modelFileName name of model to load
25+
/// @param inputImgSize size of image to set model input shape
26+
DeblurringModel(const std::string& modelFileName, const cv::Size& inputImgSize);
27+
28+
std::shared_ptr<InternalModelData> preprocess(
29+
const InputData& inputData, InferenceEngine::InferRequest::Ptr& request) override;
30+
std::unique_ptr<ResultBase> postprocess(InferenceResult& infResult) override;
31+
32+
protected:
33+
void prepareInputsOutputs(InferenceEngine::CNNNetwork & cnnNetwork) override;
34+
void changeInputSize(InferenceEngine::CNNNetwork& cnnNetwork);
35+
36+
static const size_t stride = 32;
37+
};

‎demos/common/cpp/models/include/models/results.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,10 @@ struct RetinaFaceDetectionResult : public DetectionResult {
8484
std::vector<cv::Point2f> landmarks;
8585
};
8686

87-
struct SegmentationResult : public ResultBase {
88-
SegmentationResult(int64_t frameId = -1, const std::shared_ptr<MetaData>& metaData = nullptr) :
87+
struct ImageResult : public ResultBase {
88+
ImageResult(int64_t frameId = -1, const std::shared_ptr<MetaData>& metaData = nullptr) :
8989
ResultBase(frameId, metaData) {}
90-
cv::Mat mask;
90+
cv::Mat resultImage;
9191
};
9292

9393
struct HumanPose {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
// Copyright (C) 2021 Intel Corporation
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writingb software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include "image_model.h"
20+
21+
class SuperResolutionModel : public ImageModel {
22+
public:
23+
/// Constructor
24+
/// @param modelFileName name of model to load
25+
SuperResolutionModel(const std::string& modelFileName, const cv::Size& inputImgSize);
26+
27+
std::shared_ptr<InternalModelData> preprocess(
28+
const InputData& inputData, InferenceEngine::InferRequest::Ptr& request) override;
29+
std::unique_ptr<ResultBase> postprocess(InferenceResult& infResult) override;
30+
31+
protected:
32+
void changeInputSize(InferenceEngine::CNNNetwork& cnnNetwork, int coeff);
33+
void prepareInputsOutputs(InferenceEngine::CNNNetwork & cnnNetwork) override;
34+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
// Copyright (C) 2021 Intel Corporation
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
*/
16+
17+
#include "models/deblurring_model.h"
18+
#include "utils/ocv_common.hpp"
19+
#include <utils/slog.hpp>
20+
21+
using namespace InferenceEngine;
22+
23+
DeblurringModel::DeblurringModel(const std::string& modelFileName, const cv::Size& inputImgSize) :
24+
ImageModel(modelFileName, false) {
25+
netInputHeight = inputImgSize.height;
26+
netInputWidth = inputImgSize.width;
27+
}
28+
29+
void DeblurringModel::prepareInputsOutputs(CNNNetwork& cnnNetwork) {
30+
// --------------------------- Configure input & output -------------------------------------------------
31+
// --------------------------- Prepare input blobs ------------------------------------------------------
32+
changeInputSize(cnnNetwork);
33+
34+
ICNNNetwork::InputShapes inputShapes = cnnNetwork.getInputShapes();
35+
if (inputShapes.size() != 1)
36+
throw std::runtime_error("Demo supports topologies only with 1 input");
37+
inputsNames.push_back(inputShapes.begin()->first);
38+
SizeVector& inSizeVector = inputShapes.begin()->second;
39+
if (inSizeVector.size() != 4 || inSizeVector[0] != 1 || inSizeVector[1] != 3)
40+
throw std::runtime_error("3-channel 4-dimensional model's input is expected");
41+
InputInfo& inputInfo = *cnnNetwork.getInputsInfo().begin()->second;
42+
inputInfo.setPrecision(Precision::U8);
43+
44+
// --------------------------- Prepare output blobs -----------------------------------------------------
45+
const OutputsDataMap& outputInfo = cnnNetwork.getOutputsInfo();
46+
if (outputInfo.size() != 1)
47+
throw std::runtime_error("Demo supports topologies only with 1 output");
48+
49+
outputsNames.push_back(outputInfo.begin()->first);
50+
Data& data = *outputInfo.begin()->second;
51+
data.setPrecision(Precision::FP32);
52+
const SizeVector& outSizeVector = data.getTensorDesc().getDims();
53+
if (outSizeVector.size() != 4 || outSizeVector[0] != 1 || outSizeVector[1] != 3)
54+
throw std::runtime_error("3-channel 4-dimensional model's output is expected");
55+
}
56+
57+
void DeblurringModel::changeInputSize(CNNNetwork& cnnNetwork) {
58+
ICNNNetwork::InputShapes inputShapes = cnnNetwork.getInputShapes();
59+
SizeVector& inputDims = inputShapes.begin()->second;
60+
61+
if (inputDims[2] % stride || inputDims[3] % stride)
62+
throw std::runtime_error("The shape of the model input must be divisible by stride");
63+
64+
netInputHeight = static_cast<int>((netInputHeight + stride - 1) / stride) * stride;
65+
netInputWidth = static_cast<int>((netInputWidth + stride - 1) / stride) * stride;
66+
67+
inputDims[0] = 1;
68+
inputDims[2] = netInputHeight;
69+
inputDims[3] = netInputWidth;
70+
71+
cnnNetwork.reshape(inputShapes);
72+
}
73+
74+
std::shared_ptr<InternalModelData> DeblurringModel::preprocess(const InputData& inputData, InferRequest::Ptr& request) {
75+
auto& image = inputData.asRef<ImageInputData>().inputImage;
76+
size_t h = image.rows;
77+
size_t w = image.cols;
78+
cv::Mat resizedImage;
79+
80+
if (netInputHeight - stride < h && h <= netInputHeight
81+
&& netInputWidth - stride < w && w <= netInputWidth) {
82+
int bottom = netInputHeight - h;
83+
int right = netInputWidth - w;
84+
cv::copyMakeBorder(image, resizedImage, 0, bottom, 0, right,
85+
cv::BORDER_CONSTANT, 0);
86+
} else {
87+
slog::warn << "Chosen model aspect ratio doesn't match image aspect ratio\n";
88+
cv::resize(image, resizedImage, cv::Size(netInputWidth, netInputHeight));
89+
}
90+
Blob::Ptr frameBlob = request->GetBlob(inputsNames[0]);
91+
matU8ToBlob<uint8_t>(resizedImage, frameBlob);
92+
93+
return std::make_shared<InternalImageModelData>(image.cols, image.rows);
94+
}
95+
96+
std::unique_ptr<ResultBase> DeblurringModel::postprocess(InferenceResult& infResult) {
97+
ImageResult* result = new ImageResult;
98+
*static_cast<ResultBase*>(result) = static_cast<ResultBase&>(infResult);
99+
100+
const auto& inputImgSize = infResult.internalModelData->asRef<InternalImageModelData>();
101+
102+
LockedMemory<const void> outMapped = infResult.getFirstOutputBlob()->rmap();
103+
const auto outputData = outMapped.as<float*>();
104+
105+
std::vector<cv::Mat> imgPlanes;
106+
const SizeVector& outSizeVector = infResult.getFirstOutputBlob()->getTensorDesc().getDims();
107+
size_t outHeight = (int)(outSizeVector[2]);
108+
size_t outWidth = (int)(outSizeVector[3]);
109+
size_t numOfPixels = outWidth * outHeight;
110+
imgPlanes = std::vector<cv::Mat>{
111+
cv::Mat(outHeight, outWidth, CV_32FC1, &(outputData[0])),
112+
cv::Mat(outHeight, outWidth, CV_32FC1, &(outputData[numOfPixels])),
113+
cv::Mat(outHeight, outWidth, CV_32FC1, &(outputData[numOfPixels * 2]))};
114+
cv::Mat resultImg;
115+
cv::merge(imgPlanes, resultImg);
116+
117+
if (netInputHeight - stride < static_cast<size_t>(inputImgSize.inputImgHeight) && static_cast<size_t>(inputImgSize.inputImgHeight) <= netInputHeight
118+
&& netInputWidth - stride < static_cast<size_t>(inputImgSize.inputImgWidth) && static_cast<size_t>(inputImgSize.inputImgWidth) <= netInputWidth) {
119+
result->resultImage = resultImg(cv::Rect(0, 0, inputImgSize.inputImgWidth, inputImgSize.inputImgHeight));
120+
} else {
121+
cv::resize(resultImg, result->resultImage, cv::Size(inputImgSize.inputImgWidth, inputImgSize.inputImgHeight));
122+
}
123+
124+
result->resultImage.convertTo(result->resultImage, CV_8UC3, 255);
125+
126+
return std::unique_ptr<ResultBase>(result);
127+
}

‎demos/common/cpp/models/src/segmentation_model.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ std::shared_ptr<InternalModelData> SegmentationModel::preprocess(const InputData
8181
/* Just set input blob containing read image. Resize and layout conversionx will be done automatically */
8282
request->SetBlob(inputsNames[0], wrapMat2Blob(img));
8383
/* IE::Blob::Ptr from wrapMat2Blob() doesn't own data. Save the image to avoid deallocation before inference */
84-
resPtr = std::make_shared<InternalImageMatModelData>(img);
84+
resPtr = std::make_shared<InternalImageMatModelData>(img);
8585
}
8686
else
8787
{
@@ -95,20 +95,20 @@ std::shared_ptr<InternalModelData> SegmentationModel::preprocess(const InputData
9595
}
9696

9797
std::unique_ptr<ResultBase> SegmentationModel::postprocess(InferenceResult& infResult) {
98-
SegmentationResult* result = new SegmentationResult(infResult.frameId, infResult.metaData);
98+
ImageResult* result = new ImageResult(infResult.frameId, infResult.metaData);
9999

100100
const auto& inputImgSize = infResult.internalModelData->asRef<InternalImageModelData>();
101101

102102
MemoryBlob::Ptr blobPtr = infResult.getFirstOutputBlob();
103103

104104
void* pData = blobPtr->rmap().as<void*>();
105105

106-
result->mask = cv::Mat(outHeight, outWidth, CV_8UC1);
106+
result->resultImage = cv::Mat(outHeight, outWidth, CV_8UC1);
107107

108108
if (outChannels == 1 && blobPtr->getTensorDesc().getPrecision() == Precision::I32)
109109
{
110110
cv::Mat predictions(outHeight, outWidth, CV_32SC1, pData);
111-
predictions.convertTo(result->mask, CV_8UC1);
111+
predictions.convertTo(result->resultImage, CV_8UC1);
112112
}
113113
else if (blobPtr->getTensorDesc().getPrecision() == Precision::FP32)
114114
{
@@ -129,12 +129,12 @@ std::unique_ptr<ResultBase> SegmentationModel::postprocess(InferenceResult& infR
129129
}
130130
} // nChannels
131131

132-
result->mask.at<uint8_t>(rowId, colId) = classId;
132+
result->resultImage.at<uint8_t>(rowId, colId) = classId;
133133
} // width
134134
} // height
135135
}
136136

137-
cv::resize(result->mask, result->mask,
137+
cv::resize(result->resultImage, result->resultImage,
138138
cv::Size(inputImgSize.inputImgWidth, inputImgSize.inputImgHeight),
139139
0, 0, cv::INTER_NEAREST);
140140

0 commit comments

Comments
 (0)
Please sign in to comment.