프로그래밍 언어를 배우면서 가장 근본적인 질문은 어떻게 배워야 하는가에 대한 질문 이었습니다. 프로그래밍은 우리에게 너무나 많은 일을 할 수 있는 강력한 힘을 줍니다. 하지만 문제가 있죠. 너무 강력한 힘을 주면서 동시에 너무나도 큰 자유를 선사해준다는 점입니다. 

자유

자유... 자유는 누구나 원하는 일이지만 갑자기 주어지면 뭘 해야 할지 감이 안 옵니다. 초등학교, 중학교, 고등학교에서는 하라는 데로 하기만 하면 됩니다. 심지어 대학교 조차도 커리큘럼이 있습니다. 이러한 커리큘럼을 특정한 시간 내에 특정한 주제가 정해진 상태로 우리는 하라는 일을 하면 됩니다. 하지만 프로그래밍은 우리에게 자유를 줌과 동시에 무엇을 해야 할지 우리가 스스로 결정해서 나가야 합니다. (물론 회사에 들어간다면 해야 할 일이 주어지지만 프로그래밍을 배우는 주된 이유는 내가 원하는 것을 마음껏 펼칠 수 있기 때문입니다.)

 

그렇다면 무엇을 배워야 할지 모르는 상태에서 나름의 틀을 주는 것은 무엇일까요? 그건 책이죠. 아무것도 할 줄 모른다면 일단은 머릿속에 무언가라도 넣은 상태에서 무엇을 해야 할지 결정해야 합니다. 그것도 싫다면 자바에서 주어지는 여러 기능을 시험삼아 테스트 해봐야 합니다. 틀이 주어지건 안 주어지건 간에 우리는 주어진 기능을 시험해보고 어떻게 사용해야 하며, 쓰다보면 생기는 질문을 꼭 해결하면서 진행해야 합니다. 

 

그렇다면 오늘의 포스팅에서는 어떻게 여러 기능을 연습해볼 수 있는지 살펴보도록 하겠습니다.

1. 어떻게 테스트를 할 것인가?


우리에게 가장 처음의 프로그래밍의 시작은 Hello, World가 주어진 것은 우연이 아닙니다. 가장 기본적인 입출력 프로세스를 익히기 위함이죠. Stdout이라 하는 Standard OutPut은 프로세스에서 가장 기본적인 인터페이스이죠. 그러면 단 한 줄을 분석해보도록 합시다.

 

System.out.println("Hello, World!");

 

자바의 기본적인 API를 확인할 수 있는 곳은

docs.oracle.com/en/java/javase/15/docs/api/index.html

 

Overview (Java SE 15 & JDK 15)

This document is divided into two sections: Java SE The Java Platform, Standard Edition (Java SE) APIs define the core Java platform for general-purpose computing. These APIs are in modules whose names start with java. JDK The Java Development Kit (JDK) AP

docs.oracle.com

이곳에서 확인할 수 있다. 필요한 내용이 있을 때마다 Search를 활용해서 사용하도록 해야 한다.

상단에 보면 Search가 있으니 궁금한 내용을 찾아보는 습관을 들이자. 참고로 영어가 잘 안되도 우리는 할 수 있다. 네이버 파파고와 구글 번역이 있으니 전혀 무섭지 않다. 번역기를 돌리면서 영어로도 한번 읽어보자. 차분히 영어 실력도 같이 늘어가는 것을 볼 수 있다. 언제까지고 영어가 두려워서 영어 페이지가 나오는 것을 외면할 것인가! 한번 시도해보자. 당장에 하루 이틀 만에 확 늘어날 수는 없지만 꾸준히 하면 영어 페이지가 나와도 읽을 만할 정도가 될 것이다. 

 

우리는 여기서 System을 찾아볼 것이다.

많은 검색 결과가 나온다. 그 중에서 java.lang.System을 클릭해서 들어가보자. 

두 가지 정보를 바로 얻을 수 있다. Module : java.base와 Package : java.lang 모듈과 패키지를 알아볼 수 있다. 그러면 우리가 모르는 정보는 모듈과 패키지란 단어를 모른다. 다시 찾아보면 된다. 어쨋든 모듈이란 기능상 비슷한 것을 모여서 만든 작은 부품이 조립된 하나의 덩어리를 모듈이라 부른다. 

 

모듈


현실 세계에서 자동차를 만들기 위해서는 수 많은 모듈이 필요하다. 모듈은 수 많은 부품으로 이루어져 있다. 이런 관점에서 보았을 때 모듈은 하나 또는 하나 이상의 기능을 하는 특정한 덩어리이며, 나사와 같은 작은 부품이 모여서 최소한의 기능을 할 수 있게 만들어주는 하나의 덩어리라고도 볼 수 있겠다. 대표적인 모듈은 ABS 모듈이다. 자동차 시스템에서 브레이크 시스템을 담당하는 녀석으로 Anti-lock Break System을 의미한다. 브레이크를 밝을 경우, 한 쪽 바퀴가 먼저 잠기는 것을 방지해서 차가 회전하는 것을 막아주는 역할을 한다.

 

ABS 모듈의 구성은 바퀴속도 감지기, ECU(전자 제어 모듈), 유압조정장치, 경고등 등이 기본적인 구성 성분이다. 여기서는 다른 모듈을 포함하기도 하는 것이 모듈이다. 소프트웨어에서도 마찬가지이다. 이러한 모듈의 크기는 천차만별인데, 모듈의 크기가 커지면 처음에 설계하기가 어려워지는 대신에, 모듈과 모듈을 합치는 과정이 편해진다. 반대로 모듈의 크기가 작아지면 처음에는 설계하기 쉽지만, 이러한 모듈들을 조립하는 단계에서 힘들어 진다. 자동차에서도 부품이 너무 많은 나머지 조립할 때, 일반인은 하지 못하는 것과 마찬가지이다. 하지만 조금 더 모듈의 크기가 큰 전자제품의 경우, 자동차 보다 조립하기는 쉬운 경향이 있다. 물론 이러한 예는 정확한 예는 아니지만 모듈에 대해 이해하기에는 충분하리라 생각한다.

 

모듈을 사용하는 이유는 사람이 다룰 수 있는 단위로 나누어서 소프트웨어를 설계하기 쉽고 유지보수 하기 쉽게 만들기 위함이다. 프로그램이 하나의 덩어리로만 이루어진다면 우리는 다음 소프트웨어 버전을 만들기 위해서 처음부터 설계해야할 것이다. 또한 특정 부분이 고장나서 고치려고 할 때, 그 소프트웨어를 다시 사야 할 것이다. 

 

지금 세상은 모듈화가 잘 이루어져 있어서 특정 예를 들긴 어렵지만, 소비자의 입장에서 예를 들어보로독 하자. 대표적인 덩어리 모듈의 예시를 들어보자면 핸드폰에서 탈착식 배터리와 일체형 배터리의 차이라 볼 수 있다. 탈착식 배터리의 장점은 배터리의 수명이 다 되어, 새 것으로 교체하고자 한다면 언제든지 교체가 가능하다. 하지만 일체형 배터리는 그렇게 하기 어렵다. 액정을 뜯어내야 하며, 그것을 다시 붙여야 한다. 이러한 과정에서 소비자가 직접 하기 힘든데다가 엔지니어에게 맡길 경우 많은 비용이 소모되는 것이다. 

 

패키지


  패키지란 Class들의 모음을 패키지라 한다. Package(패키지)란 말에서 알 수 있듯이 하나의 선물 꾸러미라 생각하면 편하겠다. 여기에 추가로 인터페이스를 같이 묶어두고 하나의 폴더에 저장해둔 것이다. 여기서 인터페이스라 하면 사용할 수 있게끔 만들어주는 장치라 보면 된다. 전자기기에서는 전기 코드가 인터페이스에 해당한다. (전기 코드 자체도 인터페이스이지만, 전자기기의 여러 버튼들 또한 인터페이스라 볼 수 있다.)Interface는 영어 단어 해석에서 보자면 [결합부], [접속기], [대면부] 등의 뜻을 가지고 있다. 특정 물체와 물체가 맞닿는 곳을 인터페이스라 할 수도 있다. 혹은 사물과 사용자가 서로 의사소통 할 수 있도록 만들어 놓은 매개체를 의미한다. 사용자와 맞닿은 인터페이스를 UI (User Interface)라 하기도 한다. 핸드폰에서 보이는 화면 대부분이 UI이기도 하다. 

  패키지를 두는 대표적인 이유 중 하나는 클래스 이름의 고유성을 보장하기 위해서이다. 프로그래밍 프로젝트가 커지면 커질 수록 패키지 이름이 겹치는 경우가 있는데, 이러한 상황에서 다른 패키지를 사용함으로써 중복을 회피할 수 있는 것이다.

  예로 들자면, A와 B는 파일 123을 저장하고 싶은 상태이다. 그런데 바탕화면에다가 저장하면 파일이 중복되서 하나의 파일이 사라질 확률이 있다. 이러한 상태에서 폴더를 따로 둠으로써 이를 피하는 것이다. A는 폴더 'A의 폴더'에 저장하고, B는 'B의 폴더'에 저장함으로써 파일 123은 유지가 되는 것이다.

  이제 불러오는 방식을 확인해보면, A의 폴더 -> 파일123B의 폴더 -> 파일123은 분명히 구분이 가능한 상태가 되었다.

 

* 이곳에서는 패키지의 사용법이 아닌 패키지가 무엇인지만 보도록 하고 나중에 패키지를 사용하는 방법에 대해 자세히 다루도록 하자.

 

 

자바에서 둘 사이의 차이점? 패키지와 모듈


그렇다면 모듈과의 차이점은 무엇인가? 패키지는 클래스와 인터페이스를 묶어놓은 하나의 폴더를 의미한다. 모듈은 이러한 패키지를 포함해서 특정 필요한 리소스를 모아놓은 하나의 컨테이너이다. 패키지보다는 모듈이 조금 더 상위 개념이라 볼 수 있지만, 그렇다고 패키지 위에 모듈이 있다고는 볼 수 없다. 실행가능하도록 최소한의 것들을 모아놓은 것이라 생각할 수 있다. 그래서 하드웨어적 성능이 떨어지는 IoT 기기 상에서도 응용 프로그램을 실행가능하다. 

 

 

다시 System.out.println으로 돌아가자.

여기서 System은 System class를 의미하고 있으며, 여러 class와 메소드를 포함하고 있는 것이다. 

module에서는 java.base, Package java.lang에 들어있다. 

여기에서는 PrintStream에서 out 필드임을 확인할 수 있다. out은 표준 출력 스트림을 의미한다. 여기서

 

스트림이란? 


  마우스와 키보드 같은 입력 장치와 모니터, 프린터기 같은 출력 장치에서 보낸 신호와 컴퓨터에서 보낸 신호는 컴퓨터 상에서 알아서 처리해준다. 우리는 하드웨어적인 부분을 신경쓸 필요가 없다. 이러한 작업을 해주는 것이 스트림이다. 

 

  스트림은 방향에 따라 두 가지로 나뉘어지는데, 컴퓨터 쪽으로 들어오는 스트림을 입력 스트림이며, 컴퓨터 쪽에서 사용자 방향으로 나가는 스트림을 출력 스트림이라 한다. 

 

여기까지만 공부해도 충분하다. 여기서 더 파고 들어서 그 원리까지 알면 좋겠지만, 마음이 허락 안할 수 있기에 이해력과 마음이 허락하는 한 파고들면 된다. 

 

 

스트림에 이어서 println


println은 특정 값을 입력받은 뒤에 사용자가 볼 수 있도록 출력해주는 역할을 한다. 하지만 println은 하나만 정의된 것이 아니다.

다양한 형태의 println이 정의되어 있다. 이렇게 하는 이유는 사용자가 어떤 값을 입력할지 모르기 때문이다. 우리가 앞서 보았듯이 컴퓨터는 한정된 형태의 데이터를 인식할 수 있다. 정수면 정수, 실수면 실수, 문자면 문자로 인식하는 것이다. 사람이야 각 형태를 따로 따로 자동으로 인식되지만 컴퓨터는 그러지 못하다. 그러므로 이를 모두 인식할 수 있도록 도와주는 것이 다양한 형태로 정의해두는 것이다. 우리는 이러한 형태를 자바의 다형성이라 불리며 실제 구현 방식 중 하나인 오버로딩(Overloading)방식이라 한다. 

 

같은 이름의 함수를 여러 개 정의하고, 매개변수와 그에 따른 유형 그리고 개수를 다르게 함으로써 사용자의 다양한 호출에 반응하기 위함이다. 그래야지 사용자가 숫자를 호출하건, 문자를 호출하건 다양하게 대응할 수 있는 것이다. 

지난 시간에는 Hello, World를 타이핑 해보았다. 그렇다면 Hello, World에 대한 이야기를 해보도록 하자.

[Java]Hello World! 출력하기 

public class Main{

}

자바 프로그램에서의 기본 골자는 이러한 형태로 생겼다. 바로 

 

1. public class이다.


자바 프로그램 상에서 public class는 가장 기본이 되는 것 중 하나이다. 자바 프로그램은 기본적으로 하나 이상의 class로 구성되어 있으며, 이러한 class 들이 모여 다양한 일을 하는 프로그램이 되는 것이다. class의 이름은 Main말고도 다양하게 가질 수 있다. 원하는 이름은 모두 class의 이름이 될 수 있지만 숫자로 시작하는 것은 안된다. public은 접근 제어자로 접근을 제한하는 기능을 하는 문법이다. 이는 접근에 제한이 없는 것을 의미하며, 접근제어자로는 protected, default, private를 사용한다. 객체지향에서 이러한 접근 제한 아주 중요한 역할을 한다. (대표적으로 객체지향에서 캡슐화라는 단어가 나오는데, 캡슐화의 장점 중 하나는, 해열제로 예를 들자면, 실제 세상에서 약을 먹을 때, 그 속에 어떤 성분이 있는지 모르지만 약을 먹으면 열이 내리는 역할을 해준다. 우리는 약에 대한 성분을 아무것도 모르더라도 약효가 무엇인지만 알고도 사용할 수 있는 것이다. ) 물론 객체지향에 대해 더 자세히 이야기하면 끝도 없지만 대략적인 느낌은 그러하다.

 

앞서 보았던 웹 컴파일러에서도 Ideone으로 클래스 이름을 지정했다. 

public static void main(String[] args) {
}

그 다음으로 오는 내용은 main 메소드이다. main은 전체 프로그램 상에서 하나의 main을 갖는다. 실제로 프로그램이 구동되는 공간으로써, 프로그램이 시작되는 공간이라 생각하면 편하다. 앞서 본 public말고도 static이 존재하는데, 프로그램이 시작하는 시작 공간이다 보니, 처음부터 메모리 상에 존재하게끔 만들어주는 역할을 한다고만 알아두자. 나중에 다시 이야기하도록 하겠다.

 

System.out.println("Hello, World");

마지막으로 Hello, World를 출력해주는 구문이다. 이는 자바 표준 입출력 클래스에 들어있는 함수이다. 세 부분으로 이루어져 있다. System + out + println으로 해석해도 좋다. 당연히 System은 시스템이라는 말에서 볼 수 있듯이 컴퓨터의 기본적인 일을 처리하는 공간이 될 것이며, out은 밖으로 나가는 출력 시스템, print + ln이므로 무엇인가가 프린트를 된다고 볼 수 있다. 마지막 ln은 새로운 라인을 넣어준다는 New Line과 같다. 

 

비슷한 메소드로써 System.out.print("Hello, World") 가 있다. 이 메소드는 데이터를 출력한 이후에 줄 바꿈을 하지 않는다. 

 

이렇듯 한 개의 간단한 프로그램을 보더라도 많은 키워드가 있음을 확인할 수 있다. 우리는 이러한 키워드를 모두 외울 필요는 없다. 다만 중간중간에 필요할 때마다 찾아봐야 한다. 이렇게 많은 키워드를 어떻게 외울 수 있겠는가? 물론 자주 쓰다보면 외울 수야 있다. 하지만 너무 많기 때문에 외우지 않고 레퍼런스를 찾아보면서 쓰는 것이다. 그러므로 레퍼런스를 자주자주 들여다 보는 습관을 갖는 것이 좋다. 

 

en.wikipedia.org/wiki/List_of_Java_keywords 

 

List of Java keywords

A snippet of Java code with keywords highlighted in blue and bold font In the Java programming language, a keyword is any one of 52 reserved words[1] that have a predefined meaning in the language; because of this, programmers cannot use keywords as names

en.wikipedia.org

위키피디아에는 많은 자바 키워드가 정리가 되어 있다. 구경하고 싶은 사람은 구경해도 좋다.

우리는 프로그래밍 언어를 배우게 되면 가장 먼저 출력해보는 단어들인 Hello, World를 출력해보도록 하자. 기본적인 출력을 해봄으로써 프로그래밍이 어떠한 과정으로 진행되는지 살펴보자라는 의미를 가지고 있다. 프로그래밍 세계로의 첫 걸음인 것이다. 중요하면서도 동시에 무섭기까지 하다.

 

우리는 Java IDE를 사용하도록 할 것이다. 다만, 유명한 이클립스를 사용하진 않을 것이다. 이유는 안 이뻐서다. (가장 중요한 이유다.) 그렇다면 무엇을 사용할 것인가? IntelliJ IDEA를 사용할 것이다.

 

이유는? 역시 이뻐서다. 그냥 필자의 마음에 들어서다. 처음에 뭐가 좋나 뭐가 좋나 고민할 필요가 없다. 이쁘고 무료로 지원되냐? 가 중요하다.

 

두 가지 다운로드 옵션이 존재한다. 하나는 Ultimate, 하나는 Community이다. 커뮤니티는 무료 버전이다. 하지만! 만약 학생이라면 학교 이메일을 통해 인증하고, 1년 간 무료로 사용해보도록 하자. 정말 편하다. 물론 우리에게는 더욱 강력한 VSCode도 있긴 하지만, 처음부터 사용하기엔 부담스럽다. 그냥 알아서 해주는 IntelliJ를 사용하도록 하겠다.

 

www.jetbrains.com/ko-kr/idea/

 

IntelliJ IDEA: 우수성과 인체 공학이 담긴 JetBrains Java IDE

Enterprise Java, Scala, Kotlin 등을 지원하며 강력한 기능을 제공하고 인체 공학적으로 설계된 Java IDE

www.jetbrains.com

공식 홈페이지이다. 간단하게 뭐가 우수한지 말하자면, 쓰다보면 가끔 언어를 이해하고 내게 필요한 것을 추천해줄 때 편안함을 느낀다. 물론 더 다양한 이유가 많지만, 그런건 처음에는 보이지도 않는다. 누차 이야기하지만 편하고 이뻐서다!

[학생 인증이 되시면 반드시 Ultimate을 사용하도록 하세요.]

 

 

둘의 차이는 아직 우리가 못 느낀다.

 

그러나 프로그래밍을 하면 할 수록, 알아가면 알아갈수록 필요한 기능들이 보이기 시작할 것이다. 

물론 다른 IDE도 있다.

 

code.visualstudio.com/

 

Visual Studio Code - Code Editing. Redefined

Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com

추천한다. 무료다! 강력하다! 이쁜걸로 쓰면 되지만 VSCode는 직접 하나하나 만들어가야 한다. (플러그인을 잘 설치해야 한다.) 좋고 나쁜건 없다. 그냥 아무거나 써도 된다. 사용자가 중요하다. 전동 드릴을 사야하는데 어떤 브랜드를 써야 하나요? 삼대장 같은게 있으니 그것 중에 아무거나 골라서 쓰면 된다.

노트북은? LG, 삼성, 애플과 비슷한 이미지다. 

 

인텔리제이 설치와 더불어 초기 설정에 알고 싶다면, goddaehee.tistory.com/195

여기에 추가로 플러그인 설치를 통해 한글화를 진행하면 된다. 

 


프로젝트까지 완료되면 우리는 Hello World를 볼 수 있다.

 

class Main {
    public static void main(String[] args){
        System.out.println("Hello, Name!");
    }
}

을 치고서 실행하면 된다. 

실행하면 

이런 느낌으로 나오는 것을 확인할 수 있다.

 

 


웹 컴파일러 사용하기


IDE는 편안함을 제공한다는 점에서 아주 좋다. 하지만 설치가 번거롭고 초기 셋팅을 하기까지 귀찮을 수 있다. 게다가 많은 기능이 필요없는 사람의 입장에서 설치는 정말 하기 싫은 작업 중 하나이다. 그러므로 설치하지 않고 인터넷 웹 페이지 상에서 사용할 수 있는 웹 컴파일러를 소개하고자 한다. 많이 사용되기도 하는 웹 컴파일러 중 하나는 이곳이다.

ideone.com/

 

Ideone.com

Ideone is something more than a pastebin; it's an online compiler and debugging tool which allows to compile and run code online in more than 40 programming languages.

ideone.com

컴퓨터가 느리거나 설치가 싫은 사람은 웹 컴파일러를 꼭 써보기 바란다. 추가로 위에 사이트가 접속이 안 될 경우에는 웹 컴파일러라고 구글에 치면 많은 종류가 나오니 취사선택해서 사용해보는 것도 좋다.

 

이런 느낌으로 나온다.

1. 리터럴 (Literals)


우리의 일상생활을 둘러싼 모든 것은 어떠한 관점에서 보면 모두 정보라 볼 수 있다. 그러한 관점에서 우리는 변수와 상수를 나누어서 살펴볼 필요가 있다. 수학에서도 변수와 상수는 구분되어져 있다.

이 식은 우리가 중학교 때부터 봐온 이차식이다. 아주 간단한 식이다. 이 식에는 변수와 상수가 공존하고 있다. a, b, c는 상수이며, x는 변수이다. 너무 깊게 들어가지 말고 간단하게 짚고 넘어가도록 하자. 상수는 고정된 값이며, 변수는 변할 수 있는 수이다. 그래서 컴퓨터에서도 변수와 상수 두 개로 나누어져 있다. (원래 프로그래밍 자체가 학자를 위한 것이었으므로 그 기원을 생각하면 이렇게 설계된 것이 당연시 된다.) 

 

하지만 컴퓨터에서는 하나의 개념이 더 추가된다. 바로 리터럴이다. 리터럴이란 데이터 자체의 값을 리터럴이라고 한다. 예를 들어 10이란 수가 있으면, 10 자체의 데이터를 의미하는 그 자체의 값을 리터럴이라 부른다. 예를 들어 보자.

final int a = 10 

final을 붙이면 변수를 변경할 수 없게 된다. 그래서 우리가 이야기하는 상수가 된다. 변할 수 없는 값이므로 상수의 정의에 들어맞는다. 이러한 값을 초기에 한번은 정의를 해줘야 하는데, 그 값 자체를 의미하는 10은 리터럴이 된다.

 

다시 한번 정리하자면 10이란 숫자 자체는 리터럴이며, 10을 넣어서 값을 변하지 못하게 하는 한 값은 상수가 되는 것이다. 

 

프로그래밍에서는

  • 상수는 특정 공간에 넣은 변수인데, 변하지 않는 변수를 상수라 부를 것이며,
  • 리터럴은 데이터 자체로써의 변하지 않는 어떤 값을 의미한다.

Java에서 문자 리터럴와 문자열 리터럴은 차이점이 있다.

문자 리터럴은 'a', 'b' 이렇게 하나짜리 따움표를 쓴다는 점

문자열 리터럴은 "a", "abc", "Hello"의 형태를 가진다는 점이다. 문자를 하나 쓴다고 문자 리터럴이 되지 않는다. " " 의 형태는 문자열 리터럴을 가지게 된다. 다만, 컴파일러가 똑똑해짐에 따라 알아서 바꿔주지만 그래도 조심해서 사용하도록 해야 한다.

 

마찬가지로 숫자 리터럴에서도 1_000_000 이러한 값은 숫자 리터럴이다. 문자가 아니다. 이렇게 사용하는 이유는 단위를 읽기 쉽게 만들어주기 위해서이다. (가독성) 저 숫자랑 같은 수는 1000000이다. 

 

리터럴의 종류에는 다양한 종류가 있다. 우리가 생각하는 모든 변수는 모두 리터럴이 존재한다. 정수 리터럴, 문자 리터럴, 문자열 리터럴, 실수 리터럴, 논리 리터럴 등 다양한 종류가 존재한다. 이러한 리터럴의 차이점을 아는 것은 우리가 자바를 프로그래밍할 때, 나중에 객체지향프로그래밍을 할 때 중요한 초석이 된다. 리터럴로 생성된 객체의 주소값과 특정 메서드를 활용해서 비교하는 경우에가 다를 수 있다는 점을 이해할 수 있는 길이 되는 것이다. 이러한 점은 나중에 차분히 설명하도록 하자.

 

2. 변수


변수 - 메모리 상에 자리를 지정해주고 그 자리를 사용자가 사용할 수 있도록 알려주는 것이다. 

예를 들어, 서울시 성북구 117번길 1에 사는 사람의 주소를 able이라 하면 다음부터 able이라 부르면 우리는 자연스럽게 서울시 성북구 117번길 1로 찾아가게 되는 것이다. 

 

int able;

이렇게 지정해주면 int라는 자리만큼의 메모리를 배정하주고, 특정 주소지에 대한 이름을 able이라 하자 라고 선언하는 것이 변수이다. 이제 이 공간은 사용자가 사용할 수 있다. 

able = 1;

사용할 수 있는 주소와 장소가 생겼으므로 여기에 1을 넣도록 할 것이다. 여기서 1은 리터럴로 생성이 된다. 메모리 어딘가에 생성된 상태가 되는 것이다. [차후에 이야기하겠지만, 리터럴이 생성되는 공간과 변수가 생성되는 공간은 다른 메모리 상에서 생성된다. ]

 

우리는 이러한 1을 able의 공간에 넣어주는 행위를 초기화한다고 한다. 그리고 이러한 초기화 과정은 여러번 일어날 수 있다.

 

able = 1;
able = 2;
able = 3;

이러한 코드가 온다면 초기화가 3번 일어난 것이다. 

( * 그러면 왜 값을 대입하는 것을 할당이라 안 하고 '초기화'라 하는 것인가? => 이 부분에 대한 답은 메모리를 이루고 있는 하드웨어적 요소를 생각하면 초기화란 단어가 자연스럽게 와닿게 된다. RAM은 기본적으로 휘발성 메모리로 전기가 계속 인가되어 있는 동안에는 기존에 가지고 있던 정보가 유지된다. 하지만 전기가 끊기면 날라간다. 우리는 이러한 여러 특성을 활용해서 메모리를 지웠다 썼다 를 할 수 있는 것이다. 그러면 새로운 데이터가 와서 새롭게 저장하려면 리셋을 한 뒤에 다시 데이터를 써야 하지 않겠는가? 그러한 이유에서 메모리가 초기화된다고 이야기할 수 있다. ) - 이는 이해를 위해 생략된 부분이 많으므로 반드시 공부가 깊어짐에 따라 한번 다시 생각해보길 바란다.

 


 

1. 자바란 무엇인가?


Java는 범용 프로그래밍 언어로 썬 마이크로 시스템즈(Sun Microsystems)에서 개발한 언어이다. 현재는 오라클(Oracle)에서 소유권을 가지고 있으며 유료화가 진행된 상태이다. 자바의 가장 큰 특징 중 하나는 플랫폼에 귀속되지 않는 다는 점이다. 코딩을 한번 하고 어떤 플랫폼이던지 간에 사용할 수 있게 만들어졌다. 이는 JVM이라 하는 자바가상머신을 이용해서 플랫폼에 관계 없이 사용할 수 있다. 이러한 특징으로 인해 자바는 많은 인기를 얻게 되었는데, 이는 프로그래밍 언어 순위 차트를 다루는 TIOBE에 가서 확인해도 높은 순위에 있는 것을 확인할 수 있다. 

 

1순위는 C언어, 2순위는 Java, 3순위는 Python이다. 만약에 프로그래밍이 처음이라면 개인적으로 Python을 추천한다. (아니 왜 방금 전까지 Java짱짱맨 해놓고선 Python이라뇨? 정말로 프로그래밍 자체가 처음이라면 순위보다는 일단 입문을 python으로 시작하라는 것이다. 비교적 쉬운 python을 통해 접근해보고 난이도를 낮춘 뒤에 다시 Java를 접근하는 것을 추천한다. 내가 필요한 건 모래성 쌓기인데, 갑자기 중장비 끌고 와서 고층 빌딩을 지을 순 없지 않겠는가? 그렇기에 프로그래밍 경험이 전무하다면 차라리 Python이 낫다는 것이다. 물론 읽는 것을 좋아하며, 수학을 좋아하고 딱딱한 이과감성을 사랑하는 사람이라면 Java, C, C++을 추천한다. 그렇지 않다면 일단은 Python을 통해 경험한 뒤에 들어와도 늦지 않다. 어차피 프로그래밍으로 입문해서 전문가까지 가려는 사람이라면 모든 언어는 다 써봐야 한다. 직업으로 일하려면 상황에 맞는 언어를 사용해야 하므로 언제나 다양한 언어가 필요한 것이다. 고로 결론. 시작은 Python을 추천한다.)

 

C/C++에서 Java로 넘어오면서 아주아주아주 편해진 점 중 하나는 메모리 관리의 자유로움이었다. C/C++가 개발자에게 많은 자유를 주는 만큼 주의해야 할 점이 많았는데, 대표적으로 메모리 관리이다. 그래서 C/C++는 초보자가 진입하기 어려운 장벽이 생겨버렸지만, 그만큼 성능 좋은 코드를 짤 수 있게 되었다. 하지만 현대의 하드웨는 이미 끝을 달리고 있다. 그러므로 우리는 하드웨어를 신경쓸 것이 아니라 내 생각을 구현하는게 더 중요해졌다. 그래서 자동으로 메모리 관리를 해주는 프로그래밍 언어를 쓸 필요성이 있는 것이다. Java와 파이썬은 그러하다.

 

2. 자바의 기본 로고


자바의 기본 로고는 이렇게 생겼다. 커피에 있는 자바인가? 그렇다. 필자도 대학교에서 C/C++를 하고 Java를 처음으로 선택했다. 이유는 로고가 그럴싸해서이다. 현재 자바는 오라클이 소유하고 있으며 유료화가 진행됬다. 그렇다고 무조건 유료는 아니다. 오픈소스가 존재한다. 우리는 오픈소스를 활용해서 진행하려고 한다. 

 

 

3. 설치 및 실행


jdk.java.net/15/

 

JDK 15.0.2 GA Release

JDK 15.0.2 General-Availability Release This page provides production-ready open-source builds of the Java Development Kit, version 15, an implementation of the Java SE 15 Platform under the GNU General Public License, version 2, with the Classpath Exce

jdk.java.net

이곳을 통해서 Java를 받으면 된다. JDK15를 기준으로 진행할 예정이므로 우리도 JDK 15를 받아주면 된다. 

대부분은 윈도우를 사용하고 있으므로 윈도우로 다운로드 받으면 된다. (참고로 여기는 Zip파일이다. 우리가 평소에 받던 exe파일이 아니라 자동 설치따윈 없다. ) 다운로드 받은 뒤에 원하는 장소에 압축을 풀어준다.

필자는 C를 사랑하는 사람이므로 C에다가 Java폴더를 만들어준 뒤에 압축을 풀어주었다. (정확한 이유는 D는 하드드라이브이기 때문에 SSD인 C에다가 풀어주었다.)

 

다 풀고 나면 C:\java\jdk-15.0.2 이러한 형태로 나오게 된다. 

자 이제 안타깝게도 자바를 사용하려면 바로 쓸 수 없다. 물론 바로 사용은 가능하다. 하지만 명령프롬프트를 사용해서 직접 실행파일이 있는 곳으로 끌고 가야 한다. 그래도 한번 해보자.

 

명령프롬프트를 사용하려면 

 

시작버튼 옆에 검색라인에 cmd라 타이핑하자. 그러면 명령프롬프트가 나온다. 명령프롬프트에다가 다음을 입력해보자.

 

cd.. 은 폴더의 하위 폴더로 가게 해준다. 그리고 아까 압축해제한 폴더에서 C:\java\jdk-15.0.2\bin를 찾아둔다. 그리고 cd C:\java\jdk-15.0.2\bin을입력하면 위에 상황과 같이 된다. 

 

여기에 두 가지 명령어를 입력해볼 수 있는데, java -version과 javac이다.

javac는 java의 컴파일러로 우리가 코딩을 해놓은 소스코드를 실행가능한 파일로 바꿔주는 역할을 한다. java 명령어는 바꿔놓은 파일을 java를 통해 실행할 수 있게끔 한다. (일반적으로 윈도우 환경에서 IDE를 사용하게 되면 이러한 내용은 몰라도 상관없다. 하지만 서버환경에서나 IDE가 없는 경우는 이렇게 컴파일하고 실행해야 한다. 그래서 한번은 이렇게라도 진행해보는 것이 중요하다. ) 

* IDE는 통합개발툴인데, 비주얼 스튜디오, 비주얼 스튜디오 코드, 인텔리제이와 같은 것을 의미한다.

 

자 그렇다면 매번 이렇게 귀찮게 실행해야 하는가 싶지만 그렇지 않다. 우리는 환경변수를 활용해서 자바가 설치된 폴더까지 안 가더라도 언제 어디서든 사용할 수 있도록 만들어 줄 것이다. 일반적으로 환경변수는 PATH를 설정해준다고 하는데, 컴퓨터한테 자바가 어디에 설치되어 있는지 알려주는 이정표 역할을 해주는 것이다. 

 

4. 자바 환경변수 설정하기


자바 환경변수 설정에는 명령프롬프트를 활용하는 방법과 시스템 환경설정을 통해서 하는 방법이 있는데, 명령프롬프트를 이용한 방법은 명령프롬프트가 꺼지면 초기화된, 시스템 환경설정을 이용해서 진행하도록 한다.

 

제어판 -> 시스템 정보 -> 고급 시스템 설정을 클릭한다.  [혹은 내 컴퓨터(내 PC) -> 오른쪽 클릭 -> 속성]

 

고급 시스템 설정을 클릭한 뒤에 -> 환경변수를 눌러준다. 

그 뒤에 새로 만들기를 눌러준다.

 

 

시스템 변수 편집에서 변수 이름에는 JAVA_HOME을 적어주고 변수 값에는 Java가 설치된 공간을 넣어주면 된다. 컴퓨터에게 자바가 여기에 설치되어 있다고 알려주는 것이다. 경로에 대한 변수를 할당하며, 그 변수는 JAVA_HOME이다. 대부분의 Java IDE 가 JAVA_HOME을 쓰고 있으므로 우리도 그에 따라 맞춰서 저장한다.

 

그 다음으로 Path를 입력할 것이다. 

Path를 눌러주고 편집을 누르자.

 

그러면 이렇게 나오게되는데, 

여기서 %JAVA_HOME%bin 을 입력해주자. 이것은 아까 저장한 JAVA_HOME이라는 변수에는 자바가 어디에 설치되어 있는지 알려주는 경로가 들어있다. 그곳에서 bin폴더가 있는 곳을 알려주는 것이다. (여기서 bin의 의미는 binary의 bin이다. 일반적으로 실행파일의 의미를 가지고 있다. 그래서 실행파일의 위치는 여기에 있다. 라고 알려준 것이다.)

 

여기까지만 해도 충분히1. 자바란 무엇인가?

Java는 범용 프로그래밍 언어로 썬 마이크로 시스템즈(Sun Microsystems)에서 개발한 언어이다. 현재는 오라클(Oracle)에서 소유권을 가지고 있으며 유료화가 진행된 상태이다. 자바의 가장 큰 특징 중 하나는 플랫폼에 귀속되지 않는 다는 점이다. 코딩을 한번 하고 어떤 플랫폼이던지 간에 사용할 수 있게 만들어졌다. 이는 JVM이라 하는 자바가상머신을 이용해서 플랫폼에 관계 없이 사용할 수 있다. 이러한 특징으로 인해 자바는 많은 인기를 얻게 되었는데, 이는 프로그래밍 언어 순위 차트를 다루는 TIOBE에 가서 확인해도 높은 순위에 있는 것을 확인할 수 있다. 

 

 

 

1순위는 C언어, 2순위는 Java, 3순위는 Python이다. 만약에 프로그래밍이 처음이라면 개인적으로 Python을 추천한다. (아니 왜 방금 전까지 Java짱짱맨 해놓고선 Python이라뇨? 정말로 프로그래밍 자체가 처음이라면 순위보다는 일단 입문을 python으로 시작하라는 것이다. 비교적 쉬운 python을 통해 접근해보고 난이도를 낮춘 뒤에 다시 Java를 접근하는 것을 추천한다. 내가 필요한 건 모래성 쌓기인데, 갑자기 중장비 끌고 와서 고층 빌딩을 지을 순 없지 않겠는가? 그렇기에 프로그래밍 경험이 전무하다면 차라리 Python이 낫다는 것이다. 물론 읽는 것을 좋아하며, 수학을 좋아하고 딱딱한 이과감성을 사랑하는 사람이라면 Java, C, C++을 추천한다. 그렇지 않다면 일단은 Python을 통해 경험한 뒤에 들어와도 늦지 않다. 어차피 프로그래밍으로 입문해서 전문가까지 가려는 사람이라면 모든 언어는 다 써봐야 한다. 직업으로 일하려면 상황에 맞는 언어를 사용해야 하므로 언제나 다양한 언어가 필요한 것이다. 고로 결론. 시작은 Python을 추천한다.)

 

 

 

2. 자바의 기본 로고

 

자바의 기본 로고는 이렇게 생겼다. 커피에 있는 자바인가? 그렇다. 필자도 대학교에서 C/C++를 하고 Java를 처음으로 선택했다. 이유는 로고가 그럴싸해서이다. 현재 자바는 오라클이 소유하고 있으며 유료화가 진행됬다. 그렇다고 무조건 유료는 아니다. 오픈소스가 존재한다. 우리는 오픈소스를 활용해서 진행하려고 한다. 

 

 

 

 

 

3. 설치 및 실행

jdk.java.net/15/

 

JDK 15.0.2 GA Release

 

JDK 15.0.2 General-Availability Release This page provides production-ready open-source builds of the Java Development Kit, version 15, an implementation of the Java SE 15 Platform under the GNU General Public License, version 2, with the Classpath Exce

 

jdk.java.net

이곳을 통해서 Java를 받으면 된다. JDK15를 기준으로 진행할 예정이므로 우리도 JDK 15를 받아주면 된다. 

 

 

대부분은 윈도우를 사용하고 있으므로 윈도우로 다운로드 받으면 된다. (참고로 여기는 Zip파일이다. 우리가 평소에 받던 exe파일이 아니라 자동 설치따윈 없다. ) 다운로드 받은 뒤에 원하는 장소에 압축을 풀어준다.

 

필자는 C를 사랑하는 사람이므로 C에다가 Java폴더를 만들어준 뒤에 압축을 풀어주었다. (정확한 이유는 D는 하드드라이브이기 때문에 SSD인 C에다가 풀어주었다.)

 

 

 

다 풀고 나면 C:\java\jdk-15.0.2 이러한 형태로 나오게 된다. 

 

자 이제 안타깝게도 자바를 사용하려면 바로 쓸 수 없다. 물론 바로 사용은 가능하다. 하지만 명령프롬프트를 사용해서 직접 실행파일이 있는 곳으로 끌고 가야 한다. 그래도 한번 해보자.

 

 

 

명령프롬프트를 사용하려면 

 

시작버튼 옆에 검색라인에 cmd라 타이핑하자. 그러면 명령프롬프트가 나온다. 명령프롬프트에다가 다음을 입력해보자.

 

 

cd.. 은 폴더의 하위 폴더로 가게 해준다. 그리고 아까 압축해제한 폴더에서 C:\java\jdk-15.0.2\bin를 찾아둔다. 그리고 cd C:\java\jdk-15.0.2\bin을입력하면 위에 상황과 같이 된다. 

여기에 두 가지 명령어를 입력해볼 수 있는데, java -version과 javac이다.

 

javac는 java의 컴파일러로 우리가 코딩을 해놓은 소스코드를 실행가능한 파일로 바꿔주는 역할을 한다. java 명령어는 바꿔놓은 파일을 java를 통해 실행할 수 있게끔 한다. (일반적으로 윈도우 환경에서 IDE를 사용하게 되면 이러한 내용은 몰라도 상관없다. 하지만 서버환경에서나 IDE가 없는 경우는 이렇게 컴파일하고 실행해야 한다. 그래서 한번은 이렇게라도 진행해보는 것이 중요하다. ) 

 

* IDE는 통합개발툴인데, 비주얼 스튜디오, 비주얼 스튜디오 코드, 인텔리제이와 같은 것을 의미한다.

 

 

 

자 그렇다면 매번 이렇게 귀찮게 실행해야 하는가 싶지만 그렇지 않다. 우리는 환경변수를 활용해서 자바가 설치된 폴더까지 안 가더라도 언제 어디서든 사용할 수 있도록 만들어 줄 것이다. 일반적으로 환경변수는 PATH를 설정해준다고 하는데, 컴퓨터한테 자바가 어디에 설치되어 있는지 알려주는 이정표 역할을 해주는 것이다. 

 

 

 

4. 자바 환경변수 설정하기


자바 환경변수 설정에는 명령프롬프트를 활용하는 방법과 시스템 환경설정을 통해서 하는 방법이 있는데, 명령프롬프트를 이용한 방법은 명령프롬프트가 꺼지면 초기화된, 시스템 환경설정을 이용해서 진행하도록 한다.

 

제어판 -> 시스템 정보 -> 고급 시스템 설정을 클릭한다. [혹은 내 컴퓨터(내 PC) -> 오른쪽 클릭 -> 속성]

 

고급 시스템 설정을 클릭한 뒤에 -> 환경변수를 눌러준다. 

 

 

그 뒤에 새로 만들기를 눌러준다.

 

 

 

시스템 변수 편집에서 변수 이름에는 JAVA_HOME을 적어주고 변수 값에는 Java가 설치된 공간을 넣어주면 된다. 컴퓨터에게 자바가 여기에 설치되어 있다고 알려주는 것이다. 경로에 대한 변수를 할당하며, 그 변수는 JAVA_HOME이다. 대부분의 Java IDE 가 JAVA_HOME을 쓰고 있으므로 우리도 그에 따라 맞춰서 저장한다.

 

 

 

그 다음으로 Path를 입력할 것이다. 

Path를 눌러주고 편집을 누르자.

 

그러면 이렇게 나오게되는데, 

 

여기서 %JAVA_HOME%bin 을 입력해주자. 이것은 아까 저장한 JAVA_HOME이라는 변수에는 자바가 어디에 설치되어 있는지 알려주는 경로가 들어있다. 그곳에서 bin폴더가 있는 곳을 알려주는 것이다. (여기서 bin의 의미는 binary의 bin이다. 일반적으로 실행파일의 의미를 가지고 있다. 그래서 실행파일의 위치는 여기에 있다. 라고 알려준 것이다.)

 

여기까지만 해도 java는 실행이 되지만 추가적으로 classpath가 들어있다. 클래스 파일의 경로를 알려주는 것으로 환경변수로 마찬가지로 관리한다. 자동으로 등록되기도 하지만, 환경변수로 등록해보도록 하자.

 

다시 한번 새로 만들기를 누르고

CLASSPATH와 %JAVA_HOME%\lib를 등록해주자.

'\' 이 문자는 Enter 위에 존재한다. 자주 쓰이므로 잘 기억해두도록 하자.

 

자 이제 등록이 끝났다.

잘 되었는지 확인하려면 아까와 같이 명령프롬프트를 켜고! javac 혹은 java -version을 입력하면 된다. 그리고서 정상 메시지가 출력되면 설정은 완료된 것이다. 

 

자바가 설치되어 있는 곳까지 가지 않더라도 같은 메시지가 나오는 것을 확인할 수 있을 것이다.

이런식으로 D폴더에 위치하고 있어도 잘 나오는 것을 확인할 수 있다. 컴퓨터에게 경로를 잘 알려주고 있는 것이다. 

 

지난 시간에는 이미지의 출력을 간단한 예제와 함께 살펴보았다. 이번에는 입력 받아둔 이미지를 간단한 변환인 가우시안블러를 적용해보도록 하자.

 

1. 가우시안 블러 GaussianBlur()


가우시안 블러는 이미지를 부드럽게 만들어주는 필터 같은 것이다. 가우시안이나 이와 비슷한 커널을 활용해서 이미지에 담긴 정보량을 줄여준다. 이미지 처리에서는 너무 많은 정보로 인해 오히려 정보 사이의 유의미한 연결 고리를 찾기 어려울 수 있으므로 가우시안 블러를 통해 줄여주는 것이다.

 

결과부터 먼저 살펴보자.

왼쪽이 가우시안블러가 적용된 이미지, 오른쪽이 원본이미지이다. 뿌옇게 변한 것이 가우시안 블러이다. 

 

실습을 바로 해보도록 하자.

#include <opencv2/opencv.hpp>			// 헤더 파일을 가볍게 만들기 위해 교체!

using namespace cv;

int main(int argc, char** argv) {
	Mat img = imread("cat.png");
	Mat blurredImg;						//가우시안 처리가 된 이미지를 담을 변수

	if (img.empty()) 
		return -1;

	namedWindow("img", WINDOW_AUTOSIZE);		// 입력 결과를 넣을 윈도우 만들기
	namedWindow("blurredImg", WINDOW_AUTOSIZE);	// 출력 결과를 넣을 윈도우 만들기

	imshow("img", img);		

	GaussianBlur(img, blurredImg, Size(5, 5), 3,  3);
	GaussianBlur(blurredImg, blurredImg, Size(5, 5), 3, 3);

	imshow("blurredImg", blurredImg);

	waitKey(0);

	
}

지난 시간에 적용했던 코드를 활용하고 있다.

 

Mat img = imread("cat.png");

Mat blurredImg;

입력에는 img 변수를 사용하고 있으며, 출력에는 blurredImg를 선언해서 넣어주려고 한다. 여기서는 OpenCV가 자동으로 가우시안블러를 적용함으로써 줄어든 메모리를 자동으로 할당하고 메모리 크기를 조정해준다는 점이다. (간단히 우리를 편리하게 자동으로 조정/재할당 해준다.)

 

namedWindow("img", WINDOWnamedWindow("img", WINDOW_AUTOSIZE); 
namedWindow("blurredImg", WINDOW_AUTOSIZE); 

입력과 출력 결과를 넣을 윈도우를 먼저 만들어줘야 한다. 우리의 눈에 비교가 되야 어떤 부분이 달라진지 알 수 있지 않겠는가? 그래서 두 개의 윈도우 창을 만들어 준다. 

imshow("img", img);

먼저, 가우시안블러를 적용하기 전이므로 원본 이미지를 출력해준다.


GaussianBlur(img, blurredImg, Size(5, 5), 3,  3);
GaussianBlur(blurredImg, blurredImg, Size(5, 5), 3, 3);

그 다음으로 가우시안 블러를 적용해준다. 여기서는 두 번 연속으로 가우시안블러를 적용하고 있다. 1번만 해도 상관없지만 조금 더 들여다 보기 위해 2번의 가우시안 블러를 적용해보았다. 2번 째 중복된 가우시안 블러 호출은 자기 자신이 입력과 출력으로 사용되는 위에서 이야기했듯이, Mat 구조체에 해당하는 메모리가 자동으로 조정/재할당을 함으로써 메모리 사용을 최적화해준다. (아주 편리하다! 감사합니다 개발자님들)


imshow("blurredImg", blurredImg);
가우시안 블러가 완료된 것을 윈도우에 출력해준다. 


waitKey(0);

사용자 입력을 대기함으로써 마무리가 된다.

 


GaussianBlur(img, blurredImg, Size(5, 5), 3,  3);
GaussianBlur(blurredImg, blurredImg, Size(5, 5), 3, 3);

 

우리는 이 부분을 조금 더 살펴보기 위해서 코드를 조금 조정할 필요가 있다.

 

일단 코드는 이렇다.

#include <opencv2/opencv.hpp>			// 헤더 파일을 가볍게 만들기 위해 교체!

using namespace cv;

int main(int argc, char** argv) {
	Mat img = imread("cat.png");
	Mat blurredImg1, blurredImg2;						//가우시안 처리가 된 이미지를 담을 변수

	if (img.empty()) 
		return -1;

	namedWindow("img", WINDOW_AUTOSIZE);		// 입력 결과를 넣을 윈도우 만들기
	namedWindow("blurredImg1", WINDOW_AUTOSIZE);	//중간 결과를 넣을 윈도우 만들기
	namedWindow("blurredImg2", WINDOW_AUTOSIZE);	// 마지막 결과를 넣을 윈도우 만들기

	imshow("img", img);		

	GaussianBlur(img, blurredImg1, Size(5, 5), 3,  3);
	GaussianBlur(blurredImg1, blurredImg2, Size(5, 5), 3, 3);

	imshow("blurredImg1", blurredImg1);
	imshow("blurredImg2", blurredImg2);

	waitKey(0);

	
}

중간 과정을 넣을 

namedWindow("blurredImg1", WINDOW_AUTOSIZE); 를 추가했으며, 

 

imshow("blurredImg1", blurredImg1);
imshow("blurredImg2", blurredImg2);

 

확인할 수 있는 코드를 두 개 정도 더 추가해서 변화 과정을 관찰하고자 하였다.

 

다음과 같이 블러가 점진적으로 진행됨을 확인할 수 있다.

 

그렇다면 가우시안 블러의 함수 원형을 살펴보도록 하자.

 

기본 원형은

void cv::GaussianBlur( InoutArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT)

로 이루어져 있다. src는 원본 소스, dst는 출력할 소스를 의미한다. Size는 가우시안 블러를 어떤 범위로 처리할 것인지에 대한 이야기를 하고 있다. 여기서는 5×5 형태로 만들어주고 있으며, 값에 따른 결과는 한번 확인해보도록 하자.(다만 영역의 중심 픽셀에서부터 처리되므로 홀수로 처리해야 한다.)

 

가우스안블러는 수학에서 사용되는 수식을 활용하는데, 정확한 수학적 근거를 보고 싶은 사람은 이곳을 방문하자. 수학적인 해석은 차후 시간이 되면 다루도록 하겠다.

 

* 수식을 풀어서 간단히 요약해서 말하자면 사각형의 범위를 두고 그 범위에 해당하는 수치의 적당한 값으로 수치를 변경해버리는 것이다.

정확한 계산은 아니지만 이런 느낌으로 만들어버리는 것이다. 


여기서 추가로 다운 샘플링 등과 같은 복잡한 형태의 이미지 변환도 존재한다. 이는 나중에 다루도록 하겠다.

 

출처

Computer Vision: Algorithms and Applications, 2nd ed, 2021 Richard Szeliski , szeliski.org/Book/ 

docs.opencv.org/2.4/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.html

docs.opencv.org/4.5.1/d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1

 

1. 라이브러리들

OpenCV에는 다양한 라이브러리와 모듈이 존재한다. 어떤 모듈이 존재하는지는 OpenCV를 설치한 곳에 가면 볼 수 있으며, 공식 웹사이트에서도 레퍼런스를 얻을 수 있다. 어떤 모듈이 존재하는지만 머릿속에 넣어두면 이를 시기적절하게 써주면 되는 것이다. 마치 공구 상자함에 무엇이 들어있는지 알고 있다면 어떤 일을 하던지 수월하게 할 수 있을 것이다. 하지만 어떤 공구가 들어있는지 인지가 되지 않는다면 힘들게 일할 것이다. 

 

D:\opencv\sources\modules 

 

필자는 D:\에다가 opencv를 설치했으므로 이렇게 나오는 것이지만 설치한 파일에 따라서 다 다르다. 이곳에 기본적인 모듈을 확인할 수 있다.

 

 

이렇게 폴더의 형태로 존재함을 볼 수 있다. 각각의 기능을 하나하나 실행시키는 것도 좋은 일이지만, 어떻게 사용하는지 알아볼 수 있는 설명서가 있는데, 그것이 레퍼런스이다.

docs.opencv.org/4.5.1/

 

OpenCV: OpenCV modules

OpenCV  4.5.1 Open Source Computer Vision

docs.opencv.org

이곳에 가면 여러가지 모듈을 확인하고 설명서를 볼 수 있다. 자주자주 방문하는 습관을 들이자.

 

2. 헤더


opencv2/opencv.hpp에는 OpenCV의 모든 기능을 사용할 수 있도록 모든 헤더파일이 포함되어 있다. 그래서 하나만 넣어도 충분히 컴파일이 가능하다. 하지만 닭 잡는데 소 잡는 칼을 쓸 수는 없는 법이다. 물론 그래도 되지만 너무 힘들다. 헤더파일도 마찬가지이다. 너무 큰 헤더 파일은 컴파일 시간을 늘린다. 그러므로 가볍게 만들어주는 것도 중요하다. 

#include<opencv2/opencv.hpp>	// OpenCV의 기능을 사용할 수 있게 해주는 헤더파일

int main(int argc, char** argv) {
	cv::Mat img = cv::imread("cat.png");

	imshow("img", img);
	cv::waitKey(0);

	return 0;
}

이전 블로그 글에서 사용한 코드를 헤더파일만 바꾸었다. 

[Computer Science/OpenCV] - [OpenCV]OpenCV란 무엇인가? 그리고 설치

 

실제로 두개를 모두 컴파일 해보면 차이남을 알 수 있다. cv::를 사용하고 싶지 않다면 using namespace cv;를 활용하면 cv::를 붙이지 않아도 된다. 이는 C++에서 클래스 이름을 붙여주는 것이므로 컴파일러에게 사전에 알려주는 것이다. 

#include<opencv2/opencv.hpp>	// OpenCV의 기능을 사용할 수 있게 해주는 헤더파일

using namespace cv;				// namespace cv를 알려줌으로써 미리 선언해주는 역할을 한다.

int main(int argc, char** argv) {
	Mat img = imread("cat.png");

	imshow("img", img);
	waitKey(0);

	return 0;
}

여기서 헤더 파일이 너무 많은 헤더 파일을 가지고 있으므로 필요한 기능을 담고 있는 헤더파일만 포함시키면 다음과 같다.

#include"opencv2/highgui/highgui.hpp"			// 헤더 파일을 가볍게 만들기 위해 교체!

using namespace cv;

int main(int argc, char** argv) {
	Mat img = imread("cat.png");

	if (img.empty()) return -1;

	namedWindow("img", cv::WINDOW_AUTOSIZE);
	imshow("img", img);
	waitKey(0);

	destroyWindow("img");

	return 0;
}

OpenCV에는 다양한 유형의 이미지 파일을 읽을 수 있는 유틸들을 제공한다. 기본 패키지 상에 포함되어 있는 HighGUI는 이를 도와준다. 위의 코드는 HighGUI를 활용해서 이미지 파일(여기서는 cat.png)를 열고 화면 상에 출력해주는 역할을 하고 있다.

 

여기서 int argc, char** argv는 argument라하는 인수들이 저장되는 공간이 된다. argc는 argument가 몇 개인지 알려주는 것이며, argv는 char형으로 저장되는 변수인데 배열로써 저장된다. 가장 처음에 있는 argv[0]는 실행 파일명이 저장되며, 그 뒤부터 argv[1], argv[2] ....  의 순서대로 사용자가 입력한 argument가 저장된다.

 

3. 코드 해설


다음 코드를 하나씩 해설해보면서 각각의 코드가 어떤 의미를 가지고 있는지 살펴보도록 하자.

 

#include"opencv2/highgui/highgui.hpp"	

using namespace cv;

int main(int argc, char** argv) {
	Mat img = imread("cat.png");

	if (img.empty()) return -1;

	namedWindow("img", cv::WINDOW_AUTOSIZE);
	imshow("img", img);
	waitKey(0);

	destroyWindow("img");

	return 0;
}

헤더 파일은 제외하고 main 함수 내부에 있는 것들을 살펴보도록 하자.

  1. Mat img = imread ("cat.png");

  2. if(img.empty()) return -1;

  3. namedWindow("img", cv::WINDOW_AUTOSIZE);

  4. imgshow("img", img);

  5. waitKey(0);

  6. destroyWindow("img");

이런 순서대로 살펴보도록 하자. 

1. Mat img = imread ("cat.png")

먼저 나오는 imread 이다.(namespace cv가 없으면 cv::imread) image read 라고 생각하면 되는데, 파일 이름을 기반으로 파일의 포맷을 결정해준다. 예를 들어, cat.png이므로 파일 포맷 PNG에 해당하는 데이터 구조에 필요한 메모리를 자동으로 할당해주는 것이다. 이미지 파일과 관련된 다양한 포맷을 지원한다. (BMP, JPEG, JPG, PNG, DIB, PPM, TIFF 등등 다양한 이미지 포맷을 지원한다.) imread는 최종적으로 구조체 Mat의 형태로 반환한다. 

 

Mat은 구조체로써 OpenCV의 기본을 이루는 구조체라 봐도 무방할 정도로 많이 쓰이는 구조체이다. 이미지 상에 담고 있는 정보를 처리한다. 이 정보는 단일 채널, 다중 채널, 정수 값, 부동 소수 값 등으로 컴퓨터가 이미지를 받아들이는데 사용되는 다양한 데이터를 의미한다. Mat 구조체의 기본 상속은 다음과 같다.

 

조금 더 자세한 내용은 docs.opencv.org/4.5.1/d3/d63/classcv_1_1Mat.html 이곳에서 보자.

 

2. if(img.empty()) reuturn -1;

Mat구조체의 이름을 img라 정했으며, 1번에서 imread를 통해 읽어들인 cat.png 파일을 Mat이라는 구조체 변수, 이름은 img에 넣었다. 이를 통해 img.empty()는 받은 파일이 비어있는지 아닌지를 판단해주는 것이다. 반환값은 true, false로 전달해 준다. (비어있으면 true로 반환해줌, 속에 무언가 들어있으먄 false를 반환) 

 

3. namedWindow("img", cv::WINDOW_AUTOSIZE);

namedWindow 함수는 High-level GUI, HighGUI 모듈에 속하는 함수이다. 화면에 이미지를 표시할 수 있는 윈도우를 열어준다. 인수가 두 가지가 있는데, 첫번째 인수는 윈도우 이름을 지정한다. 만약에 이름이 있으면(중복되면) 아무일도 하지 않는다. 두 번째 인수는 윈도우 사이즈를 결정해주는데,

  • 윈도우 사이즈는 자동으로 이미지 크기와 같을 것인지 - WINDOW_AUTOSIZE (이미지 사이즈에 맞춰 자동 조정되며 이후에 사용자가 조정 가능하다. 하지만 윈도우 창 크기를 마우스로 늘러거나 줄이는 것은 불가능하다. 함수에 의해서 조절해야 한다.)
  • 이미지 사이즈 관계없이 동일한 값으로 만들 것인지 - 0 (기본값이다.), 처음에 만들어진 값은 고정 값으로 만들어지지만, 마우스를 통해 늘리거나 줄이는 것이 가능하다.

두 번째 인수에 들어갈 flag값은 여기에서 확인이 가능하다. 

HighGUI는 4가지의 주요한 함수가 존재하는데, ButtonCallback, MouseCallBack, OpenGIDrawCallback, TrackbarCallback으로 차례대로 버튼, 마우스, 화면 출력, 트랙바에 해당하는 값을 담당한다. [opencv2/highgui.hpp 헤더에 들어있다.] 기본으로 제공된 함수 외 더 많은 기능을 사용하고자 한다면 Qt 를 활용해서 확장해나가면 된다. Qt는 C++을 통해 GUI를 제작하는 크로스플랫폼 프레임워크이다. (C++외에 다른 언어로도 만들 수 있다.) 자동차 계기판 GUI부터 시작해서 스마트 Tv에 들어가는 GUI까지 다양하게 만들어져있다. 

Qt를 더 알고 싶다면 -> www.qt.io/ko-kr/

 

Qt | 임베디드와 데스크탑을 위한 크로스플랫폼 소프트웨어 개발

Qt는 혁신적인 기기와 세련된 UI 및 어플리케이션을 만드는 빠르고, 스마트한 방법입니다. 우수한 크로스플랫폼 소프트웨어 개발을 만나보세요.

www.qt.io

 

4. imgshow("img", img);

Mat구조체 상에 이미지에 대한 정보가 들어있다면 imgshow를 통해 화면에 출력할 수 있다. (조금 더 정확히는 위에서 만든 윈도우에 출력할 수 있다. 만약에 만들어진 윈도우가 없다면 cv::imshow함수는 cv::namedWindow()를 활용해서 새롭게 생성한다. ) 실제로 보여주는 역할을 하게 해주는 함수이다.

 

5. waitKey(0);

waitKey(0); 의 기본 원형 int cv::waitKey ( int delay = 0 ) 의 원형을 가지고 있으며, 키 입력이 있을 때까지 기다리는 함수이다. 인수는 밀리세컨드 단위로 대기하는 것이다. 0 또는 음수로 설정이 될 경우에, 키 입력을 무한히 기다리는 형태이다. (항상 조심해야 하는 것은 시간의 단위가 밀리세컨드 단위라는 점이다! - millisecond는 1000 분의 1초이다. 0.5초라면 500 millisecond)

 

6. destroyWindow("img");

OpenCV는 메모리 사용에 대해서 많은 고려가 되었는데, destroyWindw 또한 메모리 해제와 관련된 함수이다. 일반적으로 표준 템플릿 라이브러리(STL)의 스코프 밖으로 벗어나게 되면 자동으로 메모리 할당이 해제 되지만, 규모가 조금이라도 커진다면 프로그래머가 임의로 해제해줘야 하는 상황이 발생할 수도 있다. destroyWindow는 윈도우를 닫고 관련된 모든 메모리 사용에 대해 해제하는 역할을 해준다. (메모리 누수를 방지하기 위해 중요한 역할을 한다.) 위의 코드 상에는 사실 필요가 없지만, 이러한 것이 있다라는 것을 보여주기 위해 넣어두었다.

 

 

OpenCV 로고

1. OpenCV


OpenCV는 Open Source Computer Vision의 약자로 영상 처리에 사용할 수 있는 오픈 소스 라이브러리 입니다. 컴퓨터가 사람의 눈처럼 인식할 수 있게 처리해주는 역할을 하기도 하며, 우리가 많이 사용하는 카메라 어플에서도 OpenCV가 사용하기도 한다. (추가로 자율주행자동차에서 자동차의 눈이 되주는 것이 카메라와 OpenCV가 합작해서 해낸 일이다.) 추가로 사용되는 예로는 

  • 공장에서 제품 검사할 때
  • 의료 영상 처리 및 보정 그리고 판단
  • CCTV영상
  • 로보틱스

등 다양한 범위에서 사용되고 있다. 카메라로 찍어서 할 수 있는 모든 일은 OpenCV로 처리할 수 있다. 여기에 머신 러닝과 A.I를 활용해서 그 활용도를 더욱 넓혀가고 있는 중이다.

이런 느낌의 일을 할 수 있다.
사진을 보정

 

OpenCV가 더욱 인기있는 이유는 오픈소스이지만 BSD(Berkely Software Distribution)라이선스를 따르기 때문에, 상업적 목적으로 사용해도 좋다. 그리고 소스코드 공개 의무가 없다는 점에서 강점을 가지고 있다. OpenCV의 기원은 인텔에서부터 시작되는데, 컴퓨터 비전과 인공지능의 발달 시키고자 하는 바램으로 OpenCV를 출시한 것이다. (with Grary Bradski) 

 

OpenCV는 실시간 처리에 중점을 두고 설계되서 빠른 속도와 효율성을 자랑한다. 기반 언어는 C++로 멀티 코어 프로세서를 활용할 수 있다. 심지어 인텔IPP(Integrated Performance Primitives)를 통한 최적화 루틴을 활용함으로써 로우레벨에서 자동화된 최적화를 사용할 수 있다. 이전에는 유료로 구매해야 했지만, OpenCV 3.0 부터는 IPP의 일부를 무료로 제공해주고 있다. 

[사실 인텔은 OpenCV를 배포함으로써 OpenCV가 점차 발전함에 따라 빠른 프로세서가 필요시 되고 이는 인텔 프로세서의 수요가 늘어나 수입이 늘어나는 큰 그림을 그리고 있었다.]

그렇다면 여기서 가장 중요한 단어인 컴퓨터 비전이란 무엇인가?

 

2. 컴퓨터 비전?


컴퓨터 비전은 카메라로 얻은 일련의 영상들을 모두 컴퓨터 비전이라 한다. 사람은 눈을 통해 많은 정보를 받아들인다. 지금 이 글을 읽는 순간에도 눈을 통해서 읽고 있지 않은가? 프로그래밍에서 항상 생각해보아야 할 것 중 하나의 원칙은 '사람에게 쉬운 일은 컴퓨터에게 어려울 수 있다.'라는 말이다. 컴퓨터 비전 또한 마찬가지이다. 사람에게 너무나 쉬운 보는 일은 컴퓨터에게는 너무나도 어려운 일이다. 하나의 사진에서 사람을 가려내고, 그 속에서 지나는 여러 사물을 골라내는 일은 컴퓨터에게 어렵다. 사람은 이렇게 어려운 일을 자연스럽게 해낸다. 카메라의 역할을 하고 있는 눈은 빛을 자연스럽게 조절하며, 초점을 자동으로 조절한다. 정말 대단한 일인 것이다. 카메라는 이를 일일히 작업해서 맞춰줘야 한다. 카메라가 사진을 찍으면 컴퓨터는 이를 단순한 숫자로 인식할 뿐이다. 오로지 0과 1로 이루어져서 다시 나올 뿐이다. 

 

컴퓨터는 단순히 숫자로 이루어진 형태로 사진을 인식할 뿐이다.

컴퓨터는 이러한 숫자의 행렬로 사진 및 여러 형태를 인식한다. 그렇다면 우리는 이러한 형태를 가지고 컴퓨터에게 유의미한 정보를 입력해줌으로써 사람이 보는 시선과 최대한 비슷하게 만들어야 하는 것이다. 하지만 여기에는 많은 문제가 도사리고 있다. 우리의 시각 정보는 왜곡이 많다. 예를 들어 우리가 보는 관점에 따라 사물이 왜곡될 확률이 있다. 다른 왜곡은 빛의 양에 따라 달라지기도 하며 비가 오는 경우에는 더욱 심각해진다. 심지어 카메라의 성능에 따라 계속 변한다. 전기적 노이즈도 생각해봐야 한다. 이러한 왜곡을 이겨내고서 우리는 정확한 이미지 처리가 필요한 것이다. (심지어 카메라는 3D 정보를 2D로 받아들이고 있다.) 

 

이 부분에 대한 해결책은 머신러닝 기술로 어느정도 보완하고 있다. 혹은 다른 추가적인 데이터를 활용해서, 예를 들어 라이다 센서 혹은 거리 센서를 활용해서 왜곡정보를 올바르게 해석하기 위한 노력을 하고 있다. 그리고 OpenCV는 이러한 다양한 문제들을 해결하기 위한 도구를 제공해주는 것을 목표로 한다. 지금도 많은 연구가 이루어지고 있으며, 다양한 자료들이 쏟아져 나오고 있다. 

 

OpenCV와 사용할 수 있는 언어로는 C/C++, 파이썬, Java등이 있다. 요새 많이 쓰이는 언어로는 파이썬이 많이 사용되고 있다. 빅데이터와 머신 러닝에서 강점을 보이고 있기에 파이썬이 많이 쓰인다. 하지만 이 블로그에서는 C++을 통해서 사용하도록 할 예정이다. 나중에 기회가 된다면 파이썬을 통한 머신러닝과 딥러닝 그리고 A.I를 사용할 때 파이썬을 사용하려 한다. 하나의 언어를 제대로 배워두면 다른 언어에 대한 장벽은 높지 않은 편이므로 일단은 C++로 진행하려 한다. 

 

3. 기본 구조


OpenCV의 기본 아키텍처는 다음과 같다.

기본 아키텍처

각 요소를 살펴보자면,

  • CV : Computer Vision으로 기본 구성 요소에서는 기본 이지미 처리와 고급 컴퓨터 비전 알고리즘을 포함하고 있다.
  • ML (Machine Learning) : 머신러닝이 주를 이루므로 이를 활용할 수 있는 기본적인 통계 분류기와 클러스터링 도구를 포함하고 있는 라이브러리들이 있다.
  • HighGUI : OpenCV에 기본으로 포함되어 있는 GUI이다. 여기에는 비디오와 이미지 저장 그리고 이를 로드하기 위한 I/O 루틴을 포함하고 있다. 이 모듈을 활용해서 사용자의 입력을 받고 그에 따른 출력하는 기능을 하는 유저 인터페이스 기능을 하고 있다. 기본 기능으로 지원하고 있지만 조금 더 범용적으로 Qt를 사용한다. (윈도우 GUI 툴킷 정도라 생각할 수 있다.)
  • CXCORE : 이곳에는 기본 데이터 구조와 여러 content가 구성되어 있다. 

OpenCV 아키텍처 (TBB는 Threading Building Blocks - 병렬처리를 위한 것이라 생각하면 된다.)

다른 관점에서 보자면 이러한 아키텍처 구조를 갖는다. 다양한 라이브러리의 모듈이다. 업데이트가 되면 달라지겠지만 현재 모듈 구성은 다음과 같다.

  • Core - 모든 객체 타입과 기본 연산자가 들어 있는 라이브러리 섹션

  • Imgproc - 이미지 처리 모듈로써 이미지 변환 등을 포함하고 있다.

  • highgui - 위에서 설명했다. ( 사용자의 입력을 받는 유저 인터페이스 기능 포함)

  • video - 비디오 라이브러리로써 비디오 스트림을 read/write하는 함수가 포함되어 있다.

  • calib3d - 캘리브레이션하는데 필요한 알고리즘이 포함된 모듈

  • features2d - 중요한 feature(특징)을 탐지하고 표현, 매칭하기 위한 알고리즘이 구현된 모듈

  • objdetect - 말 그대로 오브젝트 디텍트, 특정 오브젝트를 탐지하는 알고리즘이 들어있는 모듈이다. 이를 머신 러닝으로 기계 학습 시켜서 특정 물체들을 탐지할 수 있다.

  • ml - 머신러닝 라이브러리

  • flann - Fast Library for Approximate Nearest Neighbors 나중에 이야기하겠지만, 머신러닝에 사용되는 알고리즘이다. 자세한 내용은 

flann의 자세한 내용은 공식 깃헙 [github.com/mariusmuja/flann]에 있다.

  • gpu - 그래픽 카드를 이용한 연산을 사용한다. 일명 그래픽카드 연산을 위한 라이브러리이다. CUDA연산에 최적화 되어 있다. 당연히 머신러닝을 위한 설계이다. CUDA (Computed Unified Device Architecture)로써 NVIDIA에서 개발한 GPU 개발툴이다. 딥러닝에서 사용하기 위해서 만들어졌으며, 하드웨어에서는 얻을 수 없는 연산을 할 때 많이 사용된다. 비트코인 채굴할 때 사용하는 것이 CUDA이다. (tensorflow도 사용된다.)

  • photo - 사진을 활용할 수 있는 다양한 도구를 포함하고 있다.

  • stitching - 스티치 파이프라인을 구현하기 위한 모듈, Image stitching이란 이미지를 포갤 지점을 찾는 과정이라 생각하면 된다. 이를 빠르게 하는 파이프라인을 구현하기 위한 모듈이라 생각하면 된다.

  • nonfree - OpenCV에서 특허나 사용 제한이 걸려있는 알고리즘의 구현이 이곳에 있다. ( 예를 들어 SIFT알고리즘)

등이 존재한다.

 

4. 다운로드 및 설치


앞서 이야기했듯이 설치는 C++로 진행할 예정이다. 바인딩 용 언어는 Java, C++, Python 등을 많이 사용하지만 그 원론에 다가가고자 C++를 이용해서 설치하고 실습해볼 예정이다. 처음 배울 때는 역시 라이브러리가 만들어진 언어 혹은 권장하는 언어가 좋다. 필자는 그냥 C++가 빨라보여서 C++를 사용하고자 한다.

 

선행조건으로 Visual Studio가 설치되어 있어야 한다. 설치는 

visualstudio.microsoft.com/ko/downloads/ 이곳에서 할 수 있다. [커뮤니티]로 설치하면 된다. 공짜다

기본 설치 옵션으로 당연히 C++를 사용할 것이므로 "C++를 사용한 데스크톱 개발"을 체크해줘야 한다. 어차피 체크 못했어도 나중에 추가할 수 있으므로 상관이 없다. 

 

새 프로젝트 만들기 선택

먼저, 프로젝트를 만들어주고, 

 

 

Window 데스크톱 마법사 -> 다음을 눌러준다.

 

 

 

적당한 프로젝트 이름을 만들어준 뒤에, 만들기 버튼을 클릭!

 

 

빈프로젝트 체크박스에 체크해주고 확인 버튼을 누르자.

 

소스파일에서 오른쪽 클릭!

 

 

 

그러면 이렇게 나오는데, 여기서 추가 -> 새 항목을 클릭

 

 

이렇게 C++ 파일을 눌러주고 추가를 누르면 완성!

여기서 이름을 잘 보면 cpp는 C++(씨플플)으로 만들어지며, 확장명이 .c로 끝나면 C언어로 구성된다.

 


opencv.org/releases/

 

Releases - OpenCV

Become a Member Stay up to date on OpenCV and Computer Vision news Join our Newsletter  

opencv.org

OpenCV공식 홈페이지로 들어가면 다양한 버전이 나온다. 안정화 버전은 버전 3.4.13, 최신 버전은 4.5.1이다.

여기서는 4.5.1을 통해 진행해보도록 하자.

 

 

자신에게 맞는 운영체제를 선택하면 되지만, 대부분이 Windows이므로 선택!

소스포지에서 기다리면 알아서 다운로드가 시작된다. 적당한 곳에 다운로드를 받자.

211MB의 크기를 가진다. 배포 서버에 따라 속도가 천차만별 이므로 일단은 기다리자. 다운로드 받은 뒤에는 나머지 창은 꺼도 좋다. 

파일명은 opencv-4.5.1-vc14_vc15.exe 이다.

 

 

실행하면 별거 없다. Extract누르자. 이건 단순히 압축해제를 시켜주는 것이다. C:\나 D:\에다가 해두면 된다.

 


자 이제 비주얼 스튜디오로 가자.

파일을 하나 만들고 (파일명은 main.cpp로 하자)

프로젝트란에 있는 속성을 누르자.

 

구성 : 모든 구성, 플랫폼 : x64로 하자 (기본 운영체제 구성이 64비트면 x64, 32비트면 win32를 선택하면 된다.)

그리고서 좌측에 있는 C/C++ 란에 일반을 클릭한 뒤

추가 포함 디렉터리에 D:\opencv\build\include를 입력한다.

만약에 다른 곳에 저장되어 있으면 저장된 위치에 있는 [ 저장된위치\opencv\build\include ]를 입력해주면 된다.

 

이번에는 링커 탭에 있는 일반으로 간다.

거기에도 마찬가지로 추가 라이브러리 디렉터리 란에

D:\opencv\build\x64\vc15\lib 를 입력해준다. 

 

링커탭에 입력란으로 눌러준다.

그러면 추가 종속성이 있는데, 여기에 opencv_world451d.lib;를 입력해준다. 세미콜론 ;을 꼭 넣어줘야 한다. 컴퓨터가 인식할 때는 세미콜론으로 구분하기 때문에 반드시 넣어주자!

 

여기에 넣는 문장은 설치한 파일명을 명확히 입력해야 한다.

필자는 4.5.1 버전을 설치했으므로 opencv_world451d.lib가 나온것이다. 

일반적으로 [ 설치한 폴더\opencv\build\x64\vc15\lib ]에서 확인할 수 있으므로 확인해보고 가자! 

 

마지막으로

 

x64로 되어 있는지, 디버그 모드인지 확인하자.

 

자 이제 프로젝트 명을 오른쪽 클릭하면 여러 속성이 나오는데, 여기에서 파일 탐색기에서 폴더 열기를 눌러준다.

 

그리고서,

D:\opencv\build\x64\vc15\bin여기에 들어가면

 

파일 두 개가 있다. 이것을 아까 열어둔 파일 탐색기에서 폴더 열기 를 한 곳에다가 복사! 하면 된다.

 

 

프로젝트 폴더 안에 같이 나란히 존재하면 된다. 아까 사용했던 lib 파일이 아니다. 

dll 확장자를 가진 파일이다. 유의하자. 컴파일러에게 파일과 파일을 연결해주는 역할을 해준다. (동적 링크라고 하며, 실행파일에서 라이브러리 기능을 사용 시에, 라이브러리를 참조해서 기능을 호출해주는 역할을 하는 것이다.)

 


이제 프로젝트 파일에다가 코딩 테스트를 할 png 파일을 가져다 두자.

cat.PNG
0.39MB

프로젝트 폴더는 일반적으로 C:\Users\<사용자명>\source\repos\Project_OpenCV_1\Project_OpenCV_1

에 들어있다. 못 찾겠으면 위에 올라가서 탐색기에서 열기를 다시 활용하자.

 

아까 만들어 놓은 main.cpp에다가 입력하자.

#include<opencv2/imgcodecs.hpp>
#include<opencv2/video.hpp>
#include<opencv2/highgui.hpp>

#include<iostream>
#include<stdio.h>

using namespace std;

int main(int arg, char** argu) {
	cv::Mat img = cv::imread("cat.png");

	imshow("img", img);
	cv::waitKey(0);

	return 0;
}

확인할 용도이므로 나중에 설명하도록 하자.

 

타이핑이 완료되었다면, 

디버깅 시작을 누르고 잠시 기다리면 프로그램이 시작된다.

 

귀여운 고양이가 나온다면 완료! 

정말 고생했다. 이로써 우리는 OpenCV를 사용하기 위한 기본 셋팅을 완료한 것이다.

 

다음 시간에는 OpenCV에서 사용되는 기본적인 함수를 사용하면서 하나하나 이야기해보도록 하자.

 

 

참고 자료

docs.opencv.org/master/index.html

node를 사용하다보면 나오는 npm과 npx 두 가지가 존재한다.

npm은 Node Package Manager의 약자이다. (노드 패키지 매니저)

npx 는 Node Package eXecute의 약자이다. 조금 더 정확하게는 [A tool for executing Node Packages]

npx의 경우 노드 패키지 실행이라는 의미이다.

 

말에서부터 알 수 있듯이 npm은 패지키 매니저를 담당하고 있으며

npx는 실행을 담당하고 있음을 알 수 있다. 

 

우리는 npm 버전 5.2.0 이상부터는 npx를 사용할 수 있다. npx는 npm 사용시에 발생하는 발생할 수 있는 여러 문제점을 해결하기 위해 설계되었으며, 사용법은 npm과 비슷하게 사용된다. (그래서 사용하기 편하다!)

 

 

npm 대신해서 npx를 사용하는 방법은 너무나도 간단하다. 

npm을 쓰는 것 처럼 npx를 사용하면 된다.

 

지난 몇 년 동안은 npm은 의존성 문제로부터 우리를 편하게 해주었다. 다양한 프로젝트 별 패키지를 package.json으로 관리함으로써 프로젝트마다 설치될 패키지를 한번에 설치할 수 있는 편안함을 제공되어졌다. 이는 사실 npm기반 프로젝트를 실행하려면 단순히 node와 npm이 설치되어 있는지 확인하고 gitrepo를 복제한 뒤에 npm install만 해주고 프로젝트가 잘 실행되는지 테스트하면 바로 끝인 것이다. (npm 스크립트가 경로를 자동으로 추가해주기 때문에 npm install 만으로도 모든 작업이 완료되는 것이다.)

 

이렇게 편리한 npm이지만 설치하는 공간이 항상 node_modules 에 설치되기 때문에 문제가 될 수 있다.

npm -g install

로 global로 설치하게 되면 항상 node_moduls를 찾아서 설치한다. 없으면 만들어서 설치하는 구조로 되어 있다.

그래서 우리가 원하는 곳에만 설치가 하기가 힘들다. (npm 스크립트가 알아서 지정해주기 때문에 대화식으로 설치할 수가 없다.) 

물론 수동으로 지정해서 경로 지정이 가능하지만 이는 일일이 타이핑해야 하므로 자동화를 업으로 삼는 프로그래머에게는 이상적인 해결책이 아니다.

alias npmx=PATH=$(npm bin):$PATH

혹은 

./node_modules/.bin/mocha

이러한 형태로 타이핑 해야하므로 옳지 못하다. 

 

그래서 npx는 이를 간단하게 해결해준다!

 

위와 같은 코드를 사용하려 할 때, 

npx mocha

를 사용하게 되면 동일한 결과를 얻을 수 있으며, 실행이 끝난 뒤에는 자동으로 fallback 시켜준다. (auto-fallback)

여기에 추가로 이미 설치된 바이너리를 불러올 경우, 실행 중인 노드 프로세스에 직접 로드할 수 있다. 이렇게 npx는 다양한 장점을 가지고 있다. 

 

Auto-fallback

 

그렇다면 우리는 위에서 이야기한 상황을 말고 추가로 npx를 사용해야 하는 상황을 알아보도록 하자.

 

1번만 실행되어야 하는 명령


which create-react-app은 create-react-app이 존재하는가를 묻는 명령어이다.

create-react-app을 사용거나 express-generator를 사용해야 하는 상황이라면 1번만 사용된 뒤에는 사용되지 않는다. 우리가 원하는 건 프레임워크가 한번에 한해 설정하는 것이지 지속적으로 이 파일이 남아있는 상황을 원치는 않는다. (필요한 것만 빼가자!)

npx 명령어를 사용하게 되면 $PATH에 관련 <command>가 없다면 npx <command>를 호출하게 되면 npm 레지스트리에서 해당 이름을 찾고서 자동으로 설치하고 호출한다. 호출이 끝나고 난 뒤 패키지는 fallback되어 사라진다. npm 설치로 인해 생기는 오염에 대해 걱정할 필요가 없다! 

 

위와 같은 1회성 설치는 항상 최신 패키지를 가져다 써야 하므로 매번 최신화된 버전으로 업데이트할 필요가 없다. (알아서 최신 버전을 1회용으로 가져와서 설치함으로!) 

npx는 이러한 기능만으로도 다양한 고민거리를 해결해준다. 

 

 

Node.js를 버전 별로 실행할 수 있다!


여기서 -p 옵션은 $PATH 를 추가하는 command이다.

npx로 설치된 node는 각각 버전이 다름을 확인할 수 있다. 그리고 로컬에 설치된 node는 8.1.2로 나머지 1회성 설치로 인해 기존의 로컬 버전은 전혀 오염되지 않았다. 이렇게 버전을 다양하게 사용함으로써 프로젝트 별로 버전을 다르게 적용할 수 있다.

 

gist 기반 스크립트를 공유하기 위해서


모든 유틸리티 스크립트를 gist.github.com을 사용해서 공유하는 것이 보편화되었다. npx를 활용하면 하나의 명령어를 통해 직접적인 호출을 할 수 있다. 

npx https://gist.github.com/zkat/4bc19503fe9e9309e2bfaa2c58074d32

를 입력해보면 위와 같은 화면을 볼 수 있다.

 

 

참조


 

blog.npmjs.org/post/162869356040/introducing-npx-an-npm-package-runner

 

npm Blog Archive: Introducing npx: an npm package runner

npm Blog (Archive); updates from the npm team are now published on the GitHub Blog and the GitHub Changelog

blog.npmjs.org

stackoverflow.com/questions/50605219/difference-between-npx-and-npm

 

Difference between npx and npm?

I have just started learning React, and Facebook helps in simplifying the initial setup by providing the following ready-made project. If I have to install the skeleton project I have to type npx

stackoverflow.com

 

이전 시간에는 

[중학영어]09강. 보어로 쓰이는 to부정사, 동명사, 동사원형, 분사

를 배웠었다. 

품사에서 명사를 꾸며주는 역할을 하는 것은 형용사이다. 그렇다면 형용사적 역할을 하고 있는 to부정사와 분사에 대해 살펴보도록 하자.

to부정사와 분사 외에도

  • 품사 자체가 형용사인 것
  • 관계사(관계대명사, 관계부사)
  • 전치사구( 전치사 + 명사 ) [전명구]

가 있다. 일단 이번에는 to부정사와, 분사(현재분사, 과거분사)에 대해 살펴보도록 한다.

 

명사를 꾸며준다는 의미는 명사를 화려하게 만들어주는 의미가 아니다. 이는 명사의 의미를 조금 더 명확하게 만들어준다는데 의의가 있다.

예를 들어, 

a dog  → 강아지

a big dog  → 큰 강아지

두 의미에서 큰 강아지는 강아지를 조금 더 자세히 설명해주고 있다.

그래서 수식의 의미를 시력이 안 좋은 사람이 안경을 쓰면서 점점 초점이 맞아가는 과정을 이미지화해서 받아들이면 좋겠다.

 


1. 명사를 꾸며주는 to부정사

명사를 꾸며주는 to부정사는 명사 뒤에 위치하며 '~하는 명사', '~할 명사'의 형태로 해석한다.

 

time to go  →  갈 시간

time to study  →  공부할 시간

 

이런 형태로 해석된다. 

 

I bought some books to help me study hard → 나는 내가 공부를 열심히 할 수 있도록 돕는 책을 샀다.

 

I bought some books to help me study hard

some books(책들은)는 나의 공부를 열심히 하게끔 도와주는(to help) 해주는 행위를 하는 것으로 해석되므로 some books가 to부정사의 의미상 주어가 된다.

 

※ 수식을 받는 명사가, to부정사가 나타내는 동작이나 행위를 하는 것으로 해석이 되어진다면, 이 수식을 받는 명사는 to부정사의 의미상 주어가 된다.

 


I'd like some books to study. → 공부할 책이 몇 권 있었으면 좋겠습니다. 

some books를 통해 to study를 할 것이므로, 즉 공부할 책이라는 행위의 대상이 되고 있으므로 some books가 의미상 목적어가 되는 것이다.

※ 수식을 받는 명사가 to부정사가 나타내는 행위의 대상이 되면, 명사는 to부정사의 의미상 목적어가 된다.

 


가끔 to부정사와 전치사가 조합된 형태가 나오기도 하는데 우리의 해석을 방해한다.

[명사 + to부정사 + 전치사]의 형태는 의미상 [ to를 제외한 to부정사 + 전치사 + 명사 ]의 형태로 이해하면 편하다.

예를 들어, 

The student need somebody to study with. 의 문장을 보자.

somebody to study with [명사 + to v + 전치사] 의 형태로 쓰여져 있다.

study with somebody [v + 전치사 + 명사] 로 생각하면서 해석하면 훨씬 자연스러워진다.

→ 최종 문장은 The student need (study with somebody) 처럼 생각하자는 의미이다.

'학생은 필요하다. 함께 공부할 누군가가' 로 해석된다.

 


2. 명사를 수식하는 분사

분사는 두 가지가 존재한다. 현재분사와 과거분사가 있다.

  • 같이 쓰이는 어구가 있을 때는 명사 앞에 쓴다.
  • 같이 쓰이는 어구가 없을 때는 명사 뒤에 쓴다.

v-ing (현재분사)

수식 받는 명사가 동작을 직접하는 능동의 의미를 갖거나, 지금 진행의 의미를 지닌다. 

보통 해석은 '~하는', '~하고 있는' 으로 해석된다.

The man studying in front of me at the cafe was smeared with blood

여기서 The man studying이므로 공부를 하고 있는 남자이다.

[The man studying in front of me at the cafe] [was] [smeared with blood]

→ 카페 안에서 내 앞에 앉아 있는 공부하는 남자는 피투성이였다.

 

I gave my mother a letter saying thanks after hers birthday.

a letter saying 이므로 a letter(편지)가 saying하는 것이다. 

그래서 뜻은 → 나는 어머니 생신 후에 감사하다나는 편지를 드렸다.

편지가 말을 한 것처럼 쓴 것이다. '감사하다는 의미를 지닌 편지' 의 의미를 갖고 있다.

 

과거분사(p.p)

과거분사는 수식 받는 명사가 동작을 받거나 (수동적 의미), 동작이 이미 끝난 상태(완료)의 의미를 지니고 있다.

해석은 '~된' , '~해진' , '~한 (상태)'으로 해석된다. → 구매된, 깨끗해진, 가격 당한 으로 쓰여진다.

 

The slapped person hurt his face.

The slapped person은 뺨을 맞은 사람이다. ~한 상태를 나타내고 있다.

→ 뺨을 맞은 사람은 얼굴을 다쳤다.

 

The electronics purchased cannot be exchanged. 

The electronics purchased이 구매되어진 전자제품이다.

→ 구매되어진 전자제품은 교환될 수 없습니다.

 

I can sleep well in the cleaned bedroom

→ 깨끗하게 치워진 bedroom이다. 

→ 깨끗하게 치워진 침실에서 나는 잘 잘 수 있었다.

 


감정을 나타내는 동사는 현재분사와 과거분사 형태로 쓰이게 되면 명사를 꾸며주는 형용사 역할을 한다.

  • 현재 분사의 경우 '~한 감정을 느끼게 만드는' 이라는 의미로 쓰인다. (능동)
  • 과거 분사의 경우 '~한 감정을 느끼는' 이라고 쓰인다. (수동)

감정을 나타내는 동사는 다음과 같다.

 

excite 신나다.

amaze 놀라게 하다

interest 흥미를 불러 일으키다

disappoint 실망시키다.

frighten 겁먹게 만들다.

등이 있으며 현재분사와 과거분사로 만들어서 사용된다.

 

현재분사 과거분사
exciting 신나는 excited 신난
amazing 놀라게 하는 amazed 놀란
interesting 흥미를 불러일으키는 interested 흥미 있어 하는
satisfying 만족하게 하는 satisfied 만족한

Amazed father fallen onto the floor

→ 놀란 아버지가 바닥에 쓰러졌다.  [놀란 감정을 느끼는 아버지이다]

 

The magic show I saw today was an amazing show.

→ 오늘 본 마술쇼는 놀라운 쇼였다. [이 쇼가 우리를 놀라운 감정을 느끼게 만든다.]

+ Recent posts