본문 바로가기
Matlab

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

by 두재 2019. 6. 29.

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

재밌는 아이디어 있으면 댓글 주세요!!! 열심히 찾아보고 만들어보고 공유해보겠습니다!

이번 프로젝트에서는  아이폰이나 스마트폰의 기본 앨범에서 지도에 사진을 표현해주는 것을 매트랩으로 만들어보려고 합니다.

아이폰 앨범에서 'Places'를 보면 아래와 같이 지도와, 사진이 찍힌 위치와 사진들을 모아 보여줍니다. 잘 만들었죠. 이걸 매트랩에서 구현해봅시다.

아이폰 기본앱에서 지도와 사진 표시


이걸 하려면 먼저 뭘 해야할지 생각을 해봅시다.

1. 사진(들)을 불러오고

2. 사진(들)에서 위치 정보를 읽고

3. 위치 정보를 통해 지도에 표시를 해야합니다.

4. 지도에서 선을 이어주거나 정리하는 건 뭐 나중에 추가로 더 하면 되는 거니까

1, 2, 3 번이 제일 핵심적이고 필요한 부분이죠.

 


1. 사진들 불러오기

사진 들이 한 폴더에 있다고 하고 폴더 안에 있는 모든 파일을 읽어오는게 매트랩에 있어요.

dir 인데,

이 함수는 디렉토리(directory)에서 나온 함수로 폴더들과 그 트리 구조들과 관련된 함수예요. 이 함수로 할 수 있는 일에는

현재 매트랩 작업공간(폴더)에 있는 모든 파일 나열

어떠한 특정 폴더 내에 있는 .jpg 파일을 찾기

그 사진이 언제 수정되었고, 크기가 얼마인지 찾기

등을 할 수 있어요.


아래의 코드와 그 결과를 한 번 보세요.

loc = '/Users/Username/Google Drive File Stream/내 드라이브/img'
files = dir(loc)
length(files)
files(3).name

결과

우선 사진들이 담겨있는 폴더들의 경로를 loc 라는 변수에 string으로 집어넣었습니다.

files = dir(loc)를 통해 files라는 변수에 loc라는 폴더 경로 안에 있는 모든 파일들이 담겨있습니다.

결과에서 보면 '다음 필드를 포함한 7*1 struct 배열'이라고 나오죠. C언어에서도 나오는데 구조체(struct)는 변수형인데, 다른 변수형들을 한번에 가지고 있는 변수형이예요. 예를 들면 어떤 구조체 변수 안에는 문자열 하나와 정수형 하나가 포함되어 있을 수 있는 것이죠. 저기서 name, folder, date 등은 문자열(string)인데, bytes는 정수형(integer)기 때문이죠. 저 아래 6개의 필드가 포함되어 있는 구조체가 7개 있다는 것이죠. 마찬가지로 length(files)를 하면 저 구조체들의 개수인 7개가 나와요.

지금 files는 struct 배열이예요. 배열이니까 인덱싱이 가능해요. files(1), files(2) ... files(7)을 하면 각각의 구조체가 나오겠죠. 물론 이 구조체는 하나하나의 사진(파일)을 의미하는 거죠.

그리고 구조체 내부의 필드의 접근은 점(.)을 사용해요. files.name 이나 files.folder 이런 식으로요. 

배열의 관점, 구조체의 관점 두 개를 합치면 files(3).name 이라는 문법을 사용할 수 있어요.

이는 3번째 파일(사진)의 이름을 알려줘 라고 하는 거겠죠.


dir 의 사용법을 알았으니, 나중에 폴더 안에 몇 개의 사진이 있는지 몰라도 모든 사진에 대해 반복문을 만들어 작업할 수 있을거예요. 폴더를 읽고, .jpg 혹은 .png 와 같은 이미지 파일을 읽고, length를 통해 전체 개수를 찾아 반복문을 만들면 되겠죠.

2번으로 넘어갑시다.


2. 사진에서 위치 정보 알아오기

예전 포스트 중에 이미지 부분에서 이미지와 관련된 여러 함수를 알아봤는데, 

imfinfo 라는 함수가 있습니다.

이미지의 정보를 불러오는데, 아래 코드를 한 번 보시죠.

img = imfinfo(files(3).name);
GPS = img.GPSInfo;
lat = GPS.GPSLatitude

실행 결과

코드를 보시면 우선 imfinfo 안에 1번에서 우리가 찾은 이미지(3번째 사진)을 넣어 정보를 불러오라고 했습니다.

info 또한 위에서 말한것처럼 여러 데이터를 포함한 구조체로 이루어져 있고, 그 안에 GPSInfo를 통해 GPS에 관한 정보를 불러왔습니다. GPS 정보 또한 여러 필드를 포함한 구조체인데

구조체는 다른 여러 변수형을 포함한다고 했는데, 구조체가 구조체를 가질 수도 있습니다.

GPS 정보 안에서 Latitude와 Longitude가 우리가 찾는 정보겠죠.

번외) 이미지 정보에 매우 많은 정보가 있는데, 그 중 CodingMethod 가 'Huffman'으로 되어 있네요. 허프만 코딩에 대해서 한 번 설명을 드려보도록 하겠습니다.

이제 위도, 경도에 다시 집중해서 저 Latitude와 Longitude가 매트랩에서 어떻게 나와있는지 보겠습니다.

lat = [37.0000 33.0000 38.3700]이라는 3개의 소수점 3개로 이루어져 있습니다. 이는 도 분 초 를 각각 의미합니다. 

열심히 쳐다본 결과 매트랩에서 이 위도 경도를 불러올 때 완벽한 정보를 가져오지는 않습니다. 물론 GPS자체도 에러가 있어 완벽한 것이 아닌데, 사진에 저장되어 있는 실제 위도 경도와 아주아주 약간 다릅니다. 아래 두 사진을 보시죠. 왼쪽은 매트랩에서 위도와 경도를 불러온 것이고, 우측은 맥OS에서 우측 클릭, 정보 가져오기 를 통해 살펴본 상세 정보입니다.

매트랩(좌), 실제 정보(우)

도 분 초, 그 중 초에서 소수점 아래 3째 자리가 없어진다는 것을 경도를 통해 확인할 수 있습니다. 하지만 뭐 초에서 소수점 아래 2째 자리까지만으로 해도 굉장히 디테일한 정보니 진행해봅시다.

이제 위도와 경도를 알아냈으니 지도에 표시해야합니다.


3. 지도에 표시하기

위도와 경도를 알 때 지도에 마킹하는 것은 geobubble이라는 함수를 사용합니다. 이 함수는 저도 찾아보면서 알았는데,

지도 위에 데이터를 거품(원형)으로 표현합니다.

이 거품의 크기를 어떠한 데이터에 비례하게 표현할 수 도 있는데, 우선은 위도와 경도를 이용해 단순히 지도에 그려보겠습니다.

지도에 표시하기에 앞서, geobubble에 들어가는 위도와 경도는 decimal degree로 입력받는데, 현재 도 분 초로 표현되어있습니다. 다시말해 XX.XXXXX ° 가 되어야 하는데 현재는 XX °  XX'  XX''라는 도, 분, 초 형태로 표현이 되어있다는 것이죠.

도분초를 도 로 변환해주는 함수도 매트랩에 존재합니다. 

dms2degrees 라는 함수인데, 매트랩에는 이러한 뭐뭐2뭐뭐 라는 함수가 많습니다. 변환해주는 함수죠. 그 중 하나입니다.

이 함수를 사용하려면 Mapping Toolbox 4.7 이 필요합니다. 매트랩에는 파이썬과 같이 매우 다양한 종류의 추가 패키지들이 존재합니다. 파이썬에서는 패키지라고 부르는데, 매트랩에서는 애드온(Add-on)이라고 부르고 애드온 탐색기를 통해 컴퓨터에 설치되어 있는 추가 기능들을 관리할 수 있습니다. 물론 애드온 탐색기를 통해 새로운 추가 애드온을 설치할 수도 있습니다.

추가 기능 설치 과정

이 추가 패키지가 설치되어 있지 않은 상태에서 아래 코드를 실행시키시면 빨간 줄로 dms2degrees는 Mapping Toolbox 4.7이 필요하다고 말할거예요. 저 패키지 이름이 아마 밑줄 쳐 있을텐데 그걸 클릭하시면 바로 저 추가 패키지를 설치할 수 있는 위와 같은 창이 뜹니다. 설치를 누르시고 약관에 동의하시고 하다보면 설치가 완료될 것이고, 이후 사용할 수 있습니다.

이를 통해 geobubble에 대입할 수 있는 degree 형태의 위도 경도로 바꿀 수 있습니다. 아래 코드처럼 말이죠.

lat = GPS.GPSLatitude
lon = GPS.GPSLongitude
lat = dms2degrees(lat);
lon = dms2degrees(lon);

실행 결과

위 실행 결과를 보시면 분과 초 부분이 약간은 달라진 것을 확인 할 수 있습니다.

이후 geobubble에 대입하면 됩니다.

geobubble(lat,lon)
geolimits([36.77 38.34],[125.67 128.20])

코드는 위와 같습니다. 

위도와 경도로 geobubble을 통해 plot하고, 아래 geolimit은 예전 plot에서 x축, y축의 범위를 지정해준 것과 같습니다. 아래 두 사진을 보시면 geolimit이 있는 것과 없는 것의 차이를 알 수 있을 것입니다.

그냥 지도 (좌), geolimit을 통해 만든 지도 (우)

geobubble을 통해 흑백의 단순한 지도가 생성되었고, 입력한 위도와 경도를 중심으로 파란 원이 생긴 것을 볼 수 있습니다.

 


예상 외로 포스트가 길어져 다음 포스트에서 마무리짓도록 하겠습니다.

사진 들을 불러오고, 하나의 사진에서 위치 정보를 불러오고, 그 위치 정보를 지도에 표현하는 것을 해보았습니다.

다음 포스트에서 많은 사진들 각각에서 위치 정보를 불러오고, 이'들'을 지도에 한 번에 표시하고, 응용해보도록 하겠습니다.


응용이라 하면, 사진들이 밀집한 곳의 원의 크기를 키우거나, 하루의 사진들을 시간 순으로 지도에서 선을 그어보도록 하겠습니다.

다음 포스트 : 019/06/30 - [Matlab] - [프로젝트 1] 이미지 지도 - 2 (테이블과 셀형 배열)