#include "ANSANOMALIB.h" namespace ANSCENTER { bool ANSANOMALIB::OptimizeModel(bool fp16, std::string& optimizedModelFolder) { std::lock_guard 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 lock(_mutex); ModelLoadingGuard mlg(_modelLoading); 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 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 lock(_mutex); ModelLoadingGuard mlg(_modelLoading); 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 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 lock(_mutex); ModelLoadingGuard mlg(_modelLoading); 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 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 ANSANOMALIB::RunInference(const cv::Mat& input) { return RunInference(input, "ANSANOMALIBCAM"); } std::vector ANSANOMALIB::RunInference(const cv::Mat& input, const std::string& camera_id) { if (!PreInferenceCheck("ANSANOMALIB::RunInference")) return {}; std::vector 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 model = core.read_model(model_path); if (this->_openvinoPreprocess) { std::vector mean; std::vector 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()); 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()); } else { double _, maxValue; cv::minMaxLoc(anomaly_map, &_, &maxValue); pred_score = cv::Mat(cv::Size(1, 1), CV_32FC1, maxValue); } float preScore = pred_score.at(0, 0); std::vector post_mat = PostProcess(anomaly_map, pred_score, this->_meta); anomaly_map = post_mat[0]; float rawScore = post_mat[1].at(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 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 paths = GetImagePaths(image_dir); for (auto& image_path : paths) { cv::Mat image = ReadImage(image_path); Object result = this->Inference(image); std::vector 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 ANSANOMALIB::GetImagePaths(std::string& path) { try { std::vector paths; cv::glob(path, paths, false); return paths; } catch (std::exception& e) { this->_logger.LogFatal("ANSANOMALIB::GetImagePaths", e.what(), __FILE__, __LINE__); std::vector 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 mean = { 0.485, 0.456, 0.406 }; std::vector 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 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{anomaly_map, pred_score}; } catch (std::exception& e) { this->_logger.LogFatal("ANSANOMALIB::PostProcess", e.what(), __FILE__, __LINE__); std::vector 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 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 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{mask, border, superimposed_map}; } catch (std::exception& e) { this->_logger.LogFatal("ANSANOMALIB::GenImages", e.what(), __FILE__, __LINE__); cv::Mat result; return result; } } }