OverloadHotspotDetectionAlgorithm.cpp 2.5 KB
#include "OverloadHotspotDetectionAlgorithm.hpp"

#include <algorithm>
#include <opencv2/imgproc.hpp>

void Cpu::OverloadHotspotDetectionAlgorithm::setup(const cv::Size &frameSize,
                                                   const CVMatLoader &loader) {
	currentFrameSize = frameSize;

	hostFov = loader.asMat("/scene_model/FOV", CV_8UC1);

	PfcSegmenter segmenter(loader, frameSize);
	hostPfc = segmenter.segment();

	cv::Mat zerosMask;
	cv::compare(hostPfc, 0, zerosMask, cv::CMP_EQ);
	hostPfc.setTo(MAX_TEMPERATURE, zerosMask);

	cv::Mat model;
	cv::cvtColor(loader.asMat("/scene_model/CAD", CV_8UC1), model,
	             cv::COLOR_GRAY2BGR);

	std::vector<Contours> pfcContours;
	segmenter.contour(pfcContours, hostPfcMask);

	surfaceMap = std::make_unique<const SurfaceMap>(frameSize);
}

void Cpu::OverloadHotspotDetectionAlgorithm::handleFrame(
    const cv::Mat &sourceFrame, unsigned long timestamp) {
	hostFrame = sourceFrame;

	/* Apply field-of-view mask */
	cv::bitwise_and(hostFrame, hostFrame, hostInput, hostFov);
	/* Convert Kelvin to Celsius */
	cv::subtract(hostInput, KELVINS, hostTemperature);

	/* Apply median filter */
	medianBlur(hostTemperature, hostInput, 3);

	/* Threshold overheating pixels */
	cv::compare(hostInput, hostPfc, overheating, cv::CMP_GT);

	currentHotspots.clear();
	identifyHotspots(timestamp);
}

void Cpu::OverloadHotspotDetectionAlgorithm::identifyHotspots(
    unsigned long timestamp) {
	/* Analyse topologial structure */
	Contours hotspotContours;
	cv::findContours(overheating, hotspotContours, cv::RETR_TREE,
	                 cv::CHAIN_APPROX_NONE);

	for (size_t i = 0, size = hotspotContours.size();
	     i < size && i < blobsLimit; ++i) {
		const auto &contour = hotspotContours[i];
		/* Discard blobs below minimum area */
		if (contour.size() >= pixelsThreshold) {
			const int component = hostPfcMask.at<uchar>(contour[0]);
			assert(component > 0);

			Cpu::Hotspot hotspot(hostTemperature, timestamp, component, contour,
			                     surfaceMap->at(contour));

			/* Find corresponding blobs */
			matchHotspot(hotspot);
			currentHotspots.emplace_back(std::move(hotspot));
		}
	}
}

void Cpu::OverloadHotspotDetectionAlgorithm::matchHotspot(
    const Cpu::Hotspot &hotspot) {
	for (auto &persistentHotspot : uniqueHotspots) {
		if (clusterCorrespondence.corresponds(persistentHotspot.mask,
		                                      hotspot.mask)) {
			/* Merge matching blobs */
			persistentHotspot.merge(hotspot);
			return;
		}
	}
	uniqueHotspots.emplace_back(hotspot);
}