Untitled

 avatar
unknown
plain_text
a year ago
7.9 kB
5
Indexable
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/video/background_segm.hpp>

using namespace cv;
using namespace std;

void track(int, void*);
Mat orjinalGoruntu;   // Khai báo biến lưu trữ hình ảnh gốc từ camera
Mat fgMaskMOG2;       // Biến lưu trữ hình ảnh nền đã được loại bỏ
Mat griGoruntu, kirpik, or2, kenarlar, aynali; // Các biến hỗ trợ xử lý hình ảnh và hiển thị

int thresh = 140, maxVal = 255; // Ngưỡng và giá trị tối đa cho trackbar
int type = 1, deger = 8;        // Các biến khác cho trackbar

int main() {
	Ptr<BackgroundSubtractor> pMOG2 = new BackgroundSubtractorMOG2(); // Khởi tạo bộ phân đoạn nền
	cv::Rect myRoi(288, 12, 288, 288); // Khai báo vùng quan tâm (ROI)
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(1, 1)); // Khởi tạo phần tử kết cấu cho xử lý hình ảnh
	VideoCapture cap;
	cap.open(0); // Mở camera

	while (1) {
		Mat aynali2; // Biến lưu trữ hình ảnh dọc
		cap >> orjinalGoruntu; // Chụp hình ảnh từ camera
		cv::flip(orjinalGoruntu, aynali, 1); // Lật hình ảnh
		cv::rectangle(aynali, myRoi, cv::Scalar(0, 0, 255)); // Vẽ hộp giới hạn trên hình ảnh lật
		kirpik = aynali(myRoi); // Cắt ra vùng quan tâm
		cvtColor(kirpik, griGoruntu, CV_RGB2GRAY); // Chuyển sang ảnh xám
		GaussianBlur(griGoruntu, griGoruntu, Size(23, 23), 0); // Làm mờ Gaussian

		namedWindow("ayarla", CV_WINDOW_AUTOSIZE); // Tạo cửa sổ để hiển thị trackbar
		createTrackbar("Esik", "ayarla", &thresh, 250, track); // Tạo trackbar cho ngưỡng
		createTrackbar("Maksimum", "ayarla", &maxVal, 255, track); // Tạo trackbar cho giá trị tối đa
		createTrackbar("Esik Tipi", "ayarla", &type, 4, track); // Tạo trackbar cho loại ngưỡng
		createTrackbar("Kenarlar", "ayarla", &deger, 100, track); // Tạo trackbar cho cạnh

		pMOG2->operator()(kirpik, fgMaskMOG2); // Áp dụng bộ phân đoạn nền lên vùng quan tâm
		cv::rectangle(fgMaskMOG2, myRoi, cv::Scalar(0, 0, 255)); // Vẽ hộp giới hạn trên hình ảnh đã phân đoạn

		track(0, 0); // Gọi hàm track

		imshow("ORJINAL Goruntu", aynali); // Hiển thị hình ảnh gốc
		imshow("ArkaPlan Kaldirildi", fgMaskMOG2); // Hiển thị hình ảnh đã loại bỏ nền
		imshow("Gri", griGoruntu); // Hiển thị ảnh xám

		char key = waitKey(24); // Chờ nhấn phím
		if (key == 27) break; // Nếu nhấn ESC thì thoát vòng lặp
	}

	return 0;
}

void track(int, void*) {
	int count = 0; // Đếm số điểm lồi
	char a[40]; // Chuỗi lưu trữ số điểm lồi
	vector<vector<Point> > contours; // Vector chứa đường viền
	vector<Vec4i> hierarchy; // Vector chứa thông tin phân cấp

	GaussianBlur(fgMaskMOG2, fgMaskMOG2, Size(27, 27), 3.5, 3.5); // Làm mờ Gaussian
	threshold(fgMaskMOG2, fgMaskMOG2, thresh, maxVal, type); // Ngưỡng hóa ảnh

	Canny(fgMaskMOG2, kenarlar, deger, deger * 2, 3); // Phát hiện biên
	findContours(fgMaskMOG2, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0)); // Tìm đường viền
	Mat cizim = Mat::zeros(kenarlar.size(), CV_8UC3); // Tạo ma trận để vẽ

	if (contours.size() > 0) { // Nếu có đường viền được tìm thấy
		size_t indexOfBiggestContour = -1; // Chỉ số của đường viền lớn nhất
		size_t sizeOfBiggestContour = 0; // Kích thước của đường viền lớn nhất

		for (size_t i = 0; i < contours.size(); i++) { // Duyệt qua các đường viền
			if (contours[i].size() > sizeOfBiggestContour) { // Nếu kích thước của đường viền lớn hơn
				sizeOfBiggestContour = contours[i].size(); // Cập nhật kích thước lớn nhất
				indexOfBiggestContour = i; // Cập nhật chỉ số đường viền lớn nhất
			}
		}

		vector<vector<int> > hull(contours.size()); // Vector chứa các đỉnh lồi
		vector<vector<Point> > hullPoint(contours.size()); // Vector chứa các điểm đỉnh lồi
		vector<vector<Vec4i> > defects(contours.size()); // Vector chứa các khiếm khuyết
		vector<vector<Point> > defectPoint(contours.size()); // Vector chứa các điểm khiếm khuyết
		vector<vector<Point> > contours_poly(contours.size()); // Vector chứa đường viền xấp xỉ
		Point2f rect_point[4]; // Mảng lưu trữ các điểm của hình chữ nhật bao quanh
		vector<RotatedRect> minRect(contours.size()); // Vector chứa hình chữ nhật nhỏ nhất
		vector<Rect> boundRect(contours.size()); // Vector chứa hình chữ nhật giới hạn

		for (size_t i = 0; i < contours.size(); i++) { // Duyệt qua các đường viền
			if (contourArea(contours[i]) > 5000) { // Nếu diện tích đường viền lớn hơn 5000
				convexHull(contours[i], hull[i], true); // Tìm vùng lồi
				convexityDefects(contours[i], hull[i], defects[i]); // Tìm khiếm khuyết

				if (indexOfBiggestContour == i) { // Nếu đây là đường viền lớn nhất
					minRect[i] = minAreaRect(contours[i]); // Tạo hình chữ nhật bao quanh nhỏ nhất

					for (size_t k = 0; k < hull[i].size(); k++) { // Duyệt qua các đỉnh lồi
						int ind = hull[i][k]; // Lấy chỉ số của đỉnh lồi
						hullPoint[i].push_back(contours[i][ind]); // Thêm điểm vào vector hullPoint
					}

					count = 0; // Đặt lại số điểm khiếm khuyết

					for (size_t k = 0; k < defects[i].size(); k++) { // Duyệt qua các khiếm khuyết
						if (defects[i][k][3] > 13 * 256) { // Nếu khoảng cách lớn hơn ngưỡng
							int p_start = defects[i][k][0]; // Điểm bắt đầu của khiếm khuyết
							int p_end = defects[i][k][1]; // Điểm kết thúc của khiếm khuyết
							int p_far = defects[i][k][2]; // Điểm lồi của khiếm khuyết
							defectPoint[i].push_back(contours[i][p_far]); // Thêm điểm vào vector defectPoint
							circle(griGoruntu, contours[i][p_end], 3, Scalar(0, 255, 0), 2); // Vẽ điểm kết thúc khiếm khuyết
							count++; // Tăng biến đếm
						}
					}

					// Đánh số tay
					if (count == 1)
						strcpy(a, "1");
					else if (count == 2)
						strcpy(a, "2");
					else if (count == 3)
						strcpy(a, "3");
					else if (count == 4)
						strcpy(a, "4");
					else if (count == 5 || count == 6)
						strcpy(a, "5");
					else
						strcpy(a, "EL GOSTER");

					putText(aynali, a, Point(75, 450), CV_FONT_HERSHEY_SIMPLEX, 3, Scalar(0, 255, 0), 3, 8, false); // Hiển thị số tay

					drawContours(cizim, contours, i, Scalar(255, 255, 0), 2, 8, vector<Vec4i>(), 0, Point()); // Vẽ đường viền lớn nhất
					drawContours(cizim, hullPoint, i, Scalar(255, 255, 0), 1, 8, vector<Vec4i>(), 0, Point()); // Vẽ đỉnh lồi
					drawContours(griGoruntu, hullPoint, i, Scalar(0, 0, 255), 2, 8, vector<Vec4i>(), 0, Point()); // Vẽ đỉnh lồi

					approxPolyDP(contours[i], contours_poly[i], 3, false); // Xấp xỉ đường viền
					boundRect[i] = boundingRect(contours_poly[i]); // Tạo hình chữ nhật giới hạn
					rectangle(griGoruntu, boundRect[i].tl(), boundRect[i].br(), Scalar(255, 0, 0), 2, 8, 0); // Vẽ hình chữ nhật giới hạn

					minRect[i].points(rect_point); // Lấy các điểm của hình chữ nhật nhỏ nhất
					for (size_t k = 0; k < 4; k++) { // Duyệt qua 4 điểm
						line(griGoruntu, rect_point[k], rect_point[(k + 1) % 4], Scalar(0, 255, 0), 2, 8); // Vẽ các cạnh của hình chữ nhật
					}
				}
			}
		}
	}

	imshow("Sonuc", cizim); // Hiển thị kết quả
}
Editor is loading...
Leave a Comment