본문 바로가기
Matlab

[프로젝트 1] 이미지 지도 - 2 (테이블과 셀형 배열)

by 두재 2019. 6. 30.

매트랩 첫번째 프로젝트의 두번째 글입니다!

 

이 프로젝트는 아이폰이나  스마트폰의 기본 앨범에서 지도에 사진을 표현해주는 것을 매트랩에서 만드는 것입니다. 프로젝트 설명에 관한 글은 첫번째 글을 참고해주시면 좋을 것 같습니다.

2019/06/29 - [Matlab] - [프로젝트 1] 이미지 지도 (like 스마트폰 앨범) - 1

 

[프로젝트 1] 이미지 지도 (like 스마트폰 앨범) - 1

매트랩에서 음성, 이미지 처리를 대강 해보았고 재밌는 것들이 없을까 싶어 재밌는 아이디어를 매트랩으로 구현해보자는 생각이 떠올랐습니다. 매트랩 프로젝트 첫번째입니다! 재밌는 아이디어 있으면 댓글 주세요..

honeyjamtech.tistory.com

 

첫번째 포스트에서 사진들을 불러오고 각 사진에 대한 위치 정보를 읽고, 도분초 단위의 위도와 경도를 degree 단위로 바꾸고, 지도 위의 한 점에 표시해보았습니다.

 

그러면 이번에 해야 할 것은

1. 여러 점들을 지도 위에 plot하기

2. 매트랩 지도 (geobubble) 가지고 놀기

3. (응용) 선을 그어보기 + α

 


1. 여러 점들을 지도 위에 plot하기

geobubble에서 위도와 경도를 통해 위치를 마킹할 수 있었는데, 여러 점을 표현하려면 여러 위도와 경도를 한 번에 집어넣으면 됩니다.

여러 위도와 경도를 table 형태로 집어넣으면 됩니다.

파이썬 Pandas에 '데이터프레임'이라는 개념이 존재한다면, 매트랩에는 '셀형 배열'과 '테이블'이 존재합니다.

 

데이터프레임과 '테이블'은 쉽게 생각하면 엑셀과 유사한데, 많은 데이터들을 쉽게 다룰 수 있도록 해줍니다.

파이썬은 그렇지 않지만 기존에 사용하고 있던 배열은 int형인지, string형인지를 잘 고려해야합니다. 프로그래밍 언어에서 중요한 '형'을 잘 따져가며 해야하죠. 또한, 배열의 경우 행과 열들을 없애거나 추가하거나, 중복된 행들을 없애는 등의 여러 작업들을 하기 위해서는 직접 코드를 짜가며 해야 합니다. 그러한 작업들을 미리 사용할 수 있도록 하였고, 이를 사용하려면 데이터프레임이나 테이블이라는 형태를 사용해야 하는 것이죠.

파이썬의 데이터프레임에 대해서는 나중에 파이썬을 다루게 되면 추가로 얘기해보도록 하고, 매트랩에서 사용하는 테이블에 대해 알아 보겠습니다.


가. 테이블(Table) of Matlab

테이블에 관한 정보가 별로 없던 것 같습니다. 테이블 변수는 말 그대로 표입니다. 그리고 파이썬 Pandas의 데이터프레임과 많이 유사합니다.

매트랩에서 테이블 예시

테이블을 만들면 위와 같은 표가 생깁니다.

형태를 우선 보자면,

1. 맨 윗줄에는 변수 이름(열 이름)이 있습니다.

2. 맨 왼쪽에는 행 이름이 있습니다.

3. 정수형(integer), 문자열(string), 소수점(double)형이 하나의 배열(표) 형태에 포함되어 있습니다.

 

테이블에 대해 더 알아보자면

1. 배열에서 사용하는 것과 같은 인덱싱(indexing)이 가능합니다. 물론 인덱싱에 행 이름과 열 이름은 포함되지 않습니다. 그런데 약간 특이한 점이라 하면, 저 위의 테이블에서 3번째 데이터의 이름(name)을 보고 싶다면 변수 이름을 열 인덱스에 사용해도 됩니다. 아래와 같이 말이죠.

total(3, 3)
total(3, 'name')

위 두 코드는 같은 결과를 반환합니다. 파이썬의 데이터프레임과 한 가지 유사한 점이죠.

2. size(total) 과 같은 함수를 통해 크기를 받을 수 있습니다. 배열처럼요. 이 크기를 계산할 때에도 행 이름과 변수 이름은 빼고 데이터의  크기만 반환합니다.

3. 행과 열 조작이 매우 간편합니다. 

newtotal = total(3:5, {'name', 'lat'})

위와 같은 코드를 통해 기존의 테이블에서 3번째부터 5번째 행 데이터 중에 'name'과 'lat' 변수만 포함하는 3*2 테이블로 자를 수 있습니다. 이 또한 파이썬의 데이터프레임과 유사한 점이죠. 

이외에도 여러 데이터 조작 기능이 있는데(중복 데이터 없애기, 정렬하기 등) 이 프로젝트에서는 사용하지 않습니다.

 


나 .셀형 배열(Cell Array) of Matlab

테이블과 유사한 형태로 셀형 배열이 있습니다.

셀형 배열 또한 배열 안에 여러 변수형이 포함될 수 있으며, 다른 숫자형 배열을 포함할 수 있습니다. 굉장히 넓은 의미의 배열입니다.

테이블과 다른 점은 테이블은 변수 이름, 행 이름을 추가로 정할 수 있으며 데이터를 다루는데 특화된 형태이고, 셀형 배열은 그렇지는 않습니다. 한 구조에 여러 변수형이 들어갈 수 있고, 셀형 배열 안에 다른 숫자형 배열 혹은 다른 셀이 포함될 수 있다는 점이 특이합니다.

셀형 배열의 예

위 사진에서 좌측은 우리가 위에서 만든 테이블과 같은 데이터를 가지는데 데이터 구조가 셀형 배열인 예시입니다. 테이블과의 다른 점은 행 이름과 변수 이름이 없다는 것과 중괄호 {} 와 대괄호 [] 를 빼면 배열로 볼 수 있다는 점입니다. 괄호의 형태가 신기하게 생겼죠.

오른쪽 사진은 셀형 배열에 어떠한 데이터가 들어갈 수 있는지에 관한 사진인데, 단순한 정수형(integer)값, 문자열(string) 뿐 아니라 double 형으로 이루어진 3차원 배열, 3*1 크기의 다른 셀형 배열이 셀형 배열 안에 포함될 수 있습니다.

 


다시 프로젝트로 돌아와서, geobubble 안에 위도와 경도를 하나씩 표현할 수도 있지만 여러 점을 표현할 때에는 테이블을 이용합니다.

그래서 테이블을 만들어야하는데, 테이블을 직접 만들지 않고 셀형 배열을 우선 만들고, 변수 이름을 만드는 형식으로 해보겠습니다.

아래와 같은 코드를 통해 만들 수 있습니다.

for i=1:length(files)
    img = imfinfo(files(i).name);
    GPS = img.GPSInfo;
    lat = GPS.GPSLatitude;
    lon = GPS.GPSLongitude;
    lat = dms2degrees(lat);
    lon = dms2degrees(lon);
    total{i,1} = i;
    total{i,2} = files(i).name;
    total{i,3} = lat;
    total{i,4} = lon;
end

total
total = cell2table(total, 'VariableNames', {'index','name','lat','lon'})

모든 파일에 대해 반복문을 돌리고, 셀형 배열의 첫번째는 인덱스, 두번째는 사진의 이름, 세번째와 네번째는 위도, 경도로 만들었습니다.

셀형 배열을 테이블로 바꾸는 것은 cell2table이라는 함수를 사용하고, 추가 속성 설정에서 'VariableNames'를 통해 변수 이름을 설정해 줄 수 있습니다. 이 변수 이름 또한 셀형 배열로 입력받습니다.

셀형 배열, 테이블형

위와 같은 코드를 통한 결과입니다. 셀형 배열이 생성되었고, 우측에서 테이블형으로 변환이 잘 이루어진 것을 확인할 수 있습니다.

cell2table의 속성 설정에서 'RowNames'를 지정하면 행 이름도 만들 수 있는데, 설정을 안하면 기본값은 1, 2, 3 ... 인 인덱스로 설정됩니다.


geobubble(total, 'lat', 'lon')
geobasemap landcover

테이블을 만들고, geobubble에 테이블과, 위도를 의미하는 변수 이름, 경도를 의미하는 변수 이름을 설정해준다면 여러 개의 점들이 표현됩니다.

geobasemap landcover는 지도의 색깔 테마를 지정해줍니다. 아래와 같은 테마가 존재합니다. 설정을 안해주면 단순한 흑백 지도로 설정됩니다.

저 코드를 실행한 결과는 아래와 같습니다.

여러 점 표시

7장의 사진은 신촌 연대에서 백양로 걸으면서 올라왔다 내려오면서 찍은 사진입니다. 너무 범위가 좁고 매트랩에 그 정도로 고화질 위성 사진이 있을 수가 없다는 사실을 간과했습니다. 지도를 축소한 사진이 우측 사진인데, 두 사진을 잘 보면 어느 정도 잘 나온 것 같습니다. 신촌의 위치도 나름? 맞고, 백양로의 방향도 맞습니다.

 


2. 내가 움직인 경로 그어보기

lat = table2array(total(1,3));
lon = table2array(total(1,4));

for i=1:length(files)-1
    lat = horzcat(lat,table2array(total(i+1,3)));
    lon = horzcat(lon,table2array(total(i+1,4)));
end
geoplot(lat, lon)
geobasemap landcover

코드는 위와 같습니다.

지도에 선을 그어주는 함수는 geoplot인데, 이는 geobubble과 굉장히 유사합니다.

두 개의 위도와 경도가 주어지면 이 사이를 이어주는데, 여러 개의 위도와 경도가 한 번에 주어지면 이 들을 이어줍니다.

따라서 전체 파일 길이보다 한 개 적은 횟수로 반복문을 실행하여 각각의 위도, 경도들을 전체 지점의 위도, 경도를 가지는 배열로 만들어서 나중에 geoplot(lat, lon)을 통하여 한 번에 사이의 점들을 이어줍니다.

결과는 아래와 같은데, 백양로를 올라갔다가, 내려오는 경로가 잘 표현된 것 같습니다.

 

 


첫 프로젝트가 끝났습니다.

첫번째 프로젝트에서는 스마트폰의 기본 앨범에 있는 위치 정보를 이용해서 사진들을 지도 위에 표시하는 기능을 매트랩으로 구현해보았습니다.