printf("ho_tari\n");

Chpater 4 : 이미지와 동영상 파일 다루기, 직선 그리기, 문자열 출력하기, 키보드 이벤트 처리하기, 마우스 이벤트 처리하기, 트랙바 사용하기, 마스크 연산, 연산 시간 측정, 여러 수치 측정 함수 본문

OpenCV

Chpater 4 : 이미지와 동영상 파일 다루기, 직선 그리기, 문자열 출력하기, 키보드 이벤트 처리하기, 마우스 이벤트 처리하기, 트랙바 사용하기, 마스크 연산, 연산 시간 측정, 여러 수치 측정 함수

호타리 2023. 9. 13. 11:05

<OpenCV_Projects.cpp>

#include <opencv2/opencv.hpp>

extern void show_camera();
extern void show_movie();
extern void show_video_record();
extern void show_draw_lines();
extern void show_draw_polygons();
extern void show_draw_text();
extern void keyboard_event();
extern void mouse_event();
extern void trackbar_event();
extern void mask_setTo();
extern void mask_copyTo();
extern void time_inverse();
extern void useful_function();

int main()
{
    std::cout << CV_VERSION << std::endl;

    //show_camera();
    //show_movie();
    //show_video_record();
    //show_draw_lines();
    //show_draw_polygons();
    //show_draw_text();
    //keyboard_event();
    //mouse_event();
    //trackbar_event();
    //mask_setTo();
    //mask_copyTo();
    //time_inverse();
    useful_function();
}

 

<show_camera.cpp>

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

void show_camera()
{
	cv::VideoCapture cap(1);	// index ( 0 = 첫번째, 1 = 두번째) (노트북 사용시 노트북 카메라 = 0, 외부 카메라 = 1)

	if (cap.isOpened())
	{
		std::cout << "연결이 되었습니다." << std::endl;
	}
	else
	{
		std::cout << "카메라 연결 문제 발생." << std::endl;
		return;
	}

	std::cout << "Frame width : " << cvRound(cap.get(cv::CAP_PROP_FRAME_WIDTH)) << std::endl;	//cvRound : 소수점 제거 (정수로 출력)
	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;	// frame에 cap 입력
		if (frame.empty()) 
			break;

		inversed_frame = ~frame;	//비트반전

		imshow("FRAME", frame);
		imshow("INVERSE", inversed_frame);
		if (cv::waitKey(10) == 27) 
			break;	// 27 -> ESC
	}

	cv::destroyAllWindows();
}

<compile 결과>

 

<show_movie.cpp>

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

void show_movie()
{
	cv::VideoCapture cap("stopwatch.avi");

	if (cap.isOpened())
	{
		std::cout << "동영상이 연결 되었습니다." << std::endl;
	}
	else
	{
		std::cout << "동영상 파일이 없습니다." << 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::namedWindow("INVERSE", cv::WINDOW_NORMAL);

	cv::Mat frame;

	while (true)
	{
		cap >> frame;	// frame에 cap 입력

		if (frame.empty()) break;
		cv::imshow("STOPWATCH", frame);
		cv::imshow("INVERSE", ~frame);
		cv::waitKey(delay);
	}

	cv::destroyAllWindows();
}

<compile 결과>

 

<show_video_record.cpp>

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

void show_video_record()
{
	cv::VideoCapture cap(0);

	if (cap.isOpened())
	{
		std::cout << "카메라가 정상적으로 연결 되었습니다." << std::endl;
	}
	else
	{
		std::cout << "카메라 문제 발생" << std::endl;
		return;
	}

	double fps = cvRound(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;
	cv::VideoWriter output("Recording1.mp4", fourcc, 30, cv::Size(cap.get(cv::CAP_PROP_FRAME_WIDTH), cap.get(cv::CAP_PROP_FRAME_HEIGHT)));

	if (output.isOpened())
	{
		std::cout << "녹화 준비가 되었습니다." << std::endl;
	}
	else
	{
		std::cerr << "녹화 문제 발생" << std::endl;
		return;
	}

	cv::namedWindow("RECORDING");
	cv::namedWindow("INVERSE");

	while (true)
	{
		cap >> frame;

		if (frame.empty()) break;

		inversed = ~frame;

		output << inversed;	// 영상을 저장
		cv::imshow("RECORDING", frame);
		cv::imshow("INVERSE", inversed);

		if (cv::waitKey(30) == 27) break;
	}

	cv::destroyAllWindows();
}

<compile 결과>

 

<show_draw_lines.cpp>

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

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));

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

	cv::drawMarker(canvas, cv::Point(30, 350), cv::Scalar(0, 0, 255), cv::MARKER_CROSS);

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

<compile 결과>

 

<show_draw_polygons.cpp>

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

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();
}

<compile 결과>

<show_draw_text.cpp>

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

void show_draw_text()
{
	cv::Mat canvas = cv::imread("lenna.bmp");
	cv::putText(canvas, "LENNA", cv::Point(200, 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();
}

<compile 결과>

 

<keyboard_event.cpp>

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

void keyboard_event()
{
	cv::Mat img = cv::imread("lenna.bmp");

	if (img.empty()) return;

	cv::imshow("LENNA", img);

	while (true)
	{
		int key_value = cv::waitKey(0);

		if (key_value == 'I' or key_value == 'i')
		{
			img = ~img;
			cv::imshow("LENNA", img);
		}
		else
		{
			if (key_value == 27 or key_value == 'Q' or key_value == 'q') break;
		}
	}

	cv::destroyAllWindows();
}

 

<compile 결과>

<키보드 'i' 키를 눌렀을 때>

 

<mouse_event.cpp>

#pragma once
#include <opencv2/opencv.hpp>
static void on_mouse(int, int, int, int, void*);

static cv::Mat img;
static cv::Point pt_old;
void mouse_event()
{
	img = cv::imread("lenna.bmp");
	
	if (img.empty()) return;

	cv::namedWindow("LENNA", cv::WINDOW_NORMAL);
	cv::setMouseCallback("LENNA", on_mouse);
	cv::imshow("LENNA", img);
	cv::waitKey();
	cv::destroyAllWindows();
}

void on_mouse(int mouse_event, int mouse_x, int mouse_y, int flag, void*)
{
	switch (mouse_event)
	{
		case cv::EVENT_LBUTTONDOWN:
			pt_old = cv::Point(mouse_x, mouse_y);
			std::cout << "EVENT_LBUTTONDOWN  " << "x : " << mouse_x << " , " << "y : " << mouse_y << std::endl;
			break;
		case cv::EVENT_LBUTTONUP:
			std::cout << "EVENT_LBUTTONUP  " << "x : " << mouse_x << " , " << "y : " << mouse_y << std::endl;
			break;
		case cv::EVENT_MOUSEMOVE:
			if (flag & cv::EVENT_FLAG_LBUTTON)
			{
				cv::line(img, pt_old, cv::Point(mouse_x, mouse_y), cv::Scalar(255, 0, 0), 2);
				cv::imshow("LENNA", img);
				pt_old = cv::Point(mouse_x, mouse_y);
			}
			break;
	}
}

<compile 결과>

 

<trackbar_event.cpp>

#pragma once
#include <opencv2/opencv.hpp>
static void on_level_changed(int, void*);

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();
}
void on_level_changed(int position, void* userdata)
{
	cv::Mat img = *(static_cast<cv::Mat*>(userdata));
	img.setTo(position * 16);
	cv::imshow("CANVAS", img);	// updating
}

 

<compile 결과>

트랙바를 오른쪽으로 드래그하면 점점 밝기가 밝아진다

 

<mask_setTo.cpp>

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

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);

	cv::imshow("SRC", src);
	cv::imshow("MASK", mask);
	cv::waitKey();
	cv::destroyAllWindows();
}

<compile 결과>

 

<mask_copyTo.cpp>

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

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();
}

<compile 결과>

 

<time_inverse.cpp>

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

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();
}

<compile 결과>

 

<useful_function.cpp>

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

using namespace std;
using namespace cv;

void useful_function() 
{
	Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
	cout << static_cast<int>(sum(src)[0]) << endl;    // 픽셀 값들의 합
	cout << static_cast<int>(mean(src)[0]) << endl;	  // 픽셀 값들의 평균

	double min_value = 0.0;
	double max_value = 0.0;
	Point min_point;
	Point max_point;
	cout << "Min : " << min_value << " , " << "Max : " << max_value << endl;
	minMaxLoc(src, &min_value, &max_value, &min_point, &max_point);
	cout << "Min : " << min_value << " , " << "Max : " << max_value << endl;
	cout << "Min Position X : " << min_point.x << " , " << "Min Position Y : " << min_point.y << endl;
	cout << "Max Position X : " << max_point.x << " , " << "Max Position Y : " << max_point.y << endl;
}

<compile 결과>