ClusterCorrespondence.hpp 1.94 KB
/* Analysis of the outer divertor hot spot activity in the protection video
camera recordings at JET */
#pragma once

#include <opencv2/cudaarithm.hpp>

class ClusterCorrespondence {
  public:
	ClusterCorrespondence(float minOverlap, float maxOversize)
	    : minOverlap(minOverlap), maxOversize(maxOversize) {}

	bool corresponds(const cv::cuda::GpuMat &first,
	                 const cv::cuda::GpuMat &second) {
		cv::cuda::bitwise_and(first, second, overlap, cv::noArray(),
		                      overlapStream);
		cv::cuda::countNonZero(first, deviceFirstArea, firstStream);
		cv::cuda::countNonZero(second, deviceSecondArea, secondStream),
		    cv::cuda::countNonZero(overlap, deviceOverlapArea, overlapStream);

		deviceFirstArea.download(hostFirstArea, firstStream);
		deviceSecondArea.download(hostSecondArea, secondStream);
		deviceOverlapArea.download(hostOverlapArea, overlapStream);

		firstStream.waitForCompletion();
		secondStream.waitForCompletion();
		overlapStream.waitForCompletion();
		return meetsCriteria(hostFirstArea.at<int>(0),
		                     hostSecondArea.at<int>(0),
		                     hostOverlapArea.at<int>(0));
	}

  private:
	float minOverlap;
	float maxOversize;

	bool meetsCriteria(int firstArea, int secondArea, int overlapArea) const {
		return isOverlapping(firstArea, secondArea, overlapArea) &&
		       isSimilar(firstArea, secondArea);
	}

	bool isOverlapping(int firstArea, int secondArea, int overlapArea) const {
		return overlapArea >= minOverlap * std::min(firstArea, secondArea);
	}

	bool isSimilar(int firstArea, int secondArea) const {
		return (firstArea / static_cast<float>(secondArea) >=
		        1.F / maxOversize) &&
		       (firstArea / static_cast<float>(secondArea) <= maxOversize);
	}

	/* Buffors */
	cv::cuda::Stream firstStream, secondStream, overlapStream;
	cv::cuda::GpuMat overlap, deviceFirstArea, deviceSecondArea,
	    deviceOverlapArea;
	cv::Mat hostFirstArea, hostSecondArea, hostOverlapArea;
};