leggiero-crescendo / Dev-perception

자율주행데브코스 인지과정 5기 기록
1 stars 0 forks source link

OpenCV C++ Basic #3

Open leggiero-crescendo opened 1 year ago

leggiero-crescendo commented 1 year ago

영상 입출력

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

using namespace std;
using namespace cv;

int main()
{
    cv::Mat img = cv::imread("lenna.bmp"); //이미지 불러오기. 흑백을 불러오려면 cv::IMREAD_GRAYSCALE 인자 추가.

    if (img.empty())
    {
        std::cerr << "Image load failed!" << std::endl; // 이미지 load에 실패했을 경우 에러메세지 출력 후 종료.
        return -1;
    }

    cv::namedWindow("Image"); // "Image"라는 이름의 window 생성
    cv::imshow("Image", img); // "Image" 윈도우에 img를 출력.

    cv::waitKey(0); // 키 입력을 입력한 시간(ms)만큼 기다림. 0초일 경우 무한대.
    cv::destroyAllWindows();
    return 0;
}
leggiero-crescendo commented 1 year ago

cv::Mat

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

using namespace std;
using namespace cv;

int main()
{
    cv::Mat img = cv::imread("lenna.bmp"); 

    std::cout << "Width: " << img.cols << std::endl; // Width :512
    std::cout << "Height: " << img.rows << std::endl; // Height : 512
    std::cout << "Channels: " << img.channels() << std::endl; // Channels : 3

    if (img.type() == CV_8UC1)
        std::cout << "img is a grayscale image" << std::endl;
    else if(img.type() == CV_8UC3)
        std::cout << "img is a truecolor image" << std::endl;
}

초기화방법

void MatOp1()
{
    cv::Mat img1;   // empty matrix

    // 특정한 크기를 지정하여 생성하는 방법

    cv::Mat img2(480, 640, CV_8UC1);        // (h(row), w(col), unsigned char 1-channel)
    cv::Mat img3(480, 640, CV_8UC3);        // unsigned char, 3-channels
    cv::Mat img4(cv::Size(640, 480), CV_8UC3);  // Size(width, height)

    cv::Mat img5(480, 640, CV_8UC1, cv::Scalar(128));       // initial values, 128
    cv::Mat img6(480, 640, CV_8UC3, cv::Scalar(0, 0, 255)); // initial values, red

    cv::Mat mat1 = cv::Mat::zeros(3, 3, CV_32SC1);  // 0's matrix : zeros는 정적 멤버 함수임
    cv::Mat mat2 = cv::Mat::ones(3, 3, CV_32FC1);   // 1's matrix
    cv::Mat mat3 = cv::Mat::eye(3, 3, CV_32FC1);    // identity matrix

    float data[] = {1, 2, 3, 4, 5, 6};
    cv::Mat mat4(2, 3, CV_32FC1, data); // 4번째 인자에 참조할 주소 값을 넣어서 mat4에 연결하는 것
        /*
    data[0] = 100;
    std::cout << mat4 << std::endl; // [100,2,3][4,5,6] 이런식으로 값이 동기화가 됨! (데이터 값을 카피하는 것이 아니라 주소를 참조하기때문에)
    */
    // 1,2,3,4,5,6 으로 값이 지정되있는 행렬을 2행 3열의 mat 형태로 만들기 위한 방법
    cv::Mat mat5 = (Mat_<float>(2, 3) << 1, 2, 3, 4, 5, 6);
    cv::Mat mat6 = Mat_<uchar>({2, 3}, {1, 2, 3, 4, 5, 6});

    // create는 mat class의 생성자와 같지만 초기값을 지정할 수 있는 4번째 인자는 지원 하지 않음
    mat4.create(256, 256, CV_8UC3); // uchar, 3-channels
    mat5.create(4, 4, CV_32FC1);    // float, 1-channel

    mat4 = cv::Scalar(255, 0, 0); // 모든 픽셀을 파란색으로
    mat5.setTo(1.f); // 모든 엘리먼트의 값을 1.f로
}

참조, 복사 ( = : 얕은 복사 혹은 참조(동기화), clone or copyTO : 깊은 복사)

   // img1 ~ 3은 같은 영상 (4번째 인자가 img1을 가르치게 됨)
    cv::Mat img1 = cv::imread("dog.bmp");
    cv::Mat img2 = img1; // 초기화 cv::Mat img2(img1);와 동일함
    cv::Mat img3;
    img3 = img1; // 대입

    // 깊은 복사
    cv::Mat img4 = img1.clone(); // img1 -> img4
    cv::Mat img5;
    img1.copyTo(img5); // img1 -> img5

   // 여기서 아래를 실행하면
    img1.setTo(Scalar(0,255,255)));
   // img1 ~ 3 영상이 모두 0,255,255로 변함

부분 추출방법

    cv::Mat img1 = cv::imread("cat.bmp");
    cv::Mat img2 = img1(cv::Rect(220, 120, 340, 240)); // (x,y,w,h) 참조
    cv::Mat img3 = img1(cv::Rect(220, 120, 340, 240)).clone(); // 복사

    img2 = ~img2; // img2 영상을 반전시키기 (img1, 2 상화 참조 중 따라서 img 2에서 반전 시키면 img1 의 2부분이 같이 반전됨)

픽셀 값 참조


void MatOp4()
{
    cv::Mat mat1 = Mat::zeros(3, 4, CV_8UC1);

    for (int y = 0; y < mat1.rows; y++) {
        for (int x = 0; x < mat1.cols; x++) {
            mat1.at<uchar>(y, x)++;
        }
    }

    for (int y = 0; y < mat1.rows; y++) {
        uchar* p = mat1.ptr<uchar>(y);

        for (int x = 0; x < mat1.cols; x++) {
            p[x]++;
        }
    }

    for (cv::MatIterator_<uchar> it = mat1.begin<uchar>(); it != mat1.end<uchar>(); ++it) {
        (*it)++;
    }

    std::cout << "mat1:\n" << mat1 << std::endl;
}

기초 행렬 연산

    float data[] = {1, 2, 3, 4};
    cv::Mat mat1(2, 2, CV_32FC1, data);
    cv::Mat mat2 = mat1.inv();
    std::cout << "mat1:\n"  << mat1 << std::endl;
    std::cout << "mat2 = mat1 inverse:\n"  << mat2 << std::endl;

    std::cout << "mat1.t():\n"  << mat1.t() << std::endl;
    std::cout << "mat1 + 3:\n"  << mat1 + 3 << std::endl;
    std::cout << "mat1 + mat2:\n"  << mat1 + mat2 << std::endl;
    std::cout << "mat1 * mat2:\n"  << mat1 * mat2 << std::endl;
leggiero-crescendo commented 1 year ago

주요클래스

leggiero-crescendo commented 1 year ago

동영상 입력

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

int main()
{
    cv::VideoCapture cap;
    //cap.open(0);
    cap.open("../resouces/test_video.mp4");

    // cap input check
    if (!cap.isOpened()) {
        std::cerr << "Camera open failed!" << std::endl;
        return -1;
    }

    int w = cv::cvRound(cap.get(cv::CAP_PROP_FRAME_WIDTH));
    int h = cv::cvRound(cap.get(cv::CAP_PROP_FRAME_HEIGHT));

    std::cout << "width: " << w << std::endl;
    std::cout << "height: " << h << std::endl;

    cv::Mat frame;
    cv::Mat edge;

    while (true) {
        cap >> frame;

        // frame check
        if (frame.empty()) {
            std::cerr << "Empty frame!" << std::endl;
            break;
        }

        cv::Canny(frame, edge, 50, 150); // Edge 영상을 만드는 방법
        cv::imshow("frame", frame);
        cv::imshow("edge", edge);
// cap input check
        if (cv::waitKey(1) == 27) // ESC 0으로 하면한프레임 씩 보여지게 됨 
            break;                   //waitKey(1) 같이 무한정 기다리진 않도록 해야함 FPS에 맞춰서!
    }

    cap.release();
    cv::destroyAllWindows();

}

Untitled

동영상 저장

leggiero-crescendo commented 1 year ago

OpenCV 그리기함수

leggiero-crescendo commented 1 year ago

이벤트 처리 (키보드, 마우스, 트랙바)