SurfaceLayerDetectionAlgorithm.cpp 2.67 KB
#include "SurfaceLayerDetectionAlgorithm.hpp"

#include <opencv2/imgproc.hpp>

#include "algorithm/common/PfcSegmenter.hpp"

cv::Mat
Cpu::SurfaceLayerDetectionAlgorithm::setMinimumTemperature(ushort temperature) {
	hostMinTemperature.setTo(temperature);
	return hostMinTemperature;
}

void Cpu::SurfaceLayerDetectionAlgorithm::setup(const cv::Size &frameSize,
                                                const CVMatLoader &loader) {

	hostRegionMask = loader.asMat("/scene_model/FOV", CV_8UC1) &
	                 PfcSegmenter(loader, frameSize).mask("Divertors");

	hostMinTemperature.create(frameSize, CV_16UC1);
	setMinimumTemperature(434);

	hostFloatInput.create(frameSize, CV_32F);
	hostDifference.create(frameSize, CV_32F);
	hostDifference.setTo(cv::Scalar::all(0));

	hostDifferenceAbs.create(frameSize, CV_32F);
	hostDifferenceAbs.setTo(cv::Scalar::all(0));

	hostSurfaceLayers.create(frameSize, CV_8UC1);
	hostSurfaceLayers.setTo(cv::Scalar::all(0));
}

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

	/* Apply median filter */
	cv::medianBlur(hostFrame, hostFiltered, 3);
	/* Apply detection PFC mask */
	cv::bitwise_and(hostFiltered, hostFiltered, hostInput, hostRegionMask);

	/* Trim noise at minimum temperature */
	cv::max(hostInput, hostMinTemperature, hostInput);

	/* Convert to float */
	hostInput.convertTo(hostFloatInput, CV_32F);
	/* Calculate normalized derivative of the temperature evolution */
	normalizedDerivative(); /* Result in hostDifference & hostDifferenceAbs */

	/* Threshold rapidly evolving pixels */
	cv::compare(hostDifferenceAbs, derivativeThreshold, hostResult, cv::CMP_GE);
	/* Merge surface layers */
	cv::bitwise_or(hostResult, hostSurfaceLayers, hostSurfaceLayers);
}

void Cpu::SurfaceLayerDetectionAlgorithm::normalizedDerivative() {
	if (hostPreviousPreviousFrame.empty()) {
		previousPreviousTimestamp = currentTimestamp;
		hostFloatInput.copyTo(hostPreviousPreviousFrame);
		return;
	}
	if (hostPreviousFrame.empty()) {
		previousTimestamp = currentTimestamp;
		hostFloatInput.copyTo(hostPreviousFrame);
		return;
	}

	cv::subtract(hostFloatInput, hostPreviousPreviousFrame, hostDifference);
	cv::multiply(hostDifference,
	             cv::Scalar::all(
	                 (currentTimestamp - previousPreviousTimestamp) * NS_TO_S),
	             hostDifference);
	cv::divide(hostDifference, hostPreviousFrame, hostDifference);
	hostDifferenceAbs = cv::abs(hostDifference);

	previousPreviousTimestamp = previousTimestamp;
	previousTimestamp = currentTimestamp;

	hostPreviousFrame.copyTo(hostPreviousPreviousFrame);
	hostFloatInput.copyTo(hostPreviousFrame);
}