C++을 이용한 OpenCV(7)

런치·2023년 10월 4일
0

C++

목록 보기
12/14
post-thumbnail

스마트 포인터

포인터처럼 동작하는 클래스 템플릿으로, 사용이 끝난 메모리를 자동으로 해제, new 키워드를 사용해 기본 포인터가 실제 메모리를 가리키도록 초기화한 후에, 기본 포인터를 스마트 포인터에 대입하여 사용
이렇게 정의된 스마트 포인터의 수명이 다하면, 소멸자는 delete 키워드를 사용하여 할당된 메모리를 자동으로 해제
따라서 new 키워드가 반환하는 주소값을 스마트 포인터에 대입하면, 따로 메모리를 해제할 필요 없음

#pragma once
#include<opencv2/opencv.hpp>

//smart pointer
static cv::Ptr<cv::ml::KNearest> train_knn() {
	cv::Mat digits = cv::imread("digits.png", cv::IMREAD_GRAYSCALE);
	if (digits.empty())return nullptr; 
	cv::Mat train_images;
	cv::Mat train_labels;
	for (int i = 0; i < 50; ++i) {
		for (int j = 0; j < 100; ++j) {
			cv::Mat roi = digits(cv::Rect(j * 20, i * 20, 20, 20));
			cv::Mat roi_float;
			roi.convertTo(roi_float, CV_32FC1);
			cv::Mat roi_flatten = roi_float.reshape(1, 1); 
			train_images.push_back(roi_flatten);
			train_labels.push_back(i / 5);
		}
	}
	cv::Ptr<cv::ml::KNearest> knn = cv::ml::KNearest::create(); //Singular
	knn->train(train_images, cv::ml::ROW_SAMPLE,train_labels);
	return knn;
}

마우스 클릭 감지

static cv::Point point_prev(-1, -1);
static void on_mouse(int event, int x, int y, int flag, void* userdata) {
	cv::Mat src = *(static_cast<cv::Mat*>(userdata));
	if (event == cv::EVENT_LBUTTONDOWN) {
		point_prev = cv::Point(x, y);
	}
	else if (event == cv::EVENT_LBUTTONUP){
		point_prev = cv::Point(-1, -1);
	}
	else if (event == cv::EVENT_MOUSEMOVE && (flag & cv::EVENT_FLAG_LBUTTON)) {
		cv::line(src, point_prev, cv::Point(x, y), cv::Scalar(255, 255, 255), 30, cv::LINE_AA, 0);
		point_prev = cv::Point(x, y);
		cv::imshow("DISPLAY", src);
	}
}

KNN 알고리즘

최근접 알고리즘(KNN 알고리즘)은 분류 알고리즘으로 주변에 가까운 K개의 데이터를 보고 데이터가 속할 그룹을 판단

void do_knn_machine_learning() {
	cv::Ptr<cv::ml::KNearest> knn = train_knn();
	if (knn.empty()) {
		std::cerr << "Train Error" << std::endl;
		return;
	}
	std::cout << "Train finished" << std::endl;
	cv::Mat input_display(200, 200, CV_8UC1);
	cv::namedWindow("DISPLAY", cv::WINDOW_NORMAL);
	cv::setMouseCallback("DISPLAY", on_mouse, (void*)&input_display);
	while (true) {
		int keyboard_key = cv::waitKey();
		if (keyboard_key == 27)break;
		else if (keyboard_key == ' ') { //input space bar
			cv::Mat img_resize;
			cv::Mat img_float; // Matrix to transform CV_32FC1 
			cv::Mat image_flatten;
			cv::Mat resource; // Matrix to save the result
			cv::resize(input_display, img_resize, cv::Size(20, 20), 0, 0, cv::INTER_AREA);
			img_resize.convertTo(img_float,CV_32FC1);
			image_flatten = img_float.reshape(1, 1); //flatten ( 1 x 400 )
			knn->findNearest(image_flatten, 5, resource); // k =5  optionable 3,5,7,9
			std::cout << cvRound(resource.at<float>(0, 0)) << std::endl;
			input_display.setTo(0);
			cv::imshow("DISPLAY", input_display);
		}
	}
	cv::destroyAllWindows();
}
profile
점심을 안먹음

0개의 댓글