Recent Posts
printf("ho_tari\n");
Chapter3 : Point, Size, Rect, Range, Mat 클래스 본문
<OpenCV_Projects.cpp>
#include <opencv2/opencv.hpp>
extern void show_images(); // show_images()가 외부에 있다는 의미
extern void show_code_3(); // show_code_3()가 외부에 있다는 의미
extern void show_code_3_8(); // show_code_3_8()가 외부에 있다는 의미
extern void show_code_3_9(); // show_code_3_9()가 외부에 있다는 의미
extern void show_code_3_10(); // show_code_3_10()가 외부에 있다는 의미
extern void show_code_3_11(); // show_code_3_11()가 외부에 있다는 의미
extern void show_code_3_12(); // show_code_3_12()가 외부에 있다는 의미
extern void show_code_3_13();
extern void show_code_3_16();
int main()
{
std::cout << CV_VERSION << std::endl;
//show_images(); // show_images() 실행
//show_code_3(); // show_code_3() 실행
//show_code_3_8(); // show_code_3_8() 실행
//show_code_3_9(); // show_code_3_9() 실행
//show_code_3_10(); // show_code_3_10() 실행
//show_code_3_11(); // show_code_3_11() 실행
//show_code_3_12(); // show_code_3_12() 실행
//show_code_3_13();
show_code_3_16();
}
<show_code_3.cpp>
#pragma once
#include <opencv2/opencv.hpp>
void show_code_3()
{
cv::Point pt1; //default 생성자
pt1.x = 5;
pt1.y = 10;
cv::Point pt2(pt1); // 복사 생성자
cv::Point p3 = pt1 + pt2; // 연산자 overloading
int dot1 = pt1.dot(pt2); // 두점의 내적을 구함 (inner product pt1 vector pt2 vector)
std::cout << pt2 << std::endl;
cv::Size sz1(10, 20); // 너비 10 높이 20 size 클래스
cv::Size sz2; // default 생성자
cv::Size sz3 = sz1 + sz2;
int sz4 = sz1.area(); // 넓이 : 10 * 20
std::cout << sz1 << std::endl;
cv::Rect rc1(0, 10, 0 + 60, 10 + 30); // (0, 10) 부터 너비 60 높이 40 직사각형
cv::Rect rc2 = rc1 + cv::Size(50, 40); // rc1이 시작점 그로부터 50 x 40 직사각형
cv::Rect rc3 = rc2 + cv::Point(60, 60); // rc2 사각형 위치 (60, 60)만큼 이동
cv::Range r1(0, 10); // int i = 0; i < 10; ++i => 0 ~ 9
//std::string == cv::String, typedef std::string String
cv::String str1 = "Hello";
cv::String str2 = "World";
cv::String str3 = str1 + str2; // 연산자 overloading
for (int i = 0; i < 10; ++i)
{
cv::String str = cv::format("TEST %d", i); // sprintf(), 특정 형식 문자열 생성 위해 format() 함수 이용
std::cout << str << std::endl;
}
cv::Mat mat1(800, 800, CV_8UC3, cv::Scalar(255, 0, 0)); // 800 x 800 행렬, type : uchar(8비트 unsigned char, 3-channels), 모든 픽셀값이 (255, 0, 0)으로 초기화(B, G, R)
cv::Mat mat2(800, 800, CV_8UC1, cv::Scalar(127)); // 800 x 800 행렬, type : uchar(8비트 unsigned char, 1-channel), 모든 픽셀값이 127로 초기화
std::cout << "[ 10, 20 ] : " << static_cast<int>(mat2.at<uchar>(10, 20)) << std::endl; // mat2 행렬의 [ 10, 20 ]의 원소값을 참조
cv::Mat mat3(255 + cv::Mat::zeros(900, 900, CV_8UC1)); // 900 x 900 행렬의 모든 원소값을 0으로 초기화, 255 + 0 이므로 흰색 출력
cv::Mat mat4(255 * cv::Mat::ones(900, 900, CV_8UC1)); // 900 x 900 행렬의 모든 원소값을 1로 초기화, 255 * 1 이므로 흰색 출력
cv::Mat mat5(255 * cv::Mat::eye(900, 900, CV_8UC1)); // 900 x 900 Identity 행렬, 255 * 1이므로 흰색 대각선 출력
cv::imshow("Mat1", mat1);
cv::imshow("Mat2", mat2);
cv::imshow("Mat3", mat3);
cv::imshow("Mat4", mat4);
cv::imshow("Mat5", mat5);
cv::waitKey();
cv::destroyAllWindows();
}
<compile 결과>
<show_code_3_8.cpp>
#pragma once
#include <opencv2/opencv.hpp>
void show_code_3_8()
{
cv::Mat img1{ cv::imread("dog.bmp") }; // C++11 uniform initializer, 초기화 한번만 가능
if (img1.empty())
{
std::cout << "파일이 없습니다." << std::endl;
return;
}
std::cout << img1.size << std::endl;
cv::Mat img2 = img1; // 복사 생성자 shallow copy
cv::Mat img3 = img1.clone(); // deep copy
cv::imshow("IMG1", img1);
cv::imshow("IMG2", img2);
cv::imshow("IMG3", img3);
cv::waitKey();
// 아무키를 누르면 원본 이미지가 변경
img1.setTo(cv::Scalar(0, 255, 255)); // img1을 노란색으로 바꿈
cv::imshow("IMG1", img1);
cv::imshow("IMG2", img2); // img2는 img1의 shallow copy여서 노란색으로 바뀐다
cv::imshow("IMG3", img3); // img3는 deep copy여서 노란색으로 바뀌지 않는다
cv::waitKey();
cv::destroyAllWindows();
}
<compile 결과>
<show_code_3_9,cpp>
#pragma once
#include <opencv2/opencv.hpp>
void show_code_3_9()
{
cv::Mat img1 = cv::imread("cat.bmp");
if (img1.empty())
{
std::cout << "파일이 없습니다." << std::endl;
return;
}
cv::Mat img2 = img1(cv::Rect(270, 120, 340, 240)); // 연산자 overloading, 직사각형 모양으로 선정한 위치 부분의 사진 자르기
cv::Mat img3 = img1(cv::Rect(270, 120, 340, 240)).clone(); // deep copy
cv::imshow("IMG1", img1);
cv::imshow("IMG2", img2);
cv::imshow("IMG3", img3);
cv::waitKey();
img2 = ~img2; // not, 비트 반전
cv::imshow("IMG2", img2);
cv::imshow("IMG3", img3);
cv::waitKey();
cv::destroyAllWindows();
}
<compile 결과>
<show_code_3_10.cpp>
#pragma once
#include <opencv2/opencv.hpp>
void show_code_3_10()
{
std::cout << "===========================================================================" << std::endl;
cv::Mat mat1(cv::Mat::zeros(10, 10, CV_8UC1)); // 모든 원소값이 0인 10 x 10 행렬
for (int i = 0; i < mat1.rows; ++i)
{
for (int j = 0; j < mat1.cols; ++j)
{
std::cout <<static_cast<int>(mat1.at<uchar>(i, j)) << "\t"; // mat1의 행을 i, 열을 j로 하여 행렬 원소값 출력
}
std::cout << std::endl; // row 하나가 완성되면 줄바꿈하여 다음 row 시작
}
std::cout << "===========================================================================" << std::endl;
cv::Mat mat2(cv::Mat::ones(10, 10, CV_8UC1)); // 모든 원소값이 1인 10 x 10 행렬
for (int i = 0; i < mat2.rows; ++i)
{
for (int j = 0; j < mat2.cols; ++j)
{
std::cout << static_cast<int>(mat2.at<uchar>(i, j)) << "\t"; // mat2의 행을 i, 열을 j로 하여 행렬 원소값 출력, get
}
std::cout << std::endl; // row 하나가 완성되면 줄바꿈하여 다음 row 시작
}
std::cout << "===========================================================================" << std::endl;
uchar value{ 0u }; // uniform initializer
for (int i = 0; i < mat1.rows; ++i)
{
for (int j = 0; j < mat1.cols; ++j)
{
mat1.at<uchar>(i, j) = ++value; // mat1 행렬의 원소에 1씩 증가한 값들을 대입, set
}
std::cout << std::endl;
}
std::cout << "===========================================================================" << std::endl;
for (int i = 0; i < mat1.rows; ++i)
{
for (int j = 0; j < mat1.cols; ++j)
{
std::cout << static_cast<int>(mat1.at<uchar>(i, j)) << "\t"; // mat1의 행을 i, 열을 j로 하여 행렬 원소값 출력
}
std::cout << std::endl; // row 하나가 완성되면 줄바꿈하여 다음 row 시작
}
std::cout << "===========================================================================" << std::endl;
}
<compile 결과>
<show_code_3_11,cpp>
#pragma once
#include <opencv2/opencv.hpp>
void show_code_3_11()
{
cv::Mat img1 = cv::imread("coins.png", cv::IMREAD_UNCHANGED); // 바꾸지 말라는 의미
if (img1.empty())
{
return;
}
std::cout << "PNG channel : " << img1.channels() << std::endl; // channel이 몇개인지 반환
std::cout << "PNG column : " << img1.cols << std::endl; // column 수 반환
std::cout << "PNG row : " << img1.rows << std::endl; // row 수 반환
std::cout << "PNG size : " << img1.size << std::endl; // size 타입 반환
if (img1.channels() == CV_8UC1) // channel이 1개라면 gray scale
{
std::cout << "Grayscale" << std::endl;
}
else if (img1.channels() == CV_8UC3) // channeldl 3개라면 color
{
std::cout << "Color" << std::endl;
}
else // 아무것도 아니면 png
{
std::cout << "PNG image" << std::endl;
}
}
<compile 결과>
<show_code_3_12.cpp>
#pragma once
#include <opencv2/opencv.hpp>
void show_code_3_12()
{
float data[] = {1.0f, 2.0f, 3.0f, 4.0f};
std::cout << "=====================" << std::endl;
cv::Mat mat1(2, 2, CV_32FC1, data); // 1차원 배열을 행렬 형태로 바꿔줌
std::cout << mat1 << std::endl;
std::cout << "=====================" << std::endl;
cv::Mat mat2 = mat1.inv(); // 역행렬로 만들어줌
std::cout << mat2 << std::endl;
std::cout << "=====================" << std::endl;
cv::Mat mat3 = mat1 * mat2; // 행렬과 행렬의 역행렬을 곱하면 I 행렬(identity matrix)가 만들어짐
std::cout << mat3 << std::endl;
std::cout << "=====================" << std::endl;
cv::Mat mat4 = mat1.t(); // 행과 열을 서로 바꿔줌(transpose, 전치)
std::cout << mat4 << std::endl;
std::cout << "=====================" << std::endl;
cv::Mat mat5 = mat1 + mat4; // 두 행렬의 합
std::cout << mat5 << std::endl;
std::cout << "=====================" << std::endl;
cv::Mat img1 = cv::imread("lenna.bmp");
cv::imshow("IMG1", img1);
cv::Mat img2 = img1.t(); // 불러온 이미지 transpose
cv::imshow("IMG2", img2);
cv::Mat img3 = img1 + 100; // 이미지의 픽셀값들을 전부 100씩 증가
cv::imshow("IMG3", img3);
cv::Mat img4 = cv::imread("lenna.bmp", cv::IMREAD_GRAYSCALE); // 이미지를 회색으로 불러옴
cv::imshow("IMG4", img4);
cv::Mat img5 = img4 + 100; // 회색 이미지의 픽셀값을 전부 100씩 증가시키면 밝기가 밝아진다
cv::imshow("IMG5", img5);
cv::Mat img6 = img4 - 50; // 회색 이미지의 픽셀값을 전부 50씩 감소시키면 밝기가 어두워진다
cv::imshow("IMG6", img6);
cv::waitKey();
cv::destroyAllWindows();
}
<compile 결과>
<show_code_3_13.cpp>
#pragma once
#include <opencv2/opencv.hpp>
void show_code_3_13()
{
cv::Mat img1 = cv::imread("lenna.bmp", cv::IMREAD_GRAYSCALE); // lenna.bmp 이미지를 회색 이미지로 불러옴
cv::Mat img2;
img1.convertTo(img2, CV_32FC1); // img1의 타입을 변경해줌
uchar data1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; // 배열을 만들어줌
cv::Mat mat1(3, 4, CV_8UC1, data1); // 배열을 mat1 행렬에 넣어줌
std::cout << "mat1 : \n" << mat1 << std::endl;
cv::Mat mat2 = mat1.reshape(0, 1); // 3 x 4 크기의 mat1 행렬을 1 x 12 크기의 행렬로 변환, reshape(channel, row) ((0, 1)은 channel은 0으로 바꾸지 않는다는 의미, 1은 row를 1로 바꾼다는 의미)
std::cout << "mat2 : \n" << mat2 << std::endl;
cv::Mat mat3 = cv::Mat::ones(1, 4, CV_8UC1) * 255; //모든 원소가 255로 구성된 1 x 4 크기의 행렬 mat3 생성
mat1.push_back(mat3); // 3 x 4 크기의 mat1 행렬에 1 x 4 크기의 mat3 행렬을 맨 마지막 행으로 추가
std::cout << "mat1 : \n" << mat1 << std::endl;
/*
cv::imshow("IMG2", img2);
cv::waitKey();
cv::destroyAllWindows();
*/
}
<compile 결과>
<show_code_3_16.cpp>
#pragma once
#include <opencv2/opencv.hpp>
void show_code_3_16()
{
cv::Scalar blue = 128; // Scalar 클래스 타입의 변수 blue에 128 정수 하나를 이용하여 초기화
std::cout << "blue : " << blue << std::endl;
cv::Scalar yellow(0, 255, 255); // Scalar 클래스 타입의 변수 yellow의 4개의 double형 원소 중 처음 세 원소가 0, 255, 255로 설정, 마지막 네번째 원소는 0으로 초기화
std::cout << "yellow : " << yellow << std::endl;
cv::Mat img1(800, 800, CV_8UC3, yellow);
cv::imshow("IMG1", img1);
cv::waitKey();
cv::destroyAllWindows();
}
<compile 결과>
'OpenCV' 카테고리의 다른 글
Chapter7 : 필터링 (0) | 2023.09.14 |
---|---|
Chapter6 : 영상의 산술 및 논리 연산 (0) | 2023.09.14 |
Chapter5 : 영상의 밝기와 명암비 조절 (0) | 2023.09.14 |
Chpater 4 : 이미지와 동영상 파일 다루기, 직선 그리기, 문자열 출력하기, 키보드 이벤트 처리하기, 마우스 이벤트 처리하기, 트랙바 사용하기, 마스크 연산, 연산 시간 측정, 여러 수치 측정 함수 (4) | 2023.09.13 |
Chapter2 : 이미지 불러오기 (0) | 2023.09.12 |