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