지난 시간에는 개선된 어셈블리어 코드를 이용한 부팅 가능한 이미지 파일 구현 방법과 병렬 처리 프로그래밍 openmp를 마무리 하고, 기술자에 대해서 조금 더 깊이 학습하여 주성분 분석과 얼굴 인식을 위한 고유 얼굴 검출 등 까지 과정들을 살펴보았습니다.
이번 시간에는 영상 위주로 학습을 진행하면서, 영상의 한 점에 대한 좌표와 특징 벡터로 이루어진 키포인트들 간에 매칭에 관한 전반들을 다루었습니다. 여기서 동일한 물체가 나오나 서로다른 영상에 존재하는 특징들을 매칭 시켜주기 위한 쌍을 찾고 어떠한 방식으로 최적의 쌍과 기하 정렬을 구하는지 살펴보았습니다.
우선 가장 처음으로 매칭에 대해서 학습하였습니다. 매칭이란 서로 다른 영상 간에 존재하는 특징점 쌍이 서로 동일한 것인지 확인하는 과정이라 할수 있는데 이를 위해 유사도나 거리를 측정하여 매칭한 것인지 찾게 됩니다. 대표적인 특징으로 에지와 지역특징, 영역 등이 있으나 주로 매칭시에는 지역 특징이 사용되며 서로 다른 영상에 존재하는 특징들 간에 거리를 계산하기 위한 방법으로 유클리디안 거리와 마할라 노비스 거리가 있었습니다.
유클리디안 거리는 두 벡터 사이 요소 간의 차에 대한 노름으로 정리 할수 있었습니다. 하지만 유클리디안 거리는 데이터 분포에 대한 요소를 고려하지 못해 올바르지 않은 특징을 대응쌍으로 판단할수 있었습니다. 이를 개선한 마할라 노비스 거리는 유클리디안 거리 계산 중간에 데이터의 공분산 행렬을 추가하여 데이터 샘플 분포를 반영시킨 것으로 더 정확한 거리라고 할수 있었습니다. 추가적으로 매칭 성능을 판단하는 ROC 곡선에 대해서도 간단히 살펴보고 다음으로 kd 트리에 대해서 살펴보았습니다.
컴퓨터 비전에서 kd트리는 최근접 이웃인 특징을 빠르게 찾기위한 자료구조로 활용되었습니다. 한 영상에서 루트 노드로부터 분기해 나가면서 kd 트리를 만든다면, 다른 영상에서 구한 특징 즉 새로운 입력 특징이 주어질때 kd 트리를 이용하여 고속으로 최근접 이웃인 특징을 찾을수 있었습니다.
하지만 더 자세히 살펴보면 kd 트리를 이용해 최근접 이웃을 구하는 과정에서 지역 특징을 사용하다보면 기하 정렬 조건이 고려되지 않아 잘못된 형태의 매칭을 만들수 있습니다. 이러한 기하 정렬을 고려한 대표적인 알고리즘으로 최소 제곱법과 RANSAC 알고리즘을 사용하여 매칭을 수행하는 경우가 있었습니다. 최소 제곱법은 두 영상에서 구한 특징들 간에 오차를 최소한으로 하는 기하 변환 행렬을 구할수 있었으며, RANSAC에서는 거짓 긍정 오류가 존재하는 영상에 대해서 잘못된 특징쌍 즉, 노이즈를 제거하여 실제와 가까운 모델을 구할수 있었습니다.
이번 시간에는 매칭에 대한 거리 개념과 자료 구조, 최근접 이웃, 그리고 이를 기하 정렬을 고려하여 매칭을 하기 위한 알고리즘들 까지 전반에 대해서 살펴보았습니다. 사실 수식도 정리하고 더 깊이 살펴볼수 있는 내용들이기는 하나 깊이 있는 학습은 다음에 진행하고, 우선은 컴퓨터 비전 전체적인 범위를 살펴보는게 우선인 만큼 매칭에 관련된 개념과 알고리즘, 동작 과정이 어떻게 수행되구나 정도 까지만 학습하였습니다. 다음 시간에는 본격적으로 컴퓨터 비전에서의 인공지능, 기계학습 알고리즘과 활요에 대해서 학습해가고자 합니다.
지난 시간에는 대표적인 영상 특징 SIFT와 SURF의 특징과 영상 분할을 위한 다양한 방법, 특징 기술자 등 영상 관련하여 살펴보고, 병렬 처리 프로그래밍인 openmp에대한 개념과 간단한 실습, 그리고 간단한 윈도우 어플리케이션 해킹 실습을 진행하였습니다. 이번 시간에는 지난번에 기계어로 부팅 가능 이미지를 만들었던 것에서 개선하여 어셈블리어를 이용한 부팅이미지를 구현해보고, 어제 학습한 내용에 이어서 openmp의 기초적인 내용 학습을 마무리 하고자 합니다. 또 나머지로 특징 기술자 다음으로 영역 기술자와 주성분 분석, 그리고 이를 이용한 고유 얼굴 검출 및 얼굴 인식 과정에 대해 학습을 진행하고자 합니다.
어셈블리어를 이용한 부팅 이미지 구현 과정에서 일반 nasm 어셈블러 대신 nska라고 하는 어셈블러를 이용하여 이전에 기계어로 직접구현했던것 보다 간단하게 만들었습니다. 처음에는 Date Byte인 DB 명령어를 이용하여 16비트 값 하나하나 작성했던것 처럼 부팅 관련 이진값들을 입력해주었습니다. 중간에 공백 칸들은 공백으로 예약된 REVB Reserved Byte 명령어를 이용하여 공백이 필요한 부분들은 간단하게 공백을 삽입하여 기계어와 동일한 형태로 구현하였으며, QEMU 에뮬레이터에서 정상적으로 동작하는 모습을 확인하였습니다.
하지만 이러한 방식은 기계어로 코딩한 것과 별 차이가 없어 문자열을 사용하거나 다른 어셈블리 명령어를 활용하여 개선된 어셈블리 코드를 작성하였습니다. 여기서 추가로 사용한 명령어로 DW Data Word 데이터 워드를 저장하는 DW 명령어, 데이터 더블 워드 크기로 저장하는 DD등이 있었으며, 이전의 어셈블리 코드가 16진수만을 입력하였던것과 비교하면 문자열과 여러 명령어를 통해 훨씬 간결해진 코드를 구현할수 있었으며, QEMU와 Bochs 상에서 정상적으로 부팅이 되고 문자열이 출력되는 모습을 확인하였습니다.
또한 어제에 이어서 openmp 학습을 마무리 하였습니다. 오늘의 경우 병렬 프로그래밍에서 동기화를 다루는 방법과 중첩 스레드, 작업 분할 지시어, 스케줄링과 테스크 등의 개념들에 대해서 전반적으로 살펴보고 실습을 진행하였습니다. openmp는 스레드 기반 병렬프로그래밍으로 하나의 프로세스 내부에서 동작하다보니 스레드 안에 스레드를 생성하는 경우 중첩 스레드로 처리하는 방법에 대해 이해가 필요하였습니다. 그래서 중첩 스레드가 어떻게 생성이 되고 데이터들의 범위가 정해지는지, 그리고 병렬 처리할 작업들을 스레드마다 균일하게 배분할것인지 동적으로 배분할것인지에 대한 작업 분할 지시어, 그리고 작업 단위인 테스크를 어떻게 효율적으로 처리할지에 대한 스케줄링 기법과 여러개의 스레드가 같은 데이터를 동시에 다루는걸 막기위한 동기화 로직 등 지난 시간에는 간단한 연산과 사용법, 예제들을 살펴보았다면 오늘은 조금더 고급적인 활용 방법들을 살펴볼수 있는 시간을 가졌습니다.
openmp 수업을 마무리하고나서 영상 처리 일부분을 마저 진행하였습니다. 우선 지난 시간 SIFT 특징 기술자에 대해 살펴보면서 특징 기술자가 무엇인지 그리고 어떤 구성요소를 가지고 있는지, 계산하는 과정을 다루었다면 이번시간에는 개선된 특징 기술자와 영역을 다루는 기술자, 주성분 분석 방법과 이를 이용한 얼굴 인식에 대해 학습을 할 수 있었습니다.
우선 개선된 특징 기술자로 PCA-SIFT와 GLOH를 살펴보았습니다. SIFT의 경우 4 x 4 x 8 = 128바이트 크기를 차지하는 만큼 일반 영상에는 특징들이 많이 존재하므로 컴퓨터의 성능이 크게 저하될수 있습니다. 그래서 이런 벡터의 정보를 손실을 줄이면서 차원수를 줄이는 기술인 PCA를 적용한 SIFT 즉, PCA-SIFT에 대해서 살펴보고, 이와 별개로 SIFT 기술자가 사각 마스크에서 적용되었다면, 원형 마스크를 사용한 GLOH 기술자에 대해서 간단히 학습하였습니다.
다음으로 영역 기술자에 대해서 살펴보았습니다. 특징 기술자가 하나의 특징점, 키포인트에 대한 추가적인 정보였다면 영역 기술자는 공간에 대한 정보를 나타낸다고 할수 있습니다. 영역 기술자는 전역 기술자와 지역 기술자가 존재한다고 할수 있는데, 전역 기술자인 경우 대표적으로 에지가 많이 활용된다고 합니다. 하지만 전역 기술자로서는 영상의 일부분 변화를 처리할수 없기 때문에 지역 기술자를 위주로 학습하였습니다.
지역 기술자에서는 아까 특징 기술자에서 상당히 계산량이 많았던 관계로 지역 이진 패턴 방법들이 주로 사용된다고 합니다. 대표적인 LBP Local Binary Pattern은 특징점 주위에 마스크를 씌워 이에 픽셀들의 대응쌍을 찾는데 이 픽셀 쌍은 이진값을 가지는게 특징이 됩니다. 이를 통해서 해당 영역에 대한 텍스처 정보를 보존할수 있어, 얼굴 인식 문제에 적용하는 경우 얼굴을 여러가지 셀로 분할하고 각 셀에 대한 LBP 히스토그램을 만듦으로서 얼굴 인식을 위한 모델을 만든다고도 합니다.
마지막으로 주성분 분석과 고유 얼굴, 즉 얼굴 인식에 대해서 살펴보면서 마무리 하였습니다. 주성분 분석은 큰 차원의 벡터를 최대한 정보 손실을 줄이면서 저차원의 벡터로 만드는 기술이라 할수 있습니다. 여기서 고유 얼굴은 입력 얼굴과 평균 얼굴의 차이 영상이라 할수 있습니다. 이 고유 얼굴에 주성분 분석을 적용하여 저차원의 고유 벡터를 구하게 되고 이 고유벡터와의 가장 거리가 가까운 고유 얼굴을 찾음으로서 누구의 얼굴인지 판단하는 기술임을 정리하였습니다.
지난 시간에는 영상에 존재하는 경계점인 에지와 선분 검출 알고리즘, 그리고 지역 특징에 대한 개요에 대한 내용을 살펴보면서 비전 분야 학습을 진행하였고, 이외에 해킹 관련 기본 개념들과 바이너리 에디터로 기계어 코딩을 직접하여 부팅 가능한 이미지를 구현해보았습니다. 이번 시간에는 대표적인 지역 특징 검출 알고리즘인 SIFT와 SURF에 대해서 살펴보고, 영역 분할 알고리즘 그리고 이러한 특징에 대한 추가 정보인 특징 기술자가 무엇인지 살펴보았습니다. 또 병렬 프로그래밍 플랫폼인 openmp에 대한 개요적인 내용과 사용법을 학습하고, 키보드 후킹과 이미지 파일을 해킹하는 윈도우 어플리케이션 해킹 예제들을 통한 학습을 진행하였습니다.
우선 대표적인 지역 특징 검출 알고리즘인 SIFT와 SURF에 대해서 학습하였습니다. 우선 SIFT는 영상의 크기에 불변하는 지역 특징 알고리즘이라 할수 있는데, 입력 영상이 주어지면 이를 다양한 스캐일로 만들고, 여러 분포에 대한 가우시안 영상을 차분한 차분 영상을 획득합니다. 다중 스케일 차분 영상들에서 구한 특징들이 SIFT 키포인트가 되었습니다. 하지만 SIFT 알고리즘에서는 여러개의 영상에 대해 가우시안 마스크를 적용하고 차분 영상을 얻기까지에 대한 과정은 상당히 많은 계산량을 요구하여 시간이 오래걸리는 단점이 있었습니다. 이러한 문제를 극복한 SURF 알고리즘은 가우시안 필터를 박스 필터로 근사화하여 적분 영상을 이용해 박스필터들을 적용하는 방법을 사용하여, 기존의 SIFT 검출 알고리즘보다 훨씬 빠른 시간에 크기에 불변한 특징점들을 검출할수 있었습니다.
SIFT와 SURF 지역 특징 검출 알고리즘 다음으로 이미지의 영역을 분할하는 방법에 대해서 살펴보았습니다. 가장 간단한 것으로 임계치를 이용한 이진화, 색상 영역을 이용한 분할, 최소 신장 트리나 정규화 영상을 사용한 그래프 기반 방법 그리고 민시프트로 대표되는 클러스터링 알고리즘 기반 영역 분할 방법들이 존재하였습니다. 그래프 기반 방법 중에 최소 신장 트리 방법에서는 영상을 그래프의 형태로 구현하고, 이 그래프에 대한 최소 신장 트리를 만듦으로서 영상 영역들을 구분하는 방법이었습니다. 정규화 절단 방법의 경우 입력 영상을 유사도 그래프와 인접 행렬로 표현하고 연결 요소들을 분할되도록 계산하는 과정을반복하여 비슷한 영역들을 분할하는 방법이었습니다.
이 외에 추가적인 클러스터링 기반 영역 분할 방법들도 살펴보았습니다. 일단 클러스터링에 앞서 샘플들과 이 샘플들을 나타내는 확률 밀도 함수 그리고 그 함수의 봉우리인 모드의 개념을 보고, 클러스터링 문제를 다루기 시작하였습니다. 클러스터링 알고리즘 중 가장 대표적인 알고리즘이 kmeans 부터, 물체 추적에 자주 사용되는 민시프트, 그리고 DBSCAN까지 각 클러스터링 알고리즘의 특성과 장단점을 살펴보고, 민시프트 알고리즘이 물체 추적과 영상 분할에 어떻게 사용되는지 이해하는데 도움되었습니다.
영상처리의 마지막으로 특징 기술자에 대해서 학습을 진행하였습니다. 기술자란 지역 특징이 제공하지 못한 특징에 관한 추가적인 정보로 지역 특징이 해당 점의 위치와 스케일 정보만 제공한다면 기술자는 방향과 특징 벡터를 제공한다고 할수 있습니다. 이전에 살펴본 SIFT, SURF 특징은 스케일에 불변하는 특징이나 회전 불변에 필요한 정보들을 가지고 있지 않습니다. 그런 문제를 개선하기 위해서 특징 기술자가 필요하게 됩니다. 특징 기술자는 키포인트를 중심으로 커널을 씌워 윈도우 내부에 있는 픽셀들의 그라디언트 영상을 만들고, 이를 8단계로 양자화하여 그라디언트 방향 히스토그램을 만들어 주요방향을 찾습니다. 이 그라디언트 방향 히스토그램이 기술자 특징 벡터가 됩니다. 그래서 SIFT 기술자를 추출한다는 것은 기존의 키포인트, 특징점이 주어지면 이 키포인트에 주요 방향과 특징 벡터가 추가된 키포인트를 기술자라고 할수 있겠습니다.
오늘 영상 학습 하는 동안 영상 특징과 기술자, 분할 기술에 대해서 살펴보고, 나머지 시간에는 병렬 프로그래밍 플랫폼인 openmp와 윈도우 해킹에 대해서 학습을 했습니다. 이전에 openmp는 opencv를 빌드하거나 다른 오픈소스를 빌드하면서 종종 본 이름이고, 병렬프로그래밍을 수행한다는것은 알고 있었으나 이게 어떻게 한다는것인지 잘 몰랐습니다. 우연히 openmp 수업에 참여할수 있는 기회를 얻게 되어 수업에 참관하면서 openmp가 무엇인지 병렬프로그래밍을 어떻게 하고, 성능 개선이 이루어지는지 등에 대해 배울수 있었습니다.
마지막으로 윈도우 해킹과 관련된 내용들을 학습하였습니다. 32비트 윈도우에서는 자원을 제어하기 위한 WIN32API를 제공하고 있었습니다. 이 API와 제공하는 DLL을 통해 메시지를 후킹을 해보았으며, 별개로 이미지 파일을 임의로 수정하여 자바스크립트를 삽입하는 실습을 진행하였습니다. 먼저 키보드 후킹 예제를 연습해 보았습니다. kernel32.dll로부터 후킹 함수를 가져와 키로거 클래스를 정의하여 키 입력들이 오면 출력하고 ctrl을 누르면 종료되도록 구현하였습니다. 이미지 해킹 과정으로 기존의 비트맵 이미지를 파일 입출력 함수로 읽어들여 데이터 부분들을 주석처리하고 뒤에 알람을 띄우는 js 코드를 추가하도록 수정하였습니다. 이 수정된 비트맵 파일을 간단한 html에서 로드하면 이미지 파일 내에 존재하는 js코드가 실행되는 모습을 확인하였고, 악의적인 코드를 입력한다면 상당히 위험할수도 있을것 같아보였습니다.
이번시간에는 특징점, 영상분할, 기술자 등 비전 분야 내용들과 openmp의 기본사용법 그리고 간단한 윈도우 어플리케이션 해킹 실습을 해보았습니다. 내일은 openmp 나머지 내용을 학습하고, 이전에 기계어로 부팅 이미지를 만들었던것을 개선하여 어셈블리어로 구현하기, 영역 기술자, 주성분 분석 등 영상 파트 내용들을 학습할 예정입니다.
지난 시간에는 컴퓨터 비전에 관하여 개요 적인 내용과 다양한 연산에 대해서 살펴보았습니다. 오늘은 이러한 기본 연산을 이용하여 영상 내부에 존재하는 에지와 선분 검출 방법, 지역 특징 등에 대해서 간단히 살펴보고, 이와 별개로 컴퓨터 해킹과 관련된 일부 내용과 바이너리 에디터를 이용한 부팅 가능 이미지 만드는 과정에 대해서 학습을 진행하였습니다.
우선 지난번에 모폴로지 연산까지 학습한 데에 이어서 오늘은 에지 검출부터 시작하였습니다. 에지란 영상의 기울기가 급격히 변하는 부분으로 영상에 존재하는 모서리, 선과 같은 요소들이라 할수 있으며 영상의 미분을 통해 구할수 있습니다. 에지를 구하는데 있어 x와 y방향에 대한 기울기 영상, 그라디언트 벡터를 만들게 됩니다. 여기서 이러한 기울기 영상에 마스크를 적용하기도 하는데 로버츠 연산자, 프레윗 연산자, 그리고 가장 유명한 소벨 연산자가 존재합니다. 이러한 연산자와 더불어 가장 대중적으로 사용하는 에지 검출 방법로 캐니 에지가 있으며, 이전의 에지 연산자들이 영상 미분 마스크였다면 캐니 에지는 에지 영상을 검출하는대 최적화 방법을 사용하는것이 차이점이라 할수 있겠습니다. 이러한 다양한 에지들과 특성에 대해서 간단히 살펴보았습니다.
다음으로는 이러한 에지를 이용한 선분 검출 알고리즘에 대해서 살펴보았습니다. 에지를 그대로 선분으로 사용할수 있지 않을까 생각되기도 하였으나 에지는 잡음의 영향을 크게 받으며, 에지가 경계 요소를 나타낸다 하더라도 중간에 끊어지는 등의 문제로 에지 자체를 선분으로 사용하기에는 어렵습니다. 그래서 이러한 에지 요소들을 이용해 선을 검출하는 대표적인 방법인 허프 변환과 ransac에 대해서 알아보았습니다. 허프 변환은 에지 영상에 존재하는 에지들을 극좌표계 상으로 표현하여 극좌표계상 에지들의 교점을 원래 y-x 평면에서의 선분 요소로 사용하는 방법이며, 번호판 검출이나 다양한 알고리즘에서 사용되고 있습니다. ransac의 경우 샘플 데이터로부터 노이즈의 영향을 제거한 가장 근사화된 모델을 구하는 알고리즘으로 아웃라이어가 존재하더라도 실제에 가까운 모델에 구하는 과정을 살펴보았습니다.
영상처리중 가장 중요한 분야중 하나인 지역 특징에 대해서도 학습하였습니다. 지역 특징은 영상 내에 존재하는 물체간 매칭에 사용될 점이라고 할수 있으며, 영상의 크기인 스케일과 위치, 방향 특징 벡터 등으로 구성되어 있습니다. 지역 특징은 다른 특징들과 구분가능하며 다른 변형된 영상에서도 검출가능하며, 가려진 상황에서도 대처할수 있어야 하는 성질이 필요합니다. 이러한 지역 특징을 구하는 모라벡, 헤리스 코너 등의 알고리즘을 간단히 살펴보고 이러한 연산 과정에 필요한 그라디언트, 자코비안, 헤시안, 라플라시안 등에 대해서 학습을 진행하였습니다.
컴퓨터 비전 분야의 학습은 여기까지 마무리하고 다음으로는 해킹 관련 분야에 대한 학습을 시작하였습니다. 컴퓨터를 다루면서 컴퓨터 구조에 대해서 간단하게는 이제 알게 되었으나 컴퓨터의 통신 방식이나 내부 동작과정에 있어서 아직 막연함이 컷습니다. 파일을 만져볼일이 없으니 파일의 구조가 정확하게 어떤지, 패킷을 다뤄보지 않으니 패킷이 어떤 정보로 실제로 이루어져있고 저에게는 막연한 영역이라 추루 임베디드 개발 등에 있어서 해킹 측면에서의 학습이 많은 도움이 될것 같아 이 분야에 대해서도 학습을 시작하였습니다.
우선 해킹에 대해 다루면서 가장 먼저 해커와 크래커의 차이, 해커가 하는일, 그리고 해킹에 어떤것들이 있는지 살펴보았습니다. 저는 컴퓨터 소프트웨어에 웹 어플리케이션, 모바일, 임베디드 정도로만 분류할수 있었지 그 이상에 대해서는 잘 모르고 있었습니다. 컴퓨터 소프트웨어를 이와 유사한 관점에서 해킹의 종류들을 분류하였으며 각 분야의 해킹에 어떤 방식으로 취약점을 찾아 공격을 수행하는지 이전에 얼핏 듣기만 했던 공격 방식들에 대해서 조금 명확하게 파악할수 있었습니다. 그리고 내일부터 해킹에 대해서 제대로 살펴보기에 앞서 관련된 용어들을 정리하였습니다. 컴퓨터 구조부터 프로세스와 메모리, 프로토콜 등 개념과 구성들을 다시 반복하면서 어느 부분에 집중을 해야할지 이해하는데 많은 도움이 되었습니다.
마지막으로 운영체제 개발 관련된 학습의 일환으로 바이너리 에디터로 부팅가능한 이미지 파일을 생성하였습니다. 해킹 공부를 시작한것과 비슷한 취지로 저는 바이너리와 실제 프로그래밍 영역에 대해서 아주 깊은 이해도를 가지고 있지는 않았습니다. 그나마 결과물을 만들었던 GUI나 웹 어플리케이션의 경우에도 예제 코드를 제가 원하는 방향대로 수정하고 기능을 추가시켜서 만들었지 소프트웨어 개발에서 어떠한 철학이나 확고한 생각을 가지고 구현한 것은 아니라 예제를 수정하는것 이상에 대한 개발 지식이 전무하다 싶었습니다. 그런 목표로 운영체제 개발하는 좋은 자료를 찾아 학습을 시작하였으며, 가장 기본적인 단계로 이전에 가끔 보던 핵스 덤프를 조작하는 바이너리 에디터로 어떻게 동작되는지는 잘 모르겠지만 순수한 기계어로 hello world를 출력하는 간단한 부팅 이미지를 만들어 가상화 머신 QEMU와 bochs 상에서 돌려보는 실습을 진행하였습니다. 기계어 부터 시작하여 어셈블리어, 실제 운영체제 기능을 하나하나씩 구현해나가다보면 운영체제에 대한 전반적인 이해도 뿐만 아니라 구조체 정의 방법과 컴퓨터 소프트웨어 설계 등 좋은 개발자가 되는데 한번 거쳐볼만한 과정인것 같았습니다.