C++ 을 이용한 OpenCV(5)

런치·2023년 10월 4일
0

C++

목록 보기
11/14
post-thumbnail

이미지의 논리 연산

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

void arithmetic1() {
	cv::Mat src1 = cv::imread("lenna256.bmp", cv::IMREAD_GRAYSCALE);
	cv::Mat src2 = cv::imread("square.bmp", cv::IMREAD_GRAYSCALE);
	
	if (src1.empty() or src2.empty()) return;

	std::cout << src1.size << std::endl; 
	std::cout << src2.size << std::endl;

	cv::Mat dst1;
	cv::add(src1,src2,dst1);
	//cv::Mat dst2 = src2 - src1;
	cv::Mat dst2;
	cv::subtract(src2, src1, dst2);
	cv::Mat dst3;
	cv::absdiff(src1, src2, dst3); //
	cv::Mat dst4;
	cv::namedWindow("ADDWEIGHTED");
	for (double i = 0; i <= 1.0; i = i + 0.2) {
		cv::addWeighted(src1, i, src2, i - 1.0, 0.0, dst4);
		cv::imshow("ADDWEIGHTED", dst4);
		cv::waitKey();
	}
	cv::imshow("DST1", dst1);
	cv::imshow("DST2", dst2);
	cv::imshow("SRC1", src1);
	cv::imshow("SRC2", src2);
	cv::imshow("DST3", dst3);
	cv::waitKey();
	cv::destroyAllWindows();
}

void logical() {
	cv::Mat src1 = cv::imread("lenna256.bmp", cv::IMREAD_GRAYSCALE);
	cv::Mat src2 = cv::imread("square.bmp",cv::IMREAD_GRAYSCALE);
	if (src1.empty() or src2.empty())return;
	cv::Mat dst(256, 256, CV_8UC1);
	/*cv::bitwise_and(src1, src2, dst);
	cv::imshow("SRC1", src1);
	cv::imshow("SRC2", src2);
	cv::imshow("DST", dst);*/


	cv::bitwise_or(src1, src2, dst);
	cv::imshow("SRC1", src1);
	cv::imshow("SRC2", src2);
	cv::imshow("DST", dst);
	cv::waitKey();

	cv::bitwise_xor(src1, src2, dst);
	cv::imshow("SRC1", src1);
	cv::imshow("SRC2", src2);
	cv::imshow("DST", dst);
	cv::waitKey();

	cv::bitwise_not(src1, src2, dst);
	cv::imshow("SRC1", src1);
	cv::imshow("SRC2", src2);
	cv::imshow("DST", dst);
	cv::waitKey();

	cv::destroyAllWindows();
}

마우스 감지

static void on_mouse(int, int, int, int, void*);

필터 - 엠보싱

엠보싱 필터링(Embossing Filtering) : 컨벌루션 - 픽셀 간 차이 계산 - 밝기 조절의 순서로 이루어지며 주로 이미지의 경계 및 입체 느낌을 부각시키기 위해 적용

void filter_embossing() {
	cv::Mat src = cv::imread("lenna.bmp", cv::IMREAD_GRAYSCALE);
	if (src.empty()) return;
	float fillter_data[] = { -1.0f,-1.0f, 0.0f, -1.0,0.0f,1.0f,0.0f,1.0f,1.0f };

	cv::Mat emboss_kernel(3, 3, CV_32FC1, fillter_data);

	cv::Mat dst;
	cv::filter2D(src, dst, -1, emboss_kernel, cv::Point(-1, -1), 80); // 80 -> ligth up
	cv::imshow("SRC", src);
	cv::imshow("DST", dst);
	cv::waitKey();
	cv::destroyAllWindows();
}

필터 - 블러링

블러링 필터(Blurring Filter) : 컨벌루션 - 픽셀 간의 가중 평균 계산 - 흐리게 만들기의 순서로 진행되며 이미지의 노이즈를 줄이는 데 효과적이다.
주로 이미지에서 잡음을 제거하거나 세부한 텍스처를 흐리게 만들어 감추는 데 사용

void filter_blurring() {
	cv::Mat src = cv::imread("lenna.bmp", cv::IMREAD_GRAYSCALE);
	if (src.empty())return;
	cv::Mat dst;
	float blur_filter[] = { 1 / 9.f,1 / 9.f,1 / 9.f, 1 / 9.f,1 / 9.f,1 / 9.f , 1 / 9.f,1 / 9.f,1 / 9.f };
	cv::Mat dst2(3, 3, CV_32FC1, blur_filter);
	cv::filter2D(src, dst, -1, dst2, cv::Point(-1, -1), 0);
	cv::imshow("SRC", src);
	cv::imshow("DST", dst);
	cv::waitKey();

	for (int ksize = 3; ksize <= 7; ksize += 2) {
		cv::blur(src, dst, cv::Size(ksize, ksize));
		cv::String desc = cv::format("Mean : %d X %d", ksize, ksize);
		cv::putText(dst, desc, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255), 1, cv::LINE_AA);
		cv::imshow("DST", dst);
		cv::waitKey();
	}

	cv::destroyAllWindows();
}

필터 - 가우시안 (블러링)

평균값 필터보다 자연스러운 블러링 결과를 만드는 핕터 ( 주로 평균이 0 )
가우시안 분포 : 평균을 중심으로 좌우 대칭의 종 모양을 갖는 확률 분포 ( 정규 분포 )

void filter_gaussian() {
	cv::Mat src = cv::imread("rose.bmp", cv::IMREAD_GRAYSCALE);
	if (src.empty())return;
	cv::Mat dst;
	for (int sigma = 1; sigma <= 5; ++sigma) {
		cv::GaussianBlur(src, dst, cv::Size(), static_cast<double>(sigma));
		cv::String text = cv::format("Sigma : %d", sigma);
		cv::putText(dst, text, cv::Point(10, 30), cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(255), 1, cv::LINE_AA);
		cv::imshow(text, dst);
		cv::waitKey();
	}
	cv::destroyAllWindows();
}

필터/샤프닝 - 언샤프 마스크 필터

영상을 더 날카롭게 만듦

void filter_unsharp_mask() {
	cv::Mat src = cv::imread("lenna.bmp", cv::IMREAD_GRAYSCALE);
	if (src.empty())return;
	cv::imshow("SRC", src);
	cv::Mat blurred;
	float alpha = 1.0f;
	for (int sigma = 1; sigma <= 5; ++sigma) {
		cv::GaussianBlur(src, blurred, cv::Size(), sigma);
		cv::Mat dst = (1 + alpha) * src - (alpha * blurred);
		cv::String text = cv::format("Sigma : %d", sigma);
		cv::putText(dst, text, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255), 1.0, cv::LINE_AA);
		cv::imshow(text, dst);
		cv::waitKey();
	}
	cv::destroyAllWindows();
}

필터 - 노이즈 가우시안

원본 영상에 잡음의 정도와 평균이 0, 분산이 1인 확률변수를 곱한 값을 더하는 방법으로 생성

void noise_gaussian() {
	cv::Mat src = cv::imread("lenna.bmp",cv::IMREAD_GRAYSCALE);
	cv::Mat dst;
	
	for (int stddev = 10; stddev <= 30; stddev += 10) {
		cv::Mat noise(src.size(), CV_32FC1);
		cv::randn(noise, 0, stddev);
		cv::add;
		cv::String text = cv::format("STDDEV : %d", stddev);
		cv::putText(dst, text, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255), 1, cv::LINE_AA);
		cv::imshow("SRC", src);
		cv::imshow("DST", dst);
		cv::waitKey();
		cv::destroyAllWindows();
	}
}

필터 - 양방향 필터

기준 픽셀과 이웃 픽셀과의 거리, 그리고 픽셀 값의 차이를 함께 고려하여 블러링 정도를 조절하며
엣지가 아닌 부분에서만 블러링 실행

void filter_bilateral(){
	cv::Mat src = cv::imread("lenna.bmp", cv::IMREAD_GRAYSCALE);
	if (src.empty())return;
	cv::Mat dst1;
	cv::Mat dst2;
	
	cv::Mat noise(src.size(), CV_32FC1);
	cv::randn(noise, 0, 5);
	cv::add(src, noise, src, cv::noArray(), CV_8UC1);

	cv::GaussianBlur(src, dst1, cv::Size(), 5); //sigma 5
	cv::bilateralFilter(src, dst2, -1, 20, 5);

	cv::imshow("SRC", src);
	cv::imshow("DST1", dst1);
	cv::imshow("DST2", dst2);

	cv::waitKey();
	cv::destroyAllWindows();
}

필터 - 미디움 필터 (미디언 블러)

미디언 필터(Median filter)는 주변 픽셀들의 값들을 정렬하여 그 중앙값(median)으로 픽셀 값을 대체하며, 소금-후추 잡음 제거에 효과적이지만 화질이 좋지 않음.

void filter_medium() {
	cv::Mat src = cv::imread("lenna.bmp", cv::IMREAD_GRAYSCALE);
	cv::imshow("SRC", src);

	int number = static_cast<int>(src.total() * 0.1);
	for (int i=0; i < number; ++i) {
		int x = rand() % src.cols;
		int y = rand() % src.rows;
		src.at<uchar>(y, x) = (i % 2)*255;
	}
	cv::Mat dst1; //Gaussian Blur
	cv::Mat dst2; //Median blur

	cv::GaussianBlur(src, dst1, cv::Size(), 1);
	cv::medianBlur(src, dst2, 3);


	cv::imshow("SRC", src);
	cv::imshow("DST1", dst1);
	cv::imshow("DST2", dst2);
	cv::waitKey();
	cv::destroyAllWindows();
}

어파인 변환

6개의 파라미터를 가지는 어파인 변환 행렬은 이동한 점의 개수가 최소 3개 이상이어야 구할 수 있으며, 이를 통해 영상의 크기, 모양, 방향을 수정할 수 있다.

void affine_transform() {
	cv::Mat src = cv::imread("tekapo.bmp");
	if (src.empty())return;
	cv::Point2f srcPts[3];
	cv::Point2f dstPts[3];
	srcPts[0] = cv::Point2f(0, 0);
	srcPts[1] = cv::Point2f(src.cols - 1.0f, 0.0f);
	srcPts[2] = cv::Point2f(src.cols - 1.0f,src.rows-1.0f);
	dstPts[0] = cv::Point2f(50.0f,50.f);
	dstPts[1] = cv::Point2f(src.cols - 100.0f, 100.0f);
	dstPts[2] = cv::Point2f(src.cols - 50.0f,src.rows- 50.0f);
	cv::Mat M = cv::getAffineTransform(srcPts, dstPts);
	std::cout << M << std::endl;
	
	cv::Mat dst;
	cv::warpAffine(src, dst, M, cv::Size());
	cv::imshow("SRC", src);
	cv::imshow("DST", dst);
	cv::waitKey();
	cv::destroyAllWindows();
}

이미지 방향전환 ( 90도 Rotate )

void rotate_flip() {
    cv::Mat src = cv::imread("lenna.bmp");

    if (src.empty()) {
        std::cerr << "Failed to load image." << std::endl;
        return;
    }

    cv::Mat dst1;
    cv::Mat dst2;

    // Rotate the image 90 degrees clockwise
    cv::rotate(src, dst1, cv::ROTATE_90_CLOCKWISE);

    // Flip the image horizontally and vertically
    cv::flip(src, dst2, -1);

    cv::imshow("Rotated Image", dst1);
    cv::imshow("Flipped Image", dst2);
    cv::waitKey(0);
    cv::destroyAllWindows();
}

소벨 엣지 검출기

void sobel_edge() {
	cv::Mat src = cv::imread("lenna.bmp", cv::IMREAD_GRAYSCALE);
	if(src.empty())return;
	cv::Mat dx;
	cv::Mat dy;
	cv::Sobel(src, dx, CV_32FC1,1,0); 
	cv::Sobel(src, dy, CV_32FC1,0,1); 
	
	cv::imshow("SRC", src);
	cv::imshow("DX", dx);
	cv::imshow("DY", dy);

	cv::Mat mag;
	cv::magnitude(dx, dy, mag);
	//C++ float -> imshow (opencv data)
	mag.convertTo(mag, CV_8UC1);

	cv::imshow("Mag", mag);

	cv::waitKey();
	cv::destroyAllWindows();
}

직선 검출

void hough_lines() {
	cv::Mat src = cv::imread("building.jpg", cv::IMREAD_GRAYSCALE);
	if (src.empty())return;
	cv::Mat edge;
	cv::Canny(src, edge, 50, 150);
	cv::imshow("EDGE", edge);
	std::vector<cv::Vec2f> lines;
	cv::HoughLines(edge, lines, 1.0, CV_PI / 180, 230);
	cv::Mat dst;
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR); //3channel ( Not colored )

	cv::imshow("DST",dst);
	for (int i = 0; i < lines.size(); ++i)
	{
		float r = lines[i][0];
		float t = lines[i][1];
		double cos_t = cos(t);
		double sin_t = sin(t);
		double x0 = r * cos_t;
		double y0 = r * sin_t;
		double alpha = 1000;
		cv::Point pt1(cvRound(x0 + alpha * (-sin_t)), cvRound(y0 + alpha * cos_t));
		cv::Point pt2(cvRound(x0 - alpha * (-sin_t)), cvRound(y0 - alpha * cos_t));
	
		cv::line(dst, pt1, pt2, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
	}
	cv::imshow("DST", dst);
	cv::waitKey();
	cv::destroyAllWindows();
}

원형 검출

void hough_circles() {
	cv::Mat src = cv::imread("coins.png", cv::IMREAD_GRAYSCALE);
	if (src.empty()) return;
	
	cv::Mat blurred; // eliminate noise 
	cv::blur(src, blurred, cv::Size(3, 3));

	std::vector<cv::Vec3f> circles;
	cv::HoughCircles(blurred, circles, cv::HOUGH_GRADIENT,1,50,200,50);

	cv::Mat dst;
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);
	for (auto&& circle : circles) {
		cv::Point center(cvRound(circle[0]), cvRound(circle[1]));
		int radius = cvRound(circle[2]);
		cv::circle(dst, center, radius, cv::Scalar(255, 0, 0), 2, cv::LINE_AA);
	}

	cv::imshow("SRC",src);
	cv::imshow("DST",dst);
	cv::waitKey();
	cv::destroyAllWindows();
}

profile
점심을 안먹음

0개의 댓글