티스토리 뷰
QGIS 플러그인을 작성하여 현장에서 촬영된 사진의 EXIF 정보를 추출하고 엑셀 파일로 저장하고 화면에 출력하려면 다음 단계를 따르세요.
- QGIS 플러그인 관련 툴 설치
- 필요한 라이브러리를 설치합니다: exifread, openpyxl
- 사용자로부터 사진 폴더를 선택하게 합니다.
- 선택한 폴더의 사진들의 EXIF 정보를 추출합니다.
- 추출한 정보를 엑셀 파일로 저장합니다.
- QGIS 지도에 사진의 위치를 포인트 레이어로 출력합니다.
1. QGIS 플러그인 관련 TOOL 설치
QGIS프로그램 메뉴바에서 플러그인을 선택하고 플러그인 관리 및 설치...기능을 실행한다.
플러그인 설치 대화상자에서 Plugin Builder 3과 Plugin Reloader를 순서대로 설치한다.
정상적으로 설치가 되었다면 다음 그림처럼 플러그인 메뉴에 두 가지 플러그인이 설치된 것을 볼 수 있다.
플러그인 메뉴에서 Plugin Builder > Plugin Builder를 실행하면 다음과 같이 플러그인 생성 정보를 입력하는 대화상자가 나온다. 여기서 클래스 이름, 플러그인 이름, 플러그인 기능 설명, 모듈이름, 버전 번호, GIS 최소버전, 개발자 및 회사, 개발자 이메일 정보 등을 개발하고자하는 플러그인의 목적에 맞게 입력하면 된다.
입력을 마쳤으면 Next 버튼을 클릭한다.
플러그인에 대한 기능을 설명하는 대화상자에 기능에 대한 설명을 입력하고 Next 버튼을 클릭한다.
개발하는 플러그인의 형태와 게시된 위치를 지정하고 Next 버튼을 클릭한다.
다음 대화상자에서 모든 항목을 체크하고 Next 버튼을 클릭한다.
실험적 버전이라고 명시하고 Next 버튼을 클릭한다.
다음 대화상자에서 플러그인이 설치된 폴더를 지정하는데 폴더 경로는 다음 위치를 검색해서 지정한 다음 Generate 버튼을 클릭한다.
C:\Users\web1m\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins
최종적으로 설치가 완료되면 플러그인의 설치위치, 추후 설정할 내용 등을 보여주는 대화상자가 나온다. 내용을 본 후 확인 버튼을 클릭한다.
생성된 플러그인을 불러오기 위해서는 QGIS 프로그램을 다시 시작한 후 플러그인 메뉴에서 설치를 진행해야 한다.
플러그인 대화상자에서 ExtrarctGPSInfo를 검색하고 체크박스를 선택하여 설치한다.
설치된 플러그인 다음 그림처 툴바에서 확인할 수 있다.
클릭해서 실행하면 다음 그럼처럼 아무것도 개발하지 않은 상태의 대화상자가 나오면 정상적으로 설치된 것이다.
향후 이 빈 대화상자에 촬영된 사진에서 GPS 정보를 추출하는 기능을 추가할 예정이다.
import os
import exifread
from openpyxl import Workbook
from qgis.PyQt.QtWidgets import QFileDialog
from qgis.core import QgsVectorLayer, QgsFeature, QgsGeometry, QgsField, QgsFields, QgsProject
class ExifExtractor:
def __init__(self, iface):
self.iface = iface
def run(self):
# 1. 사용자로부터 사진 폴더를 선택하게 합니다.
folder = QFileDialog.getExistingDirectory(None, "Select Photo Folder")
if not folder:
return
# 2. 선택한 폴더의 사진들의 EXIF 정보를 추출합니다.
photos = []
for file in os.listdir(folder):
if file.lower().endswith(('.jpg', '.jpeg')):
with open(os.path.join(folder, file), 'rb') as f:
tags = exifread.process_file(f)
lat, lon = self._get_lat_lon(tags)
if lat and lon:
photos.append({'path': os.path.join(folder, file),
'latitude': lat,
'longitude': lon})
# 3. 추출한 정보를 엑셀 파일로 저장합니다.
wb = Workbook()
ws = wb.active
ws.append(['Path', 'Latitude', 'Longitude'])
for photo in photos:
ws.append([photo['path'], photo['latitude'], photo['longitude']])
wb.save(os.path.join(folder, "photo_exif_info.xlsx"))
# 4. QGIS 지도에 사진의 위치를 포인트 레이어로 출력합니다.
point_layer = QgsVectorLayer("Point?crs=EPSG:4326", "Photos", "memory")
point_layer.startEditing()
point_layer.addAttribute(QgsField("path", QVariant.String))
point_layer.addAttribute(QgsField("latitude", QVariant.Double))
point_layer.addAttribute(QgsField("longitude", QVariant.Double))
for photo in photos:
feature = QgsFeature()
feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(photo['longitude'], photo['latitude'])))
feature.setAttributes([photo['path'], photo['latitude'], photo['longitude']])
point_layer.addFeature(feature)
point_layer.commitChanges()
if point_layer.isValid():
QgsProject.instance().addMapLayer(point_layer)
else:
self.iface.messageBar().pushMessage("Error", "Failed to create photo point layer.", level=Qgis.Critical)
def _get_lat_lon(self, tags):
lat = None
lon = None
if "GPS GPSLatitude" in tags and "GPS GPSLatitudeRef" in tags and "GPS GPSLongitude" in tags and "GPS GPSLongitudeRef" in tags:
lat = self._convert_to_degrees(tags["GPS GPSLatitude"].values[0], tags["GPS GPSLatitudeRef"].values[0])
lon = self._convert_to_degrees(tags["GPS GPSLongitude"].values[0], tags["GPS GPSLongitudeRef"].values[0])
return lat, lon
def _convert_to_degrees(self, value, ref):
degrees = value[0].num / value[0].den
minutes = value[1].num / value[1].den
seconds = value[2].num / value[2].den
if ref in ['S', 'W']:
degrees = -degrees
minutes = -minutes
seconds = -seconds
return degrees + (minutes / 60.0) + (seconds / 3600.0)
plugin = ExifExtractor(iface)
plugin.run()
<참고>
QGIS 프로그램의 설정을 초기화 하고 싶을 때
아래 두가지 경로에 위치한 폴더를 제거하면 프로그램의 설정을 초기화할수있다.
%LocalAppData%\QGIS
'QGIS실습' 카테고리의 다른 글
QGIS에서 래스터 파일의 픽셀(GRID)을 폴리곤 파일로 변환하기 (0) | 2023.05.20 |
---|---|
사진에서 GPS 정보를 추출하는 QGIS 플러그인 코드- 2) 개발환경설정 (0) | 2023.03.29 |
QGIS를 이용한 TWI(Topographic Wetness Index) 제작하기 (0) | 2023.03.19 |
TWI(Topograhpic Wetness Index) 주제도 제작하기 (0) | 2023.03.18 |
래스터 이미지를 여러 장의 Tile 맵으로 분할하기 (0) | 2023.02.25 |