Files
ANSCORE/modules/ANSODEngine/ANSANOMALIB.cpp

699 lines
25 KiB
C++
Raw Normal View History

2026-03-28 16:54:11 +11:00
#include "ANSANOMALIB.h"
namespace ANSCENTER {
bool ANSANOMALIB::OptimizeModel(bool fp16, std::string& optimizedModelFolder) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
if (!ANSODBase::OptimizeModel(fp16, optimizedModelFolder)) {
return false;
}
if (FileExist(_modelFilePath)) {
std::string modelName = GetFileNameWithoutExtension(_modelFilePath);
std::string binaryModelName = modelName + ".bin";
std::string modelFolder = GetParentFolder(_modelFilePath);
std::string optimizedModelPath = CreateFilePath(modelFolder, binaryModelName);
if (FileExist(optimizedModelPath)) {
this->_logger.LogDebug("ANSANOMALIB::OptimizeModel", "This model is optimized. No need other optimization.", __FILE__, __LINE__);
optimizedModelFolder = modelFolder;
return true;
}
else {
this->_logger.LogFatal("ANSANOMALIB::OptimizeModel", "This model can not be optimized.", __FILE__, __LINE__);
optimizedModelFolder = modelFolder;
return false;
}
}
else {
this->_logger.LogFatal("ANSANOMALIB::OptimizeModel", "This model is not exist. Please check the model path again.", __FILE__, __LINE__);
optimizedModelFolder = "";
return false;
}
}
bool ANSANOMALIB::LoadModel(const std::string& modelZipFilePath, const std::string& modelZipPassword) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
2026-04-13 19:48:32 +10:00
ModelLoadingGuard mlg(_modelLoading);
2026-03-28 16:54:11 +11:00
try {
bool result = ANSODBase::LoadModel(modelZipFilePath, modelZipPassword);
if (!result) return false;
_device = "AUTO:GPU,CPU";
_openvinoPreprocess = true;
_efficientAd = false;
// 0. Check if the configuration file exist
if (FileExist(_modelConfigFile)) {
ModelType modelType;
std::vector<int> inputShape;
_classes = ANSUtilityHelper::GetConfigFileContent(_modelConfigFile, modelType, inputShape);
if (inputShape.size() == 2) {
if (inputShape[0] > 0)_modelConfig.inpHeight = inputShape[0];
if (inputShape[1] > 0)_modelConfig.inpWidth = inputShape[1];
}
}
else {// This is old version of model zip file
std::string xmlfile = CreateFilePath(_modelFolder, "model.xml");
std::string metafile = CreateFilePath(_modelFolder, "metadata.json");
std::string binaryfile = CreateFilePath(_modelFolder, "model.bin");
if (std::filesystem::exists(xmlfile)) {
_modelFilePath = xmlfile;
_metaFilePath = metafile;
this->_logger.LogDebug("ANSANOMALIB::Initialize. Loading OpenVINO weight", _modelFilePath, __FILE__, __LINE__);
if (FileExist(_metaFilePath)) {
this->_logger.LogDebug("ANSANOMALIB::Initialize. Loading meta data", _metaFilePath, __FILE__, __LINE__);
if (FileExist(binaryfile)) {
this->_logger.LogDebug("ANSANOMALIB::Initialize. Loading binary model", binaryfile, __FILE__, __LINE__);
}
else {
this->_logger.LogError("ANSANOMALIB::Initialize. Binary model file does not exit", binaryfile, __FILE__, __LINE__);
return false;
}
}
else {
this->_logger.LogError("ANSANOMALIB::Initialize. Meta data file does not exist", _metaFilePath, __FILE__, __LINE__);
return false;
}
}
else {
this->_logger.LogError("ANSANOMALIB::Initialize. Model file does not exist", _modelFilePath, __FILE__, __LINE__);
return false;
}
}
// Load Model from Here
InitModel(_modelFilePath, _metaFilePath, _device, _openvinoPreprocess, _efficientAd);
_isInitialized = true;
return true;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::LoadModel", e.what(), __FILE__, __LINE__);
return false;
}
}
bool ANSANOMALIB::LoadModelFromFolder(std::string licenseKey, ModelConfig modelConfig, std::string modelName, std::string className, const std::string& modelFolder, std::string& labelMap) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
2026-04-13 19:48:32 +10:00
ModelLoadingGuard mlg(_modelLoading);
2026-03-28 16:54:11 +11:00
try {
bool result = ANSODBase::LoadModelFromFolder(licenseKey, modelConfig, modelName, className, modelFolder, labelMap);
if (!result) return false;
std::string _modelName = modelName;
if (_modelName.empty()) {
_modelName = "model";
}
std::string xmlfileName = _modelName + ".xml";
std::string binfileName = _modelName + ".bin";
_modelConfig = modelConfig;
_modelConfig.detectionType = ANSCENTER::DetectionType::SEGMENTATION;
_modelConfig.modelType = ModelType::ANOMALIB;
_modelConfig.inpHeight = 640;
_modelConfig.inpWidth = 640;
if (_modelConfig.modelMNSThreshold < 0.2)
_modelConfig.modelMNSThreshold = 0.5;
if (_modelConfig.modelConfThreshold < 0.2)
_modelConfig.modelConfThreshold = 0.5;
_openvinoPreprocess = true;
_efficientAd = false;
_device = "AUTO:GPU,CPU";
// 0. Check if the configuration file exist
if (FileExist(_modelConfigFile)) {
ModelType modelType;
std::vector<int> inputShape;
_classes = ANSUtilityHelper::GetConfigFileContent(_modelConfigFile, modelType, inputShape);
if (inputShape.size() == 2) {
if (inputShape[0] > 0)_modelConfig.inpHeight = inputShape[0];
if (inputShape[1] > 0)_modelConfig.inpWidth = inputShape[1];
}
}
else {// This is old version of model zip file
std::string xmlfile = CreateFilePath(_modelFolder, xmlfileName);
std::string metafile = CreateFilePath(_modelFolder, "metadata.json");
std::string binaryfile = CreateFilePath(_modelFolder, binfileName);
if (std::filesystem::exists(xmlfile)) {
_modelFilePath = xmlfile;
_metaFilePath = metafile;
this->_logger.LogDebug("ANSANOMALIB::Initialize. Loading OpenVINO weight", _modelFilePath, __FILE__, __LINE__);
if (FileExist(_metaFilePath)) {
this->_logger.LogDebug("ANSANOMALIB::Initialize. Loading meta data", _metaFilePath, __FILE__, __LINE__);
if (FileExist(binaryfile)) {
this->_logger.LogDebug("ANSANOMALIB::Initialize. Loading binary model", binaryfile, __FILE__, __LINE__);
}
else {
this->_logger.LogError("ANSANOMALIB::Initialize. Binary model file does not exit", binaryfile, __FILE__, __LINE__);
return false;
}
}
else {
this->_logger.LogError("ANSANOMALIB::Initialize. Meta data file does not exist", _metaFilePath, __FILE__, __LINE__);
return false;
}
}
else {
this->_logger.LogError("ANSANOMALIB::Initialize. Model file does not exist", _modelFilePath, __FILE__, __LINE__);
return false;
}
}
// Load Model from Here
InitModel(_modelFilePath, _metaFilePath, _device, _openvinoPreprocess, _efficientAd);
labelMap = "Normal,Defect";
_isInitialized = true;
return true;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::LoadModel", e.what(), __FILE__, __LINE__);
return false;
}
}
bool ANSANOMALIB::Initialize(std::string licenseKey, ModelConfig modelConfig, const std::string& modelZipFilePath, const std::string& modelZipPassword, std::string& labelMap) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
2026-04-13 19:48:32 +10:00
ModelLoadingGuard mlg(_modelLoading);
2026-03-28 16:54:11 +11:00
try {
std::string openVINOVersion = ov::get_openvino_version().buildNumber;
//this->_logger.LogDebug("ANSANOMALIB::Initialize. OpenVINO version", openVINOVersion, __FILE__, __LINE__);
bool result = ANSODBase::Initialize(licenseKey, modelConfig, modelZipFilePath, modelZipPassword, labelMap);
if (!result) return false;
// Parsing for ABNORMAL only here
_modelConfig = modelConfig;
_modelConfig.detectionType = ANSCENTER::DetectionType::SEGMENTATION;
_modelConfig.modelType = ModelType::ANOMALIB;
_modelConfig.inpHeight = 640;
_modelConfig.inpWidth = 640;
if (_modelConfig.modelMNSThreshold < 0.2)
_modelConfig.modelMNSThreshold = 0.5;
if (_modelConfig.modelConfThreshold < 0.2)
_modelConfig.modelConfThreshold = 0.5;
_openvinoPreprocess = true;
_efficientAd = false;
_device = "AUTO:GPU,CPU";
// 0. Check if the configuration file exist
if (FileExist(_modelConfigFile)) {
ModelType modelType;
std::vector<int> inputShape;
_classes = ANSUtilityHelper::GetConfigFileContent(_modelConfigFile, modelType, inputShape);
if (inputShape.size() == 2) {
if (inputShape[0] > 0)_modelConfig.inpHeight = inputShape[0];
if (inputShape[1] > 0)_modelConfig.inpWidth = inputShape[1];
}
}
else {// This is old version of model zip file
std::string xmlfile = CreateFilePath(_modelFolder, "model.xml");
std::string metafile = CreateFilePath(_modelFolder, "metadata.json");
std::string binaryfile = CreateFilePath(_modelFolder, "model.bin");
if (std::filesystem::exists(xmlfile)) {
_modelFilePath = xmlfile;
_metaFilePath = metafile;
this->_logger.LogDebug("ANSANOMALIB::Initialize. Loading OpenVINO weight", _modelFilePath, __FILE__, __LINE__);
if (FileExist(_metaFilePath)) {
this->_logger.LogDebug("ANSANOMALIB::Initialize. Loading meta data", _metaFilePath, __FILE__, __LINE__);
if (FileExist(binaryfile)) {
this->_logger.LogDebug("ANSANOMALIB::Initialize. Loading binary model", binaryfile, __FILE__, __LINE__);
}
else {
this->_logger.LogError("ANSANOMALIB::Initialize. Binary model file does not exit", binaryfile, __FILE__, __LINE__);
return false;
}
}
else {
this->_logger.LogError("ANSANOMALIB::Initialize. Meta data file does not exist", _metaFilePath, __FILE__, __LINE__);
return false;
}
}
else {
this->_logger.LogError("ANSANOMALIB::Initialize. Model file does not exist", _modelFilePath, __FILE__, __LINE__);
return false;
}
}
// Load Model from Here
InitModel(_modelFilePath, _metaFilePath, _device, _openvinoPreprocess, _efficientAd);
labelMap = "Normal,Defect";
_isInitialized = true;
return true;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::Initialize", e.what(), __FILE__, __LINE__);
labelMap = "Normal,Defect";
return false;
}
}
std::vector<Object> ANSANOMALIB::RunInference(const cv::Mat& input) {
return RunInference(input, "ANSANOMALIBCAM");
}
std::vector<Object> ANSANOMALIB::RunInference(const cv::Mat& input, const std::string& camera_id) {
2026-04-13 19:48:32 +10:00
if (!PreInferenceCheck("ANSANOMALIB::RunInference")) return {};
2026-03-28 16:54:11 +11:00
std::vector<Object> output;
output.clear();
if (!_licenseValid) {
this->_logger.LogError("ANSANOMALIB::RunInference", "Invalid License", __FILE__, __LINE__);
return output;
}
if (!_isInitialized) {
this->_logger.LogError("ANSANOMALIB::RunInference", "Model is not initialized", __FILE__, __LINE__);
return output;
}
try {
if (input.empty()) return output;
if ((input.cols < 10) || (input.rows < 10)) return output;
cv::Mat frame = input;
Object result = InferenceSingleImage(frame);
result.cameraId = camera_id;
output.push_back(result);
//EnqueueDetection(output, camera_id);
return output;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::RunInference", e.what(), __FILE__, __LINE__);
return output;
}
}
ANSANOMALIB::~ANSANOMALIB() {
try {
//this->_logger.LogDebug("ANSANOMALIB::~ANSANOMALIB()", "Release ANSANOMALIB ", __FILE__, __LINE__);
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::~ANSANOMALIB()", e.what(), __FILE__, __LINE__);
}
}
bool ANSANOMALIB::Destroy() {
try {
//this->_logger.LogDebug("ANSANOMALIB::Destroy", "Release ANSANOMALIB ", __FILE__, __LINE__);
return true;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::Destroy", e.what(), __FILE__, __LINE__);
return false;
}
}
// Private
void ANSANOMALIB::InitModel(std::string& model_path,
std::string& meta_path,
std::string& device,
bool openvino_preprocess,
bool efficient_ad) {
try {
this->_efficientAd = efficient_ad;
this->_openvinoPreprocess = openvino_preprocess;
this->_meta = ANSUtilityHelper::GetJson(meta_path);
this->GetModel(model_path, device);
this->_inputs = this->_compiledModel.inputs();
this->_outputs = this->_compiledModel.outputs();
for (auto input : this->_inputs) {
std::cout << "Input: " << input.get_any_name() << ": [ ";
for (auto j : input.get_shape()) {
std::cout << j << " ";
}
std::cout << "] ";
std::cout << "dtype: " << input.get_element_type() << std::endl;
}
for (auto output : this->_outputs) {
std::cout << "Output: " << output.get_any_name() << ": [ ";
for (auto j : output.get_shape()) {
std::cout << j << " ";
}
std::cout << "] ";
std::cout << "dtype: " << output.get_element_type() << std::endl;
}
this->_inferRequest = this->_compiledModel.create_infer_request();
//this->WarmUp();
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::InitModel", e.what(), __FILE__, __LINE__);
}
}
void ANSANOMALIB::GetModel(std::string& model_path, std::string& device) {
try {
// Step 1. Initialize OpenVINO Runtime core
ov::Core core;
// Step 2. Read a Model from a Drive
std::shared_ptr<ov::Model> model = core.read_model(model_path);
if (this->_openvinoPreprocess) {
std::vector<float> mean;
std::vector<float> std;
if (!this->_efficientAd) {
mean = { this->_meta._mean[0] * 255, this->_meta._mean[1] * 255, this->_meta._mean[2] * 255 };
std = { this->_meta._std[0] * 255, this->_meta._std[1] * 255, this->_meta._std[2] * 255 };
}
else {
mean = { 0., 0., 0. };
std = { 255., 255., 255. };
}
// Step 3. Inizialize Preprocessing for the model
// https://mp.weixin.qq.com/s/4lkDJC95at2tK_Zd62aJxw
// https://blog.csdn.net/sandmangu/article/details/107181289
// https://docs.openvino.ai/latest/openvino_2_0_preprocessing.html
ov::preprocess::PrePostProcessor ppp = ov::preprocess::PrePostProcessor(model);
// Specify input image format
ppp.input(0).tensor()
.set_color_format(ov::preprocess::ColorFormat::RGB) // BGR -> RGB
.set_element_type(ov::element::u8)
.set_layout(ov::Layout("HWC")); // HWC NHWC NCHW
// Specify preprocess pipeline to input image without resizing
ppp.input(0).preprocess()
// .convert_color(ov::preprocess::ColorFormat::RGB)
.convert_element_type(ov::element::f32)
.mean(mean)
.scale(std);
// Specify model's input layout
ppp.input(0).model().set_layout(ov::Layout("NCHW"));
// Specify output results format
for (size_t i = 0; i < model->outputs().size(); i++) {
ppp.output(i).tensor().set_element_type(ov::element::f32);
}
// Embed above steps in the graph
model = ppp.build();
}
// Step 4. Load the Model to the Device
this->_compiledModel = core.compile_model(model, device,
ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT),
ov::inference_num_threads(4));
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::GetModel", e.what(), __FILE__, __LINE__);
}
}
void ANSANOMALIB::WarmUp() {
try {
cv::Size size = cv::Size(this->_meta.inferSize[1], this->_meta.inferSize[0]);
cv::Scalar color = cv::Scalar(0, 0, 0);
cv::Mat input = cv::Mat(size, CV_8UC3, color);
this->Inference(input);
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::WarmUp", e.what(), __FILE__, __LINE__);
}
}
Object ANSANOMALIB::Inference(cv::Mat& image) {
try {
Object result;
cv::Mat blob;
if (image.empty())return result;
if ((image.cols <= 5) || (image.rows <= 5))return result;
cv::Mat processedImage;
if (image.channels() == 1) {
cv::cvtColor(image, processedImage, cv::COLOR_GRAY2BGR);
}
else {
processedImage = image;
}
this->_meta.imageSize[0] = processedImage.size().height;
this->_meta.imageSize[1] = processedImage.size().width;
cv::cvtColor(processedImage, processedImage, cv::ColorConversionCodes::COLOR_BGR2RGB); // BGR2RGB
if (this->_openvinoPreprocess) {
cv::resize(processedImage, blob, { this->_meta.inferSize[0], this->_meta.inferSize[1] });
}
else {
blob = PreProcess(processedImage, this->_meta, this->_efficientAd);
blob = cv::dnn::blobFromImage(blob); // [H, W, C] -> [N, C, H, W]
}
ov::Tensor input_tensor = ov::Tensor(this->_compiledModel.input(0).get_element_type(),
this->_compiledModel.input(0).get_shape(), (float*)blob.data);
this->_inferRequest.set_input_tensor(input_tensor);
this->_inferRequest.infer();
ov::Tensor result1;
result1 = this->_inferRequest.get_output_tensor(0);
cv::Mat anomaly_map = cv::Mat(cv::Size(this->_meta.inferSize[1], this->_meta.inferSize[0]), CV_32FC1, result1.data<float>());
cv::Mat pred_score;
if (this->_outputs.size() == 2) {
ov::Tensor result2 = this->_inferRequest.get_output_tensor(1);
pred_score = cv::Mat(cv::Size(1, 1), CV_32FC1, result2.data<float>());
}
else {
double _, maxValue;
cv::minMaxLoc(anomaly_map, &_, &maxValue);
pred_score = cv::Mat(cv::Size(1, 1), CV_32FC1, maxValue);
}
float preScore = pred_score.at<float>(0, 0);
std::vector<cv::Mat> post_mat = PostProcess(anomaly_map, pred_score, this->_meta);
anomaly_map = post_mat[0];
float rawScore = post_mat[1].at<float>(0, 0);
float score = rawScore;
if (preScore >= this->_meta.imageThreshold) {
result.classId = 1;
result.className = "Defect";
}
else {
result.classId = 0;
score = 1 - rawScore;
result.className = "Normal";
}
result.box.x = 5;
result.box.y = 5;
result.box.width = this->_meta.imageSize[0] - 5;
result.box.height = this->_meta.imageSize[1] - 5;
result.polygon = ANSUtilityHelper::RectToNormalizedPolygon(result.box, processedImage.cols, processedImage.rows);
result.confidence = score;
result.mask = anomaly_map;
result.extraInfo = "";
return result;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::Inference", e.what(), __FILE__, __LINE__);
Object result;
return result;
}
}
Object ANSANOMALIB::InferenceSingleImage(cv::Mat& image) {
try {
Object result = this->Inference(image);
std::vector<cv::Mat> images = GenImages(image, result.mask, result.confidence);
cv::applyColorMap(images[0], images[0], cv::ColormapTypes::COLORMAP_JET);
cv::Mat res;
cv::hconcat(images, res);
result.mask = res;
return result;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::InferenceSingleImage", e.what(), __FILE__, __LINE__);
Object result;
return result;
}
}
void ANSANOMALIB::InferenceMultiImages(std::string& image_dir, std::string& save_dir) {
try {
std::vector<cv::String> paths = GetImagePaths(image_dir);
for (auto& image_path : paths) {
cv::Mat image = ReadImage(image_path);
Object result = this->Inference(image);
std::vector<cv::Mat> images = GenImages(image, result.mask, result.confidence);
cv::applyColorMap(images[0], images[0], cv::ColormapTypes::COLORMAP_JET);
cv::Mat res;
cv::hconcat(images, res);
SaveScoreAndImages(result.confidence, res, image_path, save_dir);
}
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::InferenceMultiImages", e.what(), __FILE__, __LINE__);
}
}
std::vector<cv::String> ANSANOMALIB::GetImagePaths(std::string& path) {
try {
std::vector<cv::String> paths;
cv::glob(path, paths, false);
return paths;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::GetImagePaths", e.what(), __FILE__, __LINE__);
std::vector<cv::String> paths;
paths.clear();
return paths;
}
}
cv::Mat ANSANOMALIB::ReadImage(std::string& path) {
try {
auto image = cv::imread(path, cv::ImreadModes::IMREAD_COLOR);
cv::cvtColor(image, image, cv::ColorConversionCodes::COLOR_BGR2RGB);
return image;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::ReadImage", e.what(), __FILE__, __LINE__);
cv::Mat result;
return result;
}
}
void ANSANOMALIB::SaveScoreAndImages(float score, cv::Mat image,
cv::String& image_path, std::string& save_dir) {
try {
auto start = image_path.rfind('\\');
if (start < 0 || start > image_path.length()) {
start = image_path.rfind('/');
}
auto end = image_path.substr(start + 1).rfind('.');
auto image_name = image_path.substr(start + 1).substr(0, end);
std::ofstream ofs;
ofs.open(save_dir + "/" + image_name + ".txt", std::ios::out);
ofs << score;
ofs.close();
cv::imwrite(save_dir + "/" + image_name + ".jpg", image);
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::SaveScoreAndImages", e.what(), __FILE__, __LINE__);
}
}
cv::Mat ANSANOMALIB::PreProcess(cv::Mat& image, MetaData& meta, bool efficient_ad) {
try {
std::vector<float> mean = { 0.485, 0.456, 0.406 };
std::vector<float> std = { 0.229, 0.224, 0.225 };
cv::Mat resized_image = ANSUtilityHelper::Resize(image, meta.inferSize[0], meta.inferSize[1], "bilinear");
resized_image.convertTo(resized_image, CV_32FC3, 1.0 / 255, 0);
if (!efficient_ad) {
resized_image = ANSUtilityHelper::Normalize(resized_image, mean, std);
}
return resized_image;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::PreProcess", e.what(), __FILE__, __LINE__);
cv::Mat result;
return result;
}
}
cv::Mat ANSANOMALIB::NormalizeMinMax(cv::Mat& targets, float threshold, float min_val, float max_val) {
try {
cv::Mat normalized = ((targets - threshold) / (max_val - min_val)) + 0.5;
cv::threshold(normalized, normalized, 1, 1, cv::ThresholdTypes::THRESH_TRUNC);
cv::threshold(normalized, normalized, 0, 0, cv::ThresholdTypes::THRESH_TOZERO);
return normalized;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::NormalizeMinMax", e.what(), __FILE__, __LINE__);
cv::Mat result;
return result;
}
}
std::vector<cv::Mat> ANSANOMALIB::PostProcess(cv::Mat& anomaly_map, cv::Mat& pred_score, MetaData& meta) {
try {
anomaly_map = NormalizeMinMax(anomaly_map, meta.pixelThreshold, meta.min, meta.max);
pred_score = NormalizeMinMax(pred_score, meta.imageThreshold, meta.min, meta.max);
anomaly_map = ANSUtilityHelper::Resize(anomaly_map, meta.imageSize[0], meta.imageSize[1], "bilinear");
return std::vector<cv::Mat>{anomaly_map, pred_score};
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::PostProcess", e.what(), __FILE__, __LINE__);
std::vector<cv::Mat> result;
result.clear();
return result;
}
}
cv::Mat ANSANOMALIB::SuperimposeAnomalyMap(cv::Mat& anomaly_map, cv::Mat& origin_image) {
try {
auto anomaly = anomaly_map.clone();
double minValue, maxValue;
cv::minMaxLoc(anomaly, &minValue, &maxValue);
anomaly = (anomaly - minValue) / (maxValue - minValue);
anomaly.convertTo(anomaly, CV_8UC1, 255, 0);
cv::applyColorMap(anomaly, anomaly, cv::ColormapTypes::COLORMAP_JET);
cv::Mat combine;
cv::addWeighted(anomaly, 0.4, origin_image, 0.6, 0, combine);
return combine;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::SuperimposeAnomalyMap", e.what(), __FILE__, __LINE__);
cv::Mat result;
return result;
}
}
cv::Mat ANSANOMALIB::AddLabel(cv::Mat& mixed_image, float score, int font) {
try {
std::string text = "Confidence Score " + std::to_string(score);
int font_size = mixed_image.cols / 1024 + 1;
int baseline = 0;
int thickness = font_size / 2;
cv::Size textsize = cv::getTextSize(text, font, font_size, thickness, &baseline);
cv::rectangle(mixed_image, cv::Point(0, 0), cv::Point(textsize.width + 10, textsize.height + 10),
cv::Scalar(225, 252, 134), cv::FILLED);
cv::putText(mixed_image, text, cv::Point(0, textsize.height + 10), font, font_size,
cv::Scalar(0, 0, 0), thickness);
return mixed_image;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::AddLabel", e.what(), __FILE__, __LINE__);
cv::Mat result;
return result;
}
}
cv::Mat ANSANOMALIB::ComputeMask(cv::Mat& anomaly_map, float threshold, int kernel_size) {
try {
cv::Mat mask = anomaly_map.clone();
cv::threshold(mask, mask, threshold, 1, cv::ThresholdTypes::THRESH_BINARY);
auto kernel = cv::getStructuringElement(cv::MorphShapes::MORPH_ELLIPSE, { kernel_size, kernel_size }, { -1, -1 });
cv::morphologyEx(mask, mask, cv::MorphTypes::MORPH_OPEN, kernel, { -1, -1 }, 1);
mask.convertTo(mask, CV_8UC1, 255, 0);
return mask;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::ComputeMask", e.what(), __FILE__, __LINE__);
cv::Mat result;
return result;
}
}
cv::Mat ANSANOMALIB::GenMaskBorder(cv::Mat& mask, cv::Mat& image) {
try {
cv::Mat b = cv::Mat::zeros(mask.size[0], mask.size[1], CV_8UC1);
cv::Mat g = b.clone();
cv::Mat r = b.clone();
cv::Canny(mask, r, 128, 255, 3, false);
std::vector<cv::Mat> rgb{ b, g, r };
cv::Mat border;
cv::merge(rgb, border);
cv::addWeighted(border, 0.4, image, 0.6, 0, border);
return border;
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::GenMaskBorder", e.what(), __FILE__, __LINE__);
cv::Mat result;
return result;
}
}
std::vector<cv::Mat> ANSANOMALIB::GenImages(cv::Mat& image, cv::Mat& anomaly_map, float score, float threshold) {
try {
cv::cvtColor(image, image, cv::ColorConversionCodes::COLOR_RGB2BGR);
cv::Mat mask = ComputeMask(anomaly_map, threshold);
cv::Mat border = GenMaskBorder(mask, image);
cv::Mat superimposed_map = SuperimposeAnomalyMap(anomaly_map, image);
superimposed_map = AddLabel(superimposed_map, score);
return std::vector<cv::Mat>{mask, border, superimposed_map};
}
catch (std::exception& e) {
this->_logger.LogFatal("ANSANOMALIB::GenImages", e.what(), __FILE__, __LINE__);
cv::Mat result;
return result;
}
}
}