반응형

폴리곤 마스크를 생성하고 사용해 보자.

 

#include <iostream>
#include <opencv2/opencv.hpp>

void onMouse(int event, int x, int y, int flags, void* userdata)
{
	static std::vector<cv::Point> points; // Static vector to store points across function calls
	cv::Scalar color(0, 255, 0); // Green color for drawing
	cv::Mat* img = (cv::Mat*)userdata; // Cast the user data to a pointer to cv::Mat

	switch (event)
	{
	case cv::EVENT_LBUTTONDOWN:
		points.push_back(cv::Point(x, y));
		std::cout << "Point added: (" << x << ", " << y << ")" << std::endl;

		break;

	case cv::EVENT_RBUTTONDOWN:
		if (!points.empty())
		{
			points.pop_back(); // Remove the last point if right button is clicked
			std::cout << "Last point removed" << std::endl;
			*img = cv::imread("palvin1.png"); // Reload the original image to clear drawings
		}
		break;
	}

	// Draw points
	for (const cv::Point& point : points)
		cv::circle(*(cv::Mat*)userdata, point, 5, color, -1);
	// userdata로도 접근 가능하지만, img 포인터로도 접근 가능

	// Draw lines between points
	if (points.size() >= 2)
		for (int i = 0; i < points.size() - 1; i++)
			cv::line(*img, points[i], points[i + 1], cv::Scalar(0, 0, 255), 2);

	cv::imshow("image", *(cv::Mat*)userdata);
}

int main()
{
	cv::Mat image = cv::imread("palvin1.png");
	cv::namedWindow("image");
	cv::setMouseCallback("image", onMouse, (void*)&image);

	cv::imshow("image", image);

	cv::waitKey(0);
	cv::destroyAllWindows();

	return 0;
}

 

 

 

 

#include <iostream>
#include <opencv2/opencv.hpp>

void onMouse(int event, int x, int y, int flags, void* userdata)
{
	static std::vector<std::pair<cv::Point, cv::Scalar>> points; // Store points along with their colors
	cv::Scalar color(0, 255, 0); // Default color is green
	cv::Mat* img = (cv::Mat*)userdata; // Cast the user data to a pointer to cv::Mat

	switch (event)
	{
	case cv::EVENT_LBUTTONDOWN:
		if (flags & cv::EVENT_FLAG_CTRLKEY) // Check if Ctrl key is pressed
			color = cv::Scalar(255, 0, 0); // Blue color if Ctrl is pressed

		points.push_back(std::make_pair(cv::Point(x, y), color));
		std::cout << "Point added: (" << x << ", " << y << ") with color "
			<< (color == cv::Scalar(0, 255, 0) ? "Green" : "Blue") << std::endl;

		break;

	case cv::EVENT_RBUTTONDOWN:
		if (!points.empty())
		{
			points.pop_back(); // Remove the last point if right button is clicked
			std::cout << "Last point removed" << std::endl;
			*img = cv::imread("palvin1.png"); // Reload the original image to clear drawings
		}
		break;
	}

	// Draw points
	for (const std::pair<cv::Point, cv::Scalar>& point_color_pair : points)
		cv::circle(*(cv::Mat*)userdata, point_color_pair.first, 5, point_color_pair.second, -1);
	// userdata로도 접근 가능하지만, img 포인터로도 접근 가능

	// Draw lines between points
	if (points.size() >= 2)
		for (int i = 0; i < points.size() - 1; i++)
			cv::line(*img, points[i].first, points[i + 1].first, cv::Scalar(0, 0, 255), 2);

	cv::imshow("image", *(cv::Mat*)userdata);
}

int main()
{
	cv::Mat image = cv::imread("palvin1.png");
	cv::namedWindow("image");
	cv::setMouseCallback("image", onMouse, (void*)&image);

	cv::imshow("image", image);

	cv::waitKey(0);
	cv::destroyAllWindows();

	return 0;
}

 

 

 

 

#include <iostream>
#include <opencv2/opencv.hpp>

std::vector<cv::Point> points;

void onMouse(int event, int x, int y, int flags, void* userdata)
{
	cv::Scalar color(0, 255, 0); // Green color for drawing
	cv::Mat* img = (cv::Mat*)userdata; // Cast the user data to a pointer to cv::Mat

	switch (event)
	{
	case cv::EVENT_LBUTTONDOWN:
		points.push_back(cv::Point(x, y));
		std::cout << "Point added: (" << x << ", " << y << ")" << std::endl;

		break;

	case cv::EVENT_RBUTTONDOWN:
		if (!points.empty())
		{
			points.pop_back(); // Remove the last point if right button is clicked
			std::cout << "Last point removed" << std::endl;
			*img = cv::imread("palvin1.png"); // Reload the original image to clear drawings
		}
		break;
	}

	// Draw points
	for (const cv::Point& point : points)
		cv::circle(*(cv::Mat*)userdata, point, 5, color, -1);
	// userdata로도 접근 가능하지만, img 포인터로도 접근 가능

	// Draw lines between points
	if (points.size() >= 2)
		for (int i = 0; i < points.size() - 1; i++)
			cv::line(*img, points[i], points[i + 1], cv::Scalar(0, 0, 255), 2);

	cv::imshow("image", *(cv::Mat*)userdata);
}

int main()
{
	cv::Mat image = cv::imread("palvin1.png");
	cv::Mat mask = cv::Mat::zeros(image.size(), CV_8UC1);
	cv::Mat result = cv::Mat::zeros(image.size(), image.type());
	cv::Mat roi;

	cv::Rect rect;

	cv::namedWindow("image");
	cv::setMouseCallback("image", onMouse, (void*)&image);

	cv::imshow("image", image);

	while (true)
	{
		int key = cv::waitKey(10);
		if (key == 27) // ESC key
			break;

		switch (key)
		{
			// c키를 누르면 모든 점을 지우고 원본 이미지를 다시 불러와서 초기화
		case 'c':
			points.clear(); // Clear all points if 'c' key is pressed
			image = cv::imread("palvin1.png"); // Reload the original image to clear drawings

			mask.setTo(0); // Clear the mask as well
			cv::imshow("image", image);
			if (cv::getWindowProperty("mask", cv::WND_PROP_VISIBLE) == 1) // Check if the mask window is open
				cv::imshow("mask", mask); // Clear the mask display as well

			result.setTo(0); // Clear the result image as well
			if (cv::getWindowProperty("result", cv::WND_PROP_VISIBLE) == 1) // Check if the result window is open
				cv::imshow("result", result); // Clear the result display as well

			roi.setTo(0); // Clear the ROI image as well
			if (cv::getWindowProperty("ROI", cv::WND_PROP_VISIBLE) == 1) // Check if the ROI window is open
				cv::imshow("ROI", roi); // Clear the ROI display as well

			break;

			// m키를 누르면 points 벡터에 저장된 점들을 이용하여 mask 이미지를 채우고, mask 이미지를 화면에 표시
		case 'm':
			mask.setTo(0); // Clear the mask before filling
			cv::fillPoly(mask, points, cv::Scalar(255)); // Fill the polygon defined by points
			cv::imshow("mask", mask);

			break;

			// r키를 누르면 mask 이미지를 이용하여 원본 이미지에서 해당 영역을 추출하여 result 이미지에 저장하고, result 이미지를 화면에 표시
		case 'r':
			image = cv::imread("palvin1.png"); // Reload the original image to clear drawings
			result.setTo(0); // Clear the result image before copying
			image.copyTo(result, mask); // Copy the masked area to the result image
			//cv::bitwise_and(image, image, result, mask); // Apply the mask to the image
			cv::imshow("result", result);

			break;

		case 'i':
			rect = cv::boundingRect(points); // Get the bounding rectangle of the points			
			roi = result(rect);
			cv::imshow("ROI", roi);

			break;

		default:
			break;
		}
	}

	cv::destroyAllWindows();

	return 0;
}

 

 

 

 

 

※ 참고

2026.03.13 - [분류 전체보기] - [OpenCV] Select Region of Interest ROI 선택

2026.03.11 - [OpenCV] - [OpenCV] Polygon Mask 폴리곤 마스크 1

 

반응형
Posted by J-sean
: