안녕하세요 

오늘은 영상처리 OPENCV를 공부한것을 정리해볼까 합니다. 

예전에 올렸을때는 기본함수가 어떤것이 있는지에 대해서 정리해서 올렸는데요.

함수정리 위주로 가니 효율적이지 않다고 생각이 들어서 예제들을 구현해보면서 함수에 대해서 설명하도록 하겠습니다.


저번에 Mat함수를 가장 많이 사용한다고 했는데요 이러한 Mat함수를 통해서 회전과 크기와 출력 화면의 크기도 조절할수가 있습니다.


그중에서 가장 큰 특징은 Matlab에서와 같이 화면을 읽어 올수가 있습니다. 


화면을 불러오기 위해서는 cv::MAT image = (경로,영상의 형태)로 출력을 하면되는데요 

어떻게 해야될지 예제를 보여드리도록 하겠습니다. 


그전에 영상을 출력하기 위해서는 클래스를 불러와야되는데요 

1
2
3
4
5
6
7
8
9
#include <opencv2/core/core.hpp>                  //Mat 클래스를 포함한 기본 자료구조와 여러 함수가 공유하는 클래스
#include <opencv2/highgui/highgui.hpp>             //윈도우 화면과 마우스 등을 제어하는 사용자 인터페이스 함수
#include <opencv2/imgproc/imgproc.hpp>             //영상처리 함수
#include <opencv2/features2d/features2d.hpp>      //특징검출, 기술자, 매칭함수
#include <opencv2/objdetect/objdetect.hpp>         //얼굴과 사람을 포함한 다양한 물체 검출 함수
#include <opencv2/video/video.hpp>                 //연속 영상과 모션 추정함수 
#include <opencv2/calib3d/calib3d.hpp>             // 카메라 캘리브레이션과 3차원 복원 함수
#include <opencv2/ml/ml.hpp>                      //기계 학습
#include <opencv2/flann/flann.hpp>                 //군집화와 다차원 공간탐색
cs

글씨가 너무 작게 나오네요;; 이렇게 여러 클래스들이 있습니다. 


이러한 클래스중에서 기본영상처리와 영상을 띄우긴 위해서는 Core,highgui, imgproc 총 3개만 사용하면됩니다. 

먼저 처음 영상을 띄어보는 예제를 보여드리겠습니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <stdlib.h>
 
using namespace cv;
using namespace std;
 
int main() {
    Mat image = imread("lena30.jpg");
 
    namedWindow("image");             //영상 이름 설정
    imshow("image", image);            //영상 출력
    waitKey(0);                     //영상 띄우기
    return 0;
}
cs

lena(레나) 이미지 출처 : https://bellard.org/bpg/lena.html

파일을 예제 처럼 설정할려면 프로젝트 파일안에 이미지를 넣으면 됩니다.

 

출력 이미지

 

위의 예제처럼 영상을 띄우긴 위해서는 imread함수를 사용하여 영상을 띄우면 되는데요

띄우기 위해서는 naemdWindow를 사용하여야합니다. (이름을 지정하지 않고 imshow 함수안에 이름을 넣어도 됩니다.)

이때 영상을 계속회서 화면에 출력하기 위해서는 waitKey()를 사용합니다. 

이 waitKey 괄호안에 필요한 키를 입력하여 영상을 끌수가 있습니다. 

 

이번에 이러한 이미지를 가지고 이미지에 노이즈를 추가시켜보겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <stdlib.h>
 
using namespace cv;
using namespace std;
 
void salt(Mat image, int n) {
 
    int i, j;
    for (int k = 0; k < n; k++) {
 
        i = rand() % image.cols; //rand() : 렌덤함수입니다. 
        j = rand() % image.rows;
    
        if (image.type() == CV_8UC1) {//그레이 영상에 노이즈 추가
            image.at<uchar>(j, i) = 255//흰색 노이즈 추가
        }
        else if (image.type() == CV_8UC3) {//컬러 영상에 노이즈 추가
            image.at<Vec3b>(j, i)[0= 0;
            image.at<Vec3b>(j, i)[1= 0;
            image.at<Vec3b>(j, i)[2= 0;
        }
    }
}
 
 
int main() {
    Mat image = imread("lena30.jpg");
    //잡음을 추가하기
    salt(image, 80000); //노이즈 추가하기
 
    namedWindow("image");
    imshow("image", image);
    waitKey(0);
    return 0;
}
cs

 

 

 

이렇게 노이즈를 추가할수가 있습니다.

코딩을 해서 돌리다보면 이러한 오류내용이 뜰때가 있을껍니다.

이경우는 경로에 이미지가 없다는 의미임으로 경로가 바로 됬는지 파일명과 형식은 잘되어있는지 꼭 확인해주세요

 

영상을 불러왔으니 영상을 저장해보는 예제를 해보도록 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
 
int main()
{
    Mat image = imread("lena30.jpg", IMREAD_COLOR);
    CV_Assert(image.data);                               //영상의 예외 처리
 
    vector<int> params_jpg, params_png;
    params_jpg.push_back(IMWRITE_JPEG_QUALITY);          //JPG로 화질 설정
    params_jpg.push_back(50);
    params_png.push_back(IMWRITE_PNG_COMPRESSION);       //PNG 압축레벨 저장
    params_png.push_back(9);
 
    imwrite("lenatest1.jpg", image);                     //행렬 영상파일로 저장
    imwrite("lenatest2.jpg", image, params_jpg);         //지정화질로 저장
    imwrite("lenatest3.png", image, params_png);     
    imwrite("lenatest4.bmp", image);                     //BMP로 화면저장
}
cs

 

 

 

 

영상이 이렇게 4개가 추가적으로 생긴것을 확인할수가 있습니다.

 

이제는 영상을 가지고 뒤집고 움직여 보겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <opencv2/opencv.hpp>
 
using namespace cv;
using namespace std;
 
int main()
{
    Mat image = imread("lenatest1.jpg", IMREAD_COLOR);
    CV_Assert(image.data);
 
    Mat x_axis, y_axis, xy_axis, rep_img, trans_img;
    flip(image, x_axis, 0); //x축 기준 상화 뒤집기
    flip(image, y_axis, 1); //y축 기준 좌우 뒤집기
    flip(image, xy_axis, -1);
 
    repeat(image, 12, rep_img);
    transpose(image, trans_img);
 
    imshow("image", image), imshow("x_axis", x_axis);
    imshow("y_axis", y_axis), imshow("xy_axis", xy_axis);
    imshow("rep_img", rep_img), imshow("trans_img", trans_img);
    waitKey();
    return 0;
}
cs

 

결과 영상이 많이 뜨네요 이렇게 많은 함수들이 있습니다.

그중에서 예제에서 보시면 숫자 0,1,-1를 넣어주는데요

이것은 0경우는 x축기준으로 위아래로 뒤집는다는 의미고 1은 y축기준으로 좌우, -1은 양축으로 뒤집는다는 의미입니다.

 

이번에 이러한 영상을 가지고 히스토그램 평활화에 대해서 해보겠는데요

히스토그램이란 무엇일까요?

 

히스토그램이란 영상에서 한 픽셀마다 가지는 명암값이라고 정의할수가 있습니다.

저의가 grayscale로 영상을 봤을때 어둡고 밝은 이미지를 보았을떄 히스토그램이 왼쪽이나 오른쪽으로 치우처져있는 것을 볼수가 있는데요

이러한 영상의 명암값을 개선하기위해서는 대표적으로 히스토그램 평활화 과정과 히스토그램 스트레칭이 있습니다.

 

첫번째로 히스토그램 스트래칭에 대해서 설명하겠는데요

이과정은 말 그대로 히스토그램의 분포를 잡아서 명암값의 분포를 늘리는것입니다.

즉 원본이미지의 히스토그램의 최소값을 0으로 움직이고 히스토그램의 최대값을 256의 값으로 움직여서 히스토그램이 골고루 나오도록하게하는것인데요

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
 
void  calc_Histo(const Mat& image, Mat& hist, int bins, int range_max = 256)
{
    int        histSize[] = { bins };            // 히스토그램 계급개수
    float   range[] = { 0, (float)range_max };        // 히스토그램 범위
    int        channels[] = { 0 };                // 채널 목록
    const float* ranges[] = { range };
 
    calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);
}
 
void draw_histo(Mat hist, Mat &hist_img, Size size = Size(256200))
{
    hist_img = Mat(size, CV_8U, Scalar(255));
    float  bin = (float)hist_img.cols / hist.rows;
    normalize(hist, hist, 0size.height, NORM_MINMAX);
 
    for (int i = 0; i<hist.rows; i++)
    {
        float idx1 = i * bin;
        float idx2 = (i + 1* bin;
        Point2f pt1 = Point2f(idx1, 0);
        Point2f pt2 = Point2f(idx2, hist.at <float>(i));
 
        if (pt2.y > 0)
            rectangle(hist_img, pt1, pt2, Scalar(0), -1);
    }
    flip(hist_img, hist_img, 0);
}
 
int search_valueIdx(Mat hist, int bias = 0)
{
    for (int i = 0; i < hist.rows; i++)
    {
        int idx = abs(bias - i);
        if (hist.at<float>(idx) > 0)    return idx;
    }
    return -1;
}
 
int main()
{
    Mat image = imread("lena30.jpg"0);
    CV_Assert(!image.empty());
 
    Mat hist, hist_dst, hist_img, hist_dst_img;
    int  histsize = 64, ranges = 256;
    calc_Histo(image, hist, histsize, ranges);
 
    float bin_width = (float)ranges / histsize;
    int low_value = (int)(search_valueIdx(hist, 0* bin_width);
    int high_value = (int)(search_valueIdx(hist, hist.rows)* bin_width);
    cout << "high_value = " << high_value << endl;
    cout << "low_value = " << low_value << endl;
 
    int d_value = high_value - low_value;
    Mat  dst = (image - low_value) * (255.0 / d_value);
 
    calc_Histo(dst, hist_dst, histsize, ranges);
    draw_histo(hist, hist_img);
    draw_histo(hist_dst, hist_dst_img);
 
    imshow("image", image);
    imshow("dst-stretching", dst);
    imshow("img_hist", hist_img);
    imshow("dst_hist", hist_dst_img);
    waitKey();
    return 0;
}
cs

 

 

 

이러한 스트래칭 방법은 원리는 아주 간편해서 좋습니다.

하지만 아주 작은 값이 최대값이나 최소값에 위치하면 개선되는것을 볼수가 없는데요

이것을 해결하기 위해서 히스토그램 평활화과정이 있습니다.

 

 

평화화 과정은 4가지 과정을 거쳐서 나오게 되는데요

첫번째로 히스토그을 계산합니다.

두번째로 히스토그램 빈도값에서 누적 빈도수(누적합)을 계산합니다.

세번째로 누적 빈도수를 정규화합니다. (nomalization)

네번째로 결과 화소값 = 정규화 누적합 * 최대 화소값에 맞춰줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <opencv2/opencv.hpp>
 
using namespace cv;
using namespace std;
 
void  calc_Histo(const Mat& image, Mat& hist, int bins, int range_max = 256)
{
    int        histSize[] = { bins };            // 히스토그램 계급개수
    float   range[] = { 0, (float)range_max };        // 히스토그램 범위
    int        channels[] = { 0 };                // 채널 목록
    const float* ranges[] = { range };
 
    calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);
}
 
void draw_histo(Mat hist, Mat &hist_img, Size size = Size(256200))
{
    hist_img = Mat(size, CV_8U, Scalar(255));
    float  bin = (float)hist_img.cols / hist.rows;
    normalize(hist, hist, 0, size.height, NORM_MINMAX);
 
    for (int i = 0; i<hist.rows; i++)
    {
        float idx1 = i * bin;
        float idx2 = (i + 1* bin;
        Point2f pt1 = Point2f(idx1, 0);
        Point2f pt2 = Point2f(idx2, hist.at <float>(i));
 
        if (pt2.y > 0)
            rectangle(hist_img, pt1, pt2, Scalar(0), -1);
    }
    flip(hist_img, hist_img, 0);
}
 
void create_hist(Mat img, Mat &hist, Mat &hist_img)
{
    int histzise = 256, range = 256;
    calc_Histo(img, hist, histzise, range);
    draw_histo(hist, hist_img);
}
 
int main()
{
    Mat image = imread("lena30.jpg"0); //영상 읽기
    CV_Assert(image.data);
 
    Mat hist, dst1, dst2, hist_img, hist_img1, hist_img2;
    create_hist(image, hist, hist_img); //히스토그램 및 그래프 그리기
 
    //히스토그램 누적합 계산
    Mat accum_hist = Mat(hist.size(), hist.type(), Scalar(0));
    accum_hist.at<float>(0= hist.at<float>(0);
 
    for (int i = 1; i < hist.rows; i++) {
        accum_hist.at<float>(i) = accum_hist.at<float>(i - 1+ hist.at<float>(i);
    }
 
    accum_hist /= sum(hist)[0];
    accum_hist *= 255;
    dst1 = Mat(image.size(), CV_8U);
    for (int i = 0; i < image.rows; i++) {
        for (int j = 0; j < image.cols; j++) {
            int idx = image.at<uchar>(i, j);
            dst1.at<uchar>(i, j) = (uchar)accum_hist.at<float>(idx);
        }
    }
 
    equalizeHist(image, dst2);
    create_hist(dst1, hist, hist_img1);
    create_hist(dst2, hist, hist_img2);
 
    imshow("User_hist", hist_img1), imshow("dst1_User", dst1);
    waitKey();
    return 0;
}
 
cs

 

 

 

이 과정은 밝은 영역부분을 다시 재편성해서 골고루 펴는 방법인데요. 흔히 분포의 균등이라는 방법이라고 합니다.

이방법을 통해서 영상의 밝기가 골고루 분포하게 되어서 어두운부분은 밝아지고 너무 밝은 부분은 어두워지는 효과를 볼수가 있습니다.

 

이렇게 위의 식과 같이 엄청 길게 나오지만 ㅋㅋ

정작 함수 equalizeHist(image, dst2);사용하면 바로 히스토그램 평활화가 된답니다. ㅎ

 

오늘은 여기까지 정리하겠습니다.

도움이 되셨으면 좋겠네요

수고하셨습니다.

반응형

'영상처리 > opencv' 카테고리의 다른 글

opencv 기본함수들 정리  (0) 2017.05.30
opencv 설치  (0) 2017.05.25

안녕하세요 오늘은 opencv에서 기본적으로 보는 함수에 대해서 책을 보고 나름 정리를 해보려고 합니다. ㅎㅎ

MATLAB 을 이용하여서 영상처리는 함수나 기본적으로 제공해주는것이 많아서 괜찮았었는데요 opencv를 사용해보니까 또 다른 느낌이네요 ㅎㅎ

부족하지만 정리를 해보았습니다. 


저번에 정리했던 opencv를 라이브러리나 경로를 추가한후에 기본적인 함수를 하나하나씩 정리를 해보았는데요 
밑의 주석에 설명을 적어놓았으니 보시면 될것 같습니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
 
int main() //대소문자 구별해야된다. 
{
    //point 객체 선언 방식 
    //point를 선언하기 위해서는 p(x,y)에 해당하는 값을 선언해야된다. 
    cv::Point_<int> pt1(100200);
    cv::Point_<float> pt2(92.3f, 125.23f);
 
    //point_ 객체 간결한 선언 방식
    //point를 간결하게 선언하기 위해서 이렇게 표현할수가 있다. 
    cv::Point2i pt3(12069);
    cv::Point2f pt4(0.3f, 0.f), pt5(0.f, 0.4f);
 
    cv::Point pt6 = pt1 + (cv::Point) pt2; //반드시 객체의 type은 동일해야됩니다. 
 
    std::cout << "pt6=" << pt6.x << "," << pt6.y << std::endl;
    std::cout << "pt6=" << pt6 << std::endl;
    std::cout << "pt6비교=" << (pt1 == pt6) << std::endl; 
    std::cout << "pt3와 pt6의 내적=" << pt3.dot(pt6) << std::endl;
    
    //위의 문장처럼 std를 넣어주거나 cv를 계속해서 넣어줘야함으로 
    //using namespace std, using namespace cv ,를 넣어주는것이 좋다. 
    //point3_자료는 3차원 을 구성하는 자료입니다. 
    Point3_<int> pt7(123);
    Point3_<float> pt8(23.f, 12.f, 45.f);
    //간략하게 적어도 됩니다. 
 
    Point3i pt9(123);
    Point3f pt10(23.f, 12.f, 45.f);
    //계산은 밑의 식과 동일하게 작용이 된다. 
 
    //size_ 같은 경우에서는 이미지의 크기나 사격형의 크기를 나타내는 역할을 한다. 
    Size sz1(200400);
    Size2d sz2(232.4123.2); //이미지가 2D이므로 2를 넣어줍니다. 
 
    cout << "sz1.width=" << sz1.width << endl;
    cout << "sz1 넓이=" << sz1.area() << endl;
    cout << "[sz1]=" << sz1 << endl;
    
    return 0;
}
cs

 

이 위에까지는 정리를 하자면 기본적인 point 즉 X,Y 축의 좌표를 나타내고 Size_ 클래스를 통한 코딩들이였는데요 


이제부터 Mat 클라스에 대해서 정리를 해보겠습니다.  

Mat 클래스의 객체를 선언할때에는, 행렬의 자료형에 특히 주위해야되기 때문에 이런 옵션들을 잘 참고 하셔야됩니다. 


행렬의 자료형 종류는 밑의 표이외에 더 많은 자료가 있지만 대표적으로 사용하는 데이터 형들 입니다. 

데이터형  

설명 

depth 값 

CV_8U 

 uchar(unsigned char)

 CV_8S

signed char 

 CV_16U

unsigned short int

 CV_16S

 signed short ing

 3

 CV_32S

int 

 4

 CV_32F

float 

 5

 CV_64F

double 

 6



Mat클래스 코딩을 정리해보았고 주석처리로 설명을 적어놓았습니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
 
int main() //대소문자 구별해야된다. 
{
    float data[] = {
        1.2f, 2.3f, 3.2f,
        4.5f, 5.f, 6.5f,
    };
    //double , short, float
    double  a = 32.12345678, b = 2.7;
    short c = 400;
    float d = 10.f, e = 11.f, f = 13.f;
 
    //Mat 객체 선엉 방법
    Mat m1(23, CV_8U);
    Mat m2(23, CV_8U, Scalar(300));
    Mat m3(23, CV_16S, Scalar(300));
    Mat    m4(23, CV_32F, data);
 
    //행렬 선언
    Mat_<int> m7(23);
    Mat_<uchar> m8(34100);
    Mat_<short> m9(45, c);
 
    // ones, zeros , eye를 사용한 객체 eye경우는 대각선
// 이라고 생각하면된다.

    Mat m5 = Mat::ones(35, CV_8UC1);
    Mat m6 = Mat::eye(33, CV_8UC1);
    //Size_ 객체 MAT 객체 선언,
    Size sz(23);
 
    
    cout << m1 << endl;
    cout << m2 << endl;
    cout << m7 << endl;
    cout << m8 << endl;
    cout << m9 << endl;
    return 0;
}
 
cs

 

 


Mat클래스를 선언하게 되면 다양한 맴버 변수들이 저장되게 되는데요 

이 정보들은 밑에 있는 표에 의해서 변수들을 확인할 수 있습니다. 

항목 

 설명

멤버 변수  

Mat::dims 

 차원수

 Mat::rows

 행의 개수

 Mat::cols

열의 개수 

 Mat::data

행렬 원소 데이터에 대한 포인터 

 Mat::step

행렬의 한 행이 차지하는 바이트 수 

 멤버

메서드

 Mat::channels()

 행렬의 채널 수 반환 

 Mat::depth()

 행렬의 깊이(행렬의 자료형)값 반환 

 Mat::elemSize()

행렬의 한 원소에 대한 바이트 크기 반환 

 Mat::elemSize1()  행렬의 한 원소의 한 채널에 대한 바잍트 크기 반환 

 Mat::empty()

행렬 원소가 비어있는지 여부 반환

 Mat::isSubmatrix()

참조 행렬인지 여부 반환

 Mat::size()

행렬의 크기를 Size형으로 반환

 Mat::step1()

step을 elemSize1()로 나누어서 정규화된 step 반환 

 Mat::total()

행렬 원소의 전체 개수 반환 

  Mat::type

행렬의 데이터 타임(자료형 + 채널수 )반환 

자료형으로 상위 3비트 + 채널 수로 하위 3비트



Mat 클래스에서 = 연산자 같은 경우에서는 Scalar에 대한 할당 연산을 지원합니다. 

예로들어서 m1 = 100을 하게 되면 행렬의 모든 원소는 100에 해당하는 값을 가지게 됩니다. 


Mat클래스는 크기와 형태가 변형이 가능합니다.

MAT::resize함수와 reshape()등 여러 함수를 사용하여서 크기를 조절할수가 있습니다.

 

또 Mat 복사 및 자료형 변환이 있습니다. 이것을 사용하는 이유는  

영상처리를 하다보면 이진화 모폴로지 연산등 전처리 작업이나 히스토그램 계산, 객체 외각 검출 등 다양한 처리 작업에서 원본 영상이 변경이 될수 있기 때문에 원본의 복사본을 사용해야한다고 합니다.

그렇기 위해서는 원본의 영상을 복사본을 만들수 있어야되는데요

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
    Mat m = (Mat_<uchar>(24<< 12345678);
    cout << "[m]=" << endl << m << endl << endl;
    // 행의 기준으로 기존 행의 크기를 변경합니다.
    m.resize(1);
    cout << "m.resize(1)= " << endl << m << endl;
    m.resize(3);
    cout << "m.resize(3)= " << endl << m << endl;
    
    
    double data[] = {
        1.1,2.2,3.3,4.4,
        5.5,6.6,7.7,8.9,
        9.9,10,11,12
    };
    Mat m1(34, CV_64F, data);
    Mat m2 = m1, clone(); //같은 데이터 값을 복사해서 새로운 행렬을 반환한다.
    Mat m3, m4;
    m1.copyTo(m3); // 행렬 데이터로 인자로 입력된 mat행렬에 복사한다. 
    m1.convertTo(m4, CV_8U); //데이터 타입도 mat행렬에 복사한다. 
 
    cout << "m1=\n" << m1 << endl;
    cout << "m2=\n" << m2 << endl;
    cout << "m3=\n" << m3 << endl;
    cout << "m4=\n" << m4 << endl;
    return 0;
 
}
cs

 

 

 

 

Mat_클래스는 정말 많은 것 같네요 ㅎㅎ

 

 

그 이후는 다음번에 또 정리해서 올리도록 하겠습니다.

오늘은 요기까지 하겠습니다. 아직 많이 부족한게 많네요 ㅎㅎ

수고하셨습니다.

반응형

'영상처리 > opencv' 카테고리의 다른 글

opencv영상띄우기와 히스토그램평활화  (0) 2017.08.02
opencv 설치  (0) 2017.05.25

안녕하세요~~ 정말로 오랜만에 글을 써봅니다. ㅎㅎ

이번에 계속 통계공부를 한 것을 올리다가 영상처리 기회가 있어서 영상처리 공부를 개인적으로 공부하였는데요 ㅎㅎ

MATLAB 과 C++ opencv로 공부를 한 바탕으로 공부를 한것을 올리려고 합니다.

 

책은 밑의 있는 두 자료로 공부를 하였습니다.


해당 책 정보 사이트

http://www.acornpub.co.kr/book/matlab


해당 책 정보 사이트

http://www.booksr.co.kr/

오늘은 아주 간단한 opencv를 설치하는 방법에 대해서 정리를 해서 올릴려고 합니다. 

 

시작해보겠습니다

 

첫번째로는 Visual Studio 를 설치해야되므로 최신 (https://www.visualstudio.com/ko/?rr=https%3A%2F%2Fwww.google.co.kr%2F) 해당사이트에서 설치를 하면됩니다. 
 

 

말풍선이 안보이겠지만 Community 2017 버젼을 설치하면 됩니다!!

 

설치하게 되면 밑의 그림처럼 나오게 되는데요 요기서 필요한 부분을 체크 !! 해주시면 됩니다.



이렇게 위의 그림처럼 체크를 해주시면 됩니다.

 

그 이후에는 opencv를 visual studio에 추가로 해줘야되므로 첫번째로 opencv를 설치합시다.

 

요기서 RELEASES에 들어가서 최신버젼을 설치해줍니다. C\에 설치해주면 됩니다

 

그 이후에서는  [제어판] -> [시스템] -> [고급 시스템 옵션] -> [환경변수] -> 경로를 설정해주면 됩니다.

환경변수 경우에서는 Path 에서는 opencv에 설치한 폴더에서 build\x64\vc14\bin으로 경로를 설정해줍니다.

(저 같은 경우에서는 C에서 설치했음으로 C:\opencv\build\x64\vc14\bin로 설정했습니다. )

 

 


 

그 이후는 Viual stdio 에서 파일을 생성합니다.

 


빈 프로젝트로 해줍니다.

그 이후에는 경로를 설정을 해줘야합니다.

[프로젝트] -> [속성] 에들어갑시다.

 

프로그램 경로에는 한글파일들이 있으면 안됩니다.!!!

 

 

첫번째로는 밑의 그림처럼[ C/C++]에서 [일반]을 include로 경로를 추가해줍니다. (캡쳐 ... 화소가 별로 안좋네요..)

저 같은 경우는 C:\opencv\build\include로 설정했습니다.

계속하여서 [링커] -> [일반] -> [추가 라이브러리 디렉터리] 에 들어갑니다.]

C:\opencv\build\x64\vc14\lib; 로 설정해줬습니다.

그 다음에는 [링커] -> [입력] -> [추가종속성] 에서 opencv_world320.lib를 등록해줍니다. !!

구성 Release 에서는 opencv_world320.lib 디버깅(Debug) 에서는 opencv_world320d.lib로 등록해줍니다.

 

 

[추가 라이브러리 디렉터리], [일반]에서도 Debug에서 반드시 똑같은 경로로 바꿔줍니다.

 

이렇게 설정하게 되면 드디어 끝났습니다.!!!!

1
2
3
4
5
6
7
8
9
10
#include <opencv2/highgui.hpp>
 
using namespace cv;
 
void  main()
{
    Mat  image(300400, CV_8UC1, Scalar(200));
    imshow("영상보기", image);
    waitKey(0);
}
cs

테스트를 해봅시다

 

결과는 이렇게 나오게 됩니다.

 

 

매트렙 경우에서는 내일 설명하도록 하겠습니다

 

오늘은 여기까지 하도록 하겠습니다ㅎ

수고하셨습니다. !!!


 


 

 

반응형

'영상처리 > opencv' 카테고리의 다른 글

opencv영상띄우기와 히스토그램평활화  (0) 2017.08.02
opencv 기본함수들 정리  (0) 2017.05.30

+ Recent posts