C++을 이용한 OpenCV(3)

런치·2023년 9월 27일
0

C++

목록 보기
8/14
post-thumbnail

연결된 카메라 확인

#pragma once
#include <opencv2/opencv.hpp>
static void on_mouse(int, int, int, int, void*); // 함수의 원형
static void on_level_changed(int, void*);

void show_camera() {
	cv::VideoCapture cap(0); // 0 index 0 = first Camera, 1 => secondary Camera
	if (cap.isOpened()) {
		std::cout << "Connected" << std::endl;
	}
	else {
		std::cout << "Error Occured" << std::endl;
		return;
	}
	std::cout << "Frame width " << cvRound(cap.get(cv::CAP_PROP_FRAME_WIDTH)) << std::endl;
	std::cout << "Frame Height " << cvRound(cap.get(cv::CAP_PROP_FRAME_HEIGHT)) << std::endl;

	cv::Mat frame;
	cv::Mat inversed_frame;
	cv::namedWindow("FRAME", cv::WINDOW_NORMAL);
	cv::namedWindow("INVERSE", cv::WINDOW_NORMAL);
	while (true) {
		cap >> frame;
		if (frame.empty()) break;
		inversed_frame = ~frame;
		imshow("FRAME", frame);
		imshow("INVERSE", inversed_frame);
		if(cv::waitKey(10) == 27) break; // 27 => ESC
	}
	cv::destroyAllWindows();
}

연결된 카메라 영상연결

void show_movie() {
	cv::VideoCapture cap("stopwatch.avi");
	if (cap.isOpened())
	{
		std::cout << "video is connected" << std::endl;
	}
	else {
		std::cout << "There is no Video" << std::endl;
		return;
	}

	std::cout << cvRound(cap.get(cv::CAP_PROP_FRAME_WIDTH)) << std::endl;
	std::cout << cvRound(cap.get(cv::CAP_PROP_FRAME_HEIGHT)) << std::endl;
	
	double fps = cap.get(cv::CAP_PROP_FPS);
	std::cout << "FPS : " << fps << std::endl;
	
	int delay = cvRound(1'000 / fps);

	cv::namedWindow("STOPWATCH", cv::WINDOW_NORMAL);
	cv::Mat frame;
	
	cv::namedWindow("INVERSE", cv::WINDOW_NORMAL);
	
	while (true) {
		cap >> frame;
		if (frame.empty()) break;
		cv::imshow("STOPWATCH", frame);
		cv::imshow("INVERSED", ~frame);
		cv::waitKey(delay);		
	}
	cv::destroyAllWindows();
}

연결된 카메라를 통한 녹화 진행

void show_video_record() {
	cv::VideoCapture cap(0);
	if (cap.isOpened())
	{
		std::cout << "Camera is Connected" << std::endl;
	}
	else {
		std::cout << "Camera is Unconnected" << std::endl;
		return;
	}
	double fps = (cap.get(cv::CAP_PROP_FPS));
	int delay = cvRound(1000 / fps);
	int fourcc = cv::VideoWriter::fourcc('X', '2', '6', '4');
	cv::Mat frame;
	cv::Mat inversed;

	// fps 함수 적용 안되면 직접 fps 때려박기..
	cv::VideoWriter output("recording.mp4", fourcc, 30, 
		cv::Size(cap.get(cv::CAP_PROP_FRAME_WIDTH),cap.get(cv::CAP_PROP_FRAME_HEIGHT)));
	if (output.isOpened()) {
		std::cout << "Recording is ready" << std::endl;
	}
	else {
		std::cout << "Recording is not ready" << std::endl;
		return;
	}
	cv::namedWindow("RECORDING");
	while (true) {
		cap >> frame;
		inversed = ~frame;
		if (frame.empty()) break;
		output << inversed; // 영상 저장
		cv::imshow("RECORDING", frame);
		if (cv::waitKey(30) == 27) break;
	}
	cv::destroyAllWindows();
}

선 그리기

void show_draw_lines() {
	cv::Mat canvas(800, 800, CV_8UC3, cv::Scalar(255,255,255));
	
	cv::line(canvas, cv::Point(50, 50), cv::Point(200, 50), cv::Scalar(0, 0, 255), 10);
	cv::line(canvas, cv::Point(50, 50), cv::Point(200, 100), cv::Scalar(255, 0, 255), 1);

	cv::arrowedLine(canvas, cv::Point(50, 200), cv::Point(150, 200), cv::Scalar(0, 255, 0), 2);
	cv::drawMarker(canvas, cv::Point(30,250),cv::Scalar(0,0,255),cv::MARKER_CROSS);

	cv::namedWindow("CANVAS", cv::WINDOW_NORMAL);
	cv::imshow("CANVAS", canvas);
	cv::waitKey();
	cv::destroyWindow("CANVAS"); 
}

도형 그리기

void show_draw_polygons(){
	cv::Mat canvas = cv::Mat(500,500,CV_8UC3,cv::Scalar(255,255,255));
	cv::rectangle(canvas, cv::Rect(50, 50, 150, 50),cv::Scalar(0,0,255),3);
	cv::rectangle(canvas, cv::Rect(50, 150, 100, 50),cv::Scalar(0,0,255), -1);
	cv::circle(canvas, cv::Point(300, 120), 60, cv::Scalar(255, 255, 0), -1, cv::LINE_AA);
	cv::ellipse(canvas,cv::Point(120,300),cv::Size(60,30),20,0,270,cv::Scalar(0,255,0),-1,cv::LINE_AA);
	
	std::vector<cv::Point>points;
	points.push_back(cv::Point(250, 250));
	points.push_back(cv::Point(300, 250));
	points.push_back(cv::Point(300, 300));
	points.push_back(cv::Point(350, 300));
	points.push_back(cv::Point(350, 350));
	points.push_back(cv::Point(250, 350));

	cv::polylines(canvas, points, true, cv::Scalar(255, 0, 255), 5, -1);

	cv::namedWindow("CANVAS", cv::WINDOW_NORMAL);
	cv::imshow("CANVAS", canvas);
	cv::waitKey();
	cv::destroyAllWindows();
}

텍스트 삽입

void show_draw_text(){
	cv::Mat canvas = cv::imread("lenna.bmp");
	cv::putText(canvas, "LENNA",cv::Point(250,450),cv::FONT_HERSHEY_TRIPLEX | \
    cv::FONT_ITALIC,2,cv::Scalar(255,0,0),5,-1);
	cv::namedWindow("LENNA", cv::WINDOW_NORMAL);
	cv::imshow("LENNA", canvas);
	cv::waitKey();
	cv::destroyAllWindows;
	}

키보드 입력에 대한 이벤트 (종료)

void keyboard_event(int key) {
    if (key == 27) {
        // ESC 키가 눌렸을 때 프로그램 종료
        std::cout << "ESC 키 눌림. 프로그램 종료." << std::endl;
    }
}

마우스에 입력에 대한 이벤트

static cv::Mat img;
static cv::Point pt_old;
void mouse_event(int event, int x, int y, int flags, void* userdata) {
    if (event == cv::EVENT_LBUTTONDOWN) {
        // 왼쪽 마우스 버튼이 눌렸을 때
        pt_old = cv::Point(x, y);
    }
    else if (event == cv::EVENT_LBUTTONUP) {
        // 왼쪽 마우스 버튼이 떼어졌을 때
        cv::Point pt_new(x, y);
        cv::line(img, pt_old, pt_new, cv::Scalar(0, 0, 255), 2); // 빨간색 선으로 점을 연결
        cv::imshow("Image", img);
    }
}

마우스를 따라 이벤트

void on_mouse(int mouse_event, int mouse_x, int mouse_y, int flags, void* param) {
    // 이 함수는 마우스 이벤트가 발생할 때마다 호출됩니다.

    if (mouse_event == cv::EVENT_LBUTTONDOWN) {
        // 왼쪽 마우스 버튼이 눌렸을 때
        pt_old = cv::Point(mouse_x, mouse_y);
    }
    else if (mouse_event == cv::EVENT_LBUTTONUP) {
        // 왼쪽 마우스 버튼이 떼어졌을 때
        cv::Point pt_new(mouse_x, mouse_y);
        cv::line(img, pt_old, pt_new, cv::Scalar(0, 0, 255), 2); // 빨간색 선으로 점을 연결
        cv::imshow("Image", img);
    }
}

출력 이미지 상단에 Trackbar 생성

void trackbar_event() {
	cv::Mat canvas(800, 800, CV_8UC1);
	cv::namedWindow("CANVAS");
	cv::createTrackbar("Level", "CANVAS", nullptr, 16, on_level_changed, (void*)&canvas);
	cv::imshow("CANVAS", canvas);
	cv::waitKey();
	cv::destroyAllWindows();
}

Trackbar 와 연동해서 레벨에 따라 바뀌도록 함

void on_level_changed(int positition, void* userdata) {
	cv::Mat img = *(static_cast<cv::Mat*>(userdata));
	img.setTo(positition * 16);
	cv::imshow("CANVAS", img); //updating
}

특정 영역의 색을 바꿈

void mask_setTo() {
	cv::Mat src = cv::imread("lenna.bmp");
	cv::Mat mask = cv::imread("mask_smile.bmp",cv::IMREAD_GRAYSCALE);
	if (src.empty() or mask.empty()) return;
	src.setTo(cv::Scalar(0, 255, 0), mask); //mask 의 RGB 값을 src에 적용
	cv::imshow("SRC", src);
	cv::imshow("MASK", mask);
	cv::waitKey();
	cv::destroyAllWindows();
}

OpenCV를 통한 이미지 합성

void mask_copyTo() {
	cv::Mat src = cv::imread("airplane.bmp");
	cv::Mat mask = cv::imread("mask_plane.bmp", cv::IMREAD_GRAYSCALE);
	cv::Mat dst = cv::imread("field.bmp");
	if (src.empty() or mask.empty() or dst.empty()) return;

	cv::imshow("ORIGINAL", dst);
	cv::imshow("SRC", src);
	cv::imshow("MASK", mask);

	src.copyTo(dst, mask);
	cv::imshow("CHANGED", dst);
	cv::waitKey();
	cv::destroyAllWindows();
}

실행 소요 시간 측정

void time_inverse(){
	cv::Mat img = cv::imread("lenna.bmp", cv::IMREAD_GRAYSCALE);
	if (img.empty()) return;
	cv::Mat dst(img.rows, img.cols, img.type());
	cv::TickMeter tick;
	tick.start();
	for (int i = 0; i < img.rows; ++i) {
		for (int j = 0; j < img.cols; ++j) {
			dst.at<uchar>(i, j) = 255 - img.at<uchar>(i, j);
		}
	}
	tick.stop();
	std::cout << "걸린 시간 : " << tick.getTimeSec() << "초" << std::endl;
	cv::imshow("IMG", img);
	cv::imshow("DST", dst);
	cv::waitKey();
	cv::destroyAllWindows();
}

min & max 함수

void useful_funtions() {
	cv::Mat src = cv::imread("lenna.bmp", cv::IMREAD_GRAYSCALE);
	std::cout << static_cast<int>(cv::sum(src)[0]) << std::endl;
	std::cout << static_cast<int>(cv::mean(src)[0]) << std::endl;
	
	double min_value = 0.0;
	double max_value = 0.0;
	
	cv::Point min_point;
	cv::Point max_point;
	
	std::cout << "Min : " << min_value << " , " << "Max : " << max_value << std::endl;
	cv::minMaxLoc(src, &min_value, &max_value, &min_point, &max_point);
	std::cout << "Min : " << min_value << " , " << "Max : " << max_value << std::endl;
	std::cout << "Min Poisition X: " << min_point.x << " , " << "Min Position: " << min_point.y << std::endl;
	std::cout << "Max Poisition X: " << max_point.x << " , " << "Max Position: " << max_point.y << std::endl;
	
}
profile
점심을 안먹음

0개의 댓글