박민혀기

CELLON Kart Source Code 1.3V (2023.07.27) 본문

CELLON Kart(Tracking)/Source Code

CELLON Kart Source Code 1.3V (2023.07.27)

박민혀기 2023. 7. 27. 10:55

Update Feature

  • Descending order sort in contours
  • Processing to biggest contour area top 5
  • Comparing to error distance of pixels mean
  • Shortest error distance is best

Next Develop

  • Size, HSV의 Balance 비교
  • AdaptiveHSV 적용?
  • AutoFocus 카메라 사용시 샤프닝 적용
#include <iostream>
#include <cmath>
#include <opencv2/opencv.hpp>

#define MIN_CONTOUR		3
#define COUNT_CONTOUR	5

using namespace std;
using namespace cv;

Mat frame;
Scalar meanHSV = Scalar(0, 0, 0);

bool comparePointVectors(const vector<Point>& a, const vector<Point>& b) {
	return a.size() > b.size();
}

vector<vector<Point>> SortingArea(vector<vector<Point>> SortingContours) {
	sort(SortingContours.begin(), SortingContours.end(), comparePointVectors);

	return SortingContours;
}

Scalar pixels_avg(vector<Scalar> pixels) {
	Scalar avgHSV(0, 0, 0);

	for (int i = 0; i < pixels.size(); i++)
		avgHSV += pixels[i];

	avgHSV /= static_cast<float>(pixels.size());
	return avgHSV;
}

int Close_HSV(vector<Scalar> Compare_HSV_List) {
	int Close_HSV_Index = 0;
	int Close_HSV_Dis, Close_HSV_Dis_List;
	Scalar Close_HSV = Compare_HSV_List[0];
	Scalar Close_HSV_Min, Close_HSV_Min_List, Close_HSV_List;

	for (int i = 1; i < Compare_HSV_List.size(); i++) {
		Close_HSV_Min = meanHSV - Close_HSV;
		Close_HSV_Dis = abs(Close_HSV_Min[0]) + abs(Close_HSV_Min[1]) + abs(Close_HSV_Min[2]);

		Close_HSV_Min_List = meanHSV - Compare_HSV_List[i];
		Close_HSV_Dis_List = abs(Close_HSV_Min_List[0]) + abs(Close_HSV_Min_List[1]) + abs(Close_HSV_Min_List[2]);

		if (Close_HSV_Dis > Close_HSV_Dis_List) {
			Close_HSV = Compare_HSV_List[i];
			Close_HSV_Index = i;
		}
		else	continue;
	}

	return Close_HSV_Index;
}

void HSV_Process(Scalar lowerHSV, Scalar upperHSV) {
	Mat hsv_frame, mask;
	vector<Scalar> HSV_List;

	cvtColor(frame, hsv_frame, COLOR_BGR2HSV);
	inRange(hsv_frame, lowerHSV, upperHSV, mask);
	imshow("mask", mask);

	vector<vector<Point>> contours;
	findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	contours = SortingArea(contours);
	//cout << "contours : " << contours.size() << endl;

	if (contours.size() > MIN_CONTOUR) {
		for (int i = 0; i < COUNT_CONTOUR; i++) {
			Mat contours_mask = Mat::zeros(hsv_frame.size(), CV_8UC1);
			drawContours(contours_mask, contours, i, Scalar(255), -1);

			//mean으로 가능은 할 듯
			vector<Scalar> pixels;
			for (int y = 0; y < contours_mask.rows; y++) {
				for (int x = 0; x < contours_mask.cols; x++) {
					if (contours_mask.at<uchar>(y, x) == 255) {
						pixels.push_back(hsv_frame.at<Vec3b>(y, x));
					}
				}
			}

			HSV_List.push_back(pixels_avg(pixels));
		}

		int Close_Contour_Index = Close_HSV(HSV_List);
		Rect boundRect = boundingRect(contours[Close_Contour_Index]);
		drawContours(frame, contours, Close_Contour_Index, cv::Scalar(0, 255, 255), 1);
		rectangle(frame, boundRect, Scalar(0, 255, 0), 2);
	}
}

Scalar Push_Button(Rect2i roi_point) {
	Mat hsv_frame;
	hsv_frame = frame(roi_point).clone();
	cvtColor(hsv_frame, hsv_frame, COLOR_BGR2HSV);


	imshow("hsv_frame", hsv_frame);

	return mean(hsv_frame);
}

Scalar AdaptiveHSVUpdate(Rect2i roi_point) {
	Mat hsv_frame;
	hsv_frame = frame(roi_point).clone();
	cvtColor(hsv_frame, hsv_frame, COLOR_BGR2HSV);

	return mean(hsv_frame);
}

int main() {
	VideoCapture cap = VideoCapture(0);
	if (!cap.isOpened()) {
		cout << "Could't load camera" << endl;
		return -1;
	}

	double width = cap.get(CAP_PROP_FRAME_WIDTH);
	double height = cap.get(CAP_PROP_FRAME_HEIGHT);
	namedWindow("frame");

	int key;
	int frameCount = 0;
	Scalar dis_HSV = Scalar(32, 32, 32);
	Scalar lowerHSV, upperHSV;
	Rect2i roi_frame = Rect(Point(width / 5 * 2, height / 10 * 2), Point(width / 5 * 3, height / 10 * 8));

	while (1) {
		cap >> frame;
		flip(frame, frame, 1);
		if (frame.empty()) {
			cout << "Could't load frame" << endl;
			return -1;
		}

				//Raspberry Camera Mode//
		//Mat gaussian_blur;
		//GaussianBlur(frame, gaussian_blur, Size(9, 9), 5);
		//Mat sharpened = frame - gaussian_blur;
		//Mat result = frame + sharpened;

		key = waitKey(10);
		if (key == 27)	break;
		else if (key == 32) {
			meanHSV = Push_Button(roi_frame);
			cout << "meanHSV : " << meanHSV << endl;

			lowerHSV = meanHSV - dis_HSV;
			upperHSV = meanHSV + dis_HSV;
		}

		if (meanHSV[0] != 0 || meanHSV[1] != 0 || meanHSV[2] != 0) {
			HSV_Process(lowerHSV, upperHSV);
		}

		rectangle(frame, roi_frame, Scalar(0, 0, 255), 2, 8);
		imshow("frame", frame);
	}

	cap.release();
	destroyAllWindows();

	return 0;
}