<commit_before>#include "CueDetector.h"

CueDetector::CueDetector()
{
	cueLine.resize(2);
}

CueDetector::~CueDetector()
{
}

cv::vector<cv::Vec2i> CueDetector::detect(cv::Mat frame)
{
	// Reset cueLines.
	cueLine[0] = cv::Vec2i(0, 0);
	cueLine[1] = cv::Vec2i(0, 0);

	cv::Mat croppedFrame = frame.clone(); // copy so we don't overwrite the user's view with GaussianBlur's blur call.
	croppedFrame = croppedFrame(cv::Rect(CROP_X, CROP_Y, CROP_WIDTH, CROP_HEIGHT)); // Crop the image for the typical location of the cue.
	GaussianBlur(croppedFrame);
	hsiSegment(croppedFrame);
	skeleton(croppedFrame);
	//regHoughLines(croppedFrame, 120);
	probHoughLinesCueSegments(croppedFrame);

	cv::line(frame, cv::Point(cueLine[0][0], cueLine[0][1]), cv::Point(cueLine[1][0], cueLine[1][1]), cv::Scalar(0, 0, 255), 3, CV_AA);

	return cueLine;
}

void CueDetector::probHoughLinesCueSegments(cv::Mat& frame) {
	// Finds segments of a cue interrupted by a hand.
	cv::vector<cv::Vec4i> lines;
	HoughLinesP(frame, lines, 1, CV_PI / 180, HOUGH_THRESHOLD, CUE_SEGMENT_MIN_LENGTH, CUE_SEGMENT_MAX_GAP);

	cv::Mat houghMap(frame.size(), CV_8UC1, cv::Scalar(0));

	for (size_t i = 0; i < lines.size(); i++)
	{
		line(houghMap, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), cv::Scalar(255), 1, CV_AA);
	}

	mergeCueSegments(houghMap);

	frame = houghMap.clone();
}

void CueDetector::mergeCueSegments(cv::Mat& frame)
{
	// combines two cue segments into a single line segment.
	cv::vector<cv::Vec4i> lines;
	HoughLinesP(frame, lines, 1, CV_PI / 180, 50, 25, 100);


	// Calculate the lengths of all lines.
	int maxLengthIndex = -1;
	int maxSquaredLength = -1;
	cv::Mat houghMap(frame.size(), CV_8UC3, cv::Scalar(0));
	for (size_t i = 0; i < lines.size(); i++)
	{
		line(houghMap, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), cv::Scalar(255, 255, 255), 1, CV_AA);
		int squaredLength = (lines[i][0] - lines[i][2]) + (lines[i][1] - lines[i][3]);

		if (squaredLength > maxSquaredLength)
		{
			maxSquaredLength = squaredLength;
			maxLengthIndex = i;

			// Convert cropped coords to global coords.
			cueLine[0] = cv::Vec2i(lines[i][0] + CROP_X, lines[i][1] + CROP_Y);
			cueLine[1] = cv::Vec2i(lines[i][2] + CROP_X, lines[i][3] + CROP_Y);
		}
	}
}

void CueDetector::hsiSegment(cv::Mat& frame)
{
	//Can be used to control with trackbars the values
	int minH = 22;
	int maxH = 62;

	int minS = 14;
	int maxS = 166;

	int minV = 215;
	int maxV = 255;

	cv::Mat hsvFrame;

	cvtColor(frame, hsvFrame, cv::COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV

	cv::Mat hsvMask;

	inRange(hsvFrame, cv::Scalar(minH, minS, minV), cv::Scalar(maxH, maxS, maxV), hsvMask); //Threshold the image

	//Used to make the mask bigger (For our specific situation we want to make sure the mask
	//includes the whole pool table, having it a bit bigger thant he pool table is not an issue.
	dilate(hsvMask, hsvMask, getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(4, 4)));

	cv::Mat maskedFrame;
	frame.copyTo(maskedFrame, hsvMask);
	frame = maskedFrame.clone();
}

void CueDetector::GaussianBlur(cv::Mat& frame)
{
	//int display_dst(int delay);
	for (int i = 1; i < 7; i = i + 2)
	{
		cv::blur(frame, frame, cv::Size(i, i), cv::Point(-1, -1));
	}
}

void CueDetector::skeleton(cv::Mat& frame)
{
	// http://stackoverflow.com/questions/16665742/a-good-approach-for-detecting-lines-in-an-image<commit_msg>Increased tolerance for HSI-segmenting CueDetector  - tip of cue was filtering cue tip of the deflated pocket marker test video in the Hue and Saturation channels<commit_after>#include "CueDetector.h"

CueDetector::CueDetector()
{
	cueLine.resize(2);
}

CueDetector::~CueDetector()
{
}

cv::vector<cv::Vec2i> CueDetector::detect(cv::Mat frame)
{
	// Reset cueLines.
	cueLine[0] = cv::Vec2i(0, 0);
	cueLine[1] = cv::Vec2i(0, 0);

	cv::Mat croppedFrame = frame.clone(); // copy so we don't overwrite the user's view with GaussianBlur's blur call.
	croppedFrame = croppedFrame(cv::Rect(CROP_X, CROP_Y, CROP_WIDTH, CROP_HEIGHT)); // Crop the image for the typical location of the cue.
	GaussianBlur(croppedFrame);
	hsiSegment(croppedFrame);
	skeleton(croppedFrame);
	//regHoughLines(croppedFrame, 120);
	probHoughLinesCueSegments(croppedFrame);

	cv::line(frame, cv::Point(cueLine[0][0], cueLine[0][1]), cv::Point(cueLine[1][0], cueLine[1][1]), cv::Scalar(0, 0, 255), 3, CV_AA);

	return cueLine;
}

void CueDetector::probHoughLinesCueSegments(cv::Mat& frame) {
	// Finds segments of a cue interrupted by a hand.
	cv::vector<cv::Vec4i> lines;
	HoughLinesP(frame, lines, 1, CV_PI / 180, HOUGH_THRESHOLD, CUE_SEGMENT_MIN_LENGTH, CUE_SEGMENT_MAX_GAP);

	cv::Mat houghMap(frame.size(), CV_8UC1, cv::Scalar(0));

	for (size_t i = 0; i < lines.size(); i++)
	{
		line(houghMap, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), cv::Scalar(255), 1, CV_AA);
	}

	mergeCueSegments(houghMap);

	imshow("Cue Segments", houghMap);

	frame = houghMap.clone();
}

void CueDetector::mergeCueSegments(cv::Mat& frame)
{
	// combines two cue segments into a single line segment.
	cv::vector<cv::Vec4i> lines;
	HoughLinesP(frame, lines, 1, CV_PI / 180, 50, 25, 100);


	// Calculate the lengths of all lines.
	int maxLengthIndex = -1;
	int maxSquaredLength = -1;
	cv::Mat houghMap(frame.size(), CV_8UC3, cv::Scalar(0));
	for (size_t i = 0; i < lines.size(); i++)
	{
		line(houghMap, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), cv::Scalar(255, 255, 255), 1, CV_AA);
		int squaredLength = (lines[i][0] - lines[i][2]) + (lines[i][1] - lines[i][3]);

		if (squaredLength > maxSquaredLength)
		{
			maxSquaredLength = squaredLength;
			maxLengthIndex = i;

			// Convert cropped coords to global coords.
			cueLine[0] = cv::Vec2i(lines[i][0] + CROP_X, lines[i][1] + CROP_Y);
			cueLine[1] = cv::Vec2i(lines[i][2] + CROP_X, lines[i][3] + CROP_Y);
		}
	}

	imshow("Cue Lines", houghMap);
}

void CueDetector::hsiSegment(cv::Mat& frame)
{
	//Can be used to control with trackbars the values
	int minH = 22;
	int maxH = 100;

	int minS = 1;
	int maxS = 166;

	int minV = 215;
	int maxV = 255;

	cv::Mat hsvFrame;

	cvtColor(frame, hsvFrame, cv::COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV

	cv::Mat hsvMask;

	inRange(hsvFrame, cv::Scalar(minH, minS, minV), cv::Scalar(maxH, maxS, maxV), hsvMask); //Threshold the image

	//Used to make the mask bigger (For our specific situation we want to make sure the mask
	//includes the whole pool table, having it a bit bigger thant he pool table is not an issue.
	dilate(hsvMask, hsvMask, getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(4, 4)));

	cv::Mat maskedFrame;
	frame.copyTo(maskedFrame, hsvMask);
	frame = maskedFrame.clone();

	imshow("HSI Cue", frame);
}

void CueDetector::GaussianBlur(cv::Mat& frame)
{
	//int display_dst(int delay);
	for (int i = 1; i < 7; i = i + 2)
	{
		cv::blur(frame, frame, cv::Size(i, i), cv::Point(-1, -1));
	}
}

void CueDetector::skeleton(cv::Mat& frame)
{
	// http://stackoverflow.com/questions/16665742/a-good-approach-for-detecting-lines-in-an-image
{'fraction_non_alphanumeric': 0.16924809912700647, 'fraction_numerical': 0.033511686848774994, 'mean_word_length': 5.039965986394558, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3282631', 'n_tokens_mistral': 3082, 'n_tokens_neox': 2806, 'n_words': 670}