Code/C++

[OpenCV C++] 이미지 불러오고 저장하기 (Ubuntu CMakeLists, Command args 연결, Clion)

capaca 2023. 4. 20. 00:15

2023.04.19 - [Code/CMake] - [Ubuntu] VSCode CMake build&debug (C++)
2023.04.20 - [Code/C++] - [OpenCV C++] 이미지 저장하고 불러오기 , 창닫기 (CV 함수 설명)
 
🐣 목적 : CPP 파일을 Build 한 후 object file을 실행시킬 경우 args를 받아(입력 이미지, 출력이미지) 실행시키기!
🐣 방법 1 : CMakefile과 cpp 파일을 생성하고 clion으로 실행시킬 때 args를 넣기
🐣 방법 2 : CMakefile과 cpp 파일을 생성하고 shell 창을 통해 실행 시키기 
 
 

실행결과 result.png 또는 원하는 argv로 저장!


📌 공통과정

- 아래와 같은 구조로 폴더를 구성해 준다

.
├── CMakeLists.txt #1
├── examples
│   ├── lenna.bmp
│   └── imgread.cpp
├── main.cpp
├── modules
│   ├── CMakeLists.txt #2
│   ├── module1
│      ├── CMakeLists.txt #3
│      ├── include > module1 > ClassMat.hpp
│      └── src > ClassMat.cpp
│   
└── thirdparty
    │
    └── OpenCV
        ├── build
        ├── install
        └── opencv

2023.04.18 - [Code/CMake] - Ubuntu - OpenCV 원하는 폴더에 build & Install
-> 이 부분을 참고해서 thirdparty내에 설치하면 된다 (단 -DCMAKE_BUILD_TYPE=Debug 모드로 진행)
 
 


총 3가지의 CMakeLists.txt를 작성해야하는데 
#1은 전체 폴더에서 링크를 연결해준다고 생각하면 되고,
2번은 module1과 #1을 연결 module1 내부는 include를 찾을 수 있도록 해준다

 
CMakeLists.txt 🧡 #1

cmake_minimum_required(VERSION 3.16)
project(<project_name> LANGUAGES CXX) # CXX -> C++

set(CMAKE_CXX_STANDARD 14) # CMAKE_ : Depends on Cmake
set(CMAKE_CXX_STANDARD_REQUIRED ON) # only do 14 versions of cmake

add_subdirectory(modules)

add_executable(<project_name>  main.cpp) # (project-name project.cpp)

# add_excutable을 통해서 실행할 파일을 생성
add_executable(read_img examples/imgread.cpp)

# target_link_libraries : target libraries 연결
target_link_libraries(read_img PRIVATE
        module1
        )

CMakeLists.txt 💚 #2

add_subdirectory(module1) // 하위 directory 연결을 위한 징검다리!

CMakeLists.txt 💜 #3

cmake_minimum_required(VERSION 3.16)
project(module1 LANGUAGES CXX) # CXX -> C++

set(CMAKE_CXX_STANDARD 14) # CMAKE_ : Depends on Cmake
set(CMAKE_CXX_STANDARD_REQUIRED ON) # only do 14 versions of cmake

set(MODULE1_SOURCE_FILES
        src/ClassMat.cpp
        ) # Create a variable : MODULE1_SOURCE_FILES

add_library(module1
        ${MODULE1_SOURCE_FILES}
        ) # 위 변수에 있는 모든 소스파일들을 넣으려고 함

# REQUIRED : 없으면 build 안 하겠다
find_package(OpenCV REQUIRED HINTS ${CMAKE_SOURCE_DIR}/thirdparty/OpenCV/install/lib/cmake/opencv4)

if (OpenCV_FOUND)
    message(STATUS "OpenCV Found! - ${OpenCV_DIR}")
endif()
#include_directories() # global 하위 cmake directory

target_include_directories(module1 PUBLIC
        include
        ${OpenCV_INCLUDE_DIRS}
        ) # target header files folder

target_link_libraries(module1 PUBLIC
        ${OpenCV_LIBS} # link libraries 하고 싶어요!
        )

이후에 hpp, cpp file들을 작성해 주자 

🐍ClassMat.hpp🐍

# include "opencv2/opencv.hpp"

class ClassMat
{
public:
    ClassMat() = default;

private:
    cv::Mat cv_mat_;
};

🦕ClassMat.cpp🦕

#include "module1/ClassMat.hpp"

🐬imgread.cpp🐬

#include <iostream>
#include <typeinfo> // type information
#include <unistd.h> // dir

#include "opencv2/opencv.hpp"


int main(int argc, char* argv[]) // argc : input num, argv : input char s  // char* argv[]와 char **argv는 모두 문자열 포인터 배열을 나타
{
    std::string input_img;
    std::string output_img;

// argc 가 몇 개인지 확인한 후 값을 사용할 것인지 아닌지 판단
    if (argc == 2){
        input_img = argv[1];
        output_img = "./examples/result.png";
        std::cout << "here!" << std::endl;
    }
    else if(argc == 3){
        input_img = argv[1];
        output_img = argv[2];
    }
    else{
        input_img = "./examples/lenna.bmp";
        output_img = "./examples/result.png";
    }

// directory가 어디인지 궁금해서 넣어둔 부분 의미없음
    char cwd[1024];
    if (getcwd(cwd, sizeof(cwd)) != nullptr) {
        std::cout << "Current working directory: " << cwd << std::endl;
    } else {
        std::cerr << "Failed to get current working directory\n";
        return 1;
    }

// 1. imread
    cv::Mat src = cv::imread(input_img,  cv::IMREAD_GRAYSCALE); // cmake-build-debug에서 실행됨으로,,,, 상위단으로 올라가서 다시 exaple로,,

// 2. file check
    if (src.empty()) {
        std::cerr << "Image laod failed!" << std::endl;
        return -1;
    }
    
// 3. img 조작
    cv::Mat dst = 255 - src;

// 4. 조작된 이미지 저장 imwrite
    cv::imwrite(output_img, dst);
    
// 5. 결과확인
    cv::imshow("src", src);
    cv::imshow("dst", dst);
    cv::waitKey();
    cv::destroyAllWindows();
}

 


🪄 방법 1

- 망치모양을 통해 빌드한 후 실행 시킬 경우 Run > Edit Configurations

🪄 방법 2

- build 후 shell 창에 입력

./cmake-build-debug/read_img ./examples/lenna.bmp
# <실행 파일의 경로> <read image arg> <write image arg>