위치 기반 서비스 개발 메모

2024. 4. 10. 22:18Toy Project

이전 직장에서 로드뷰 데이터, 좌표기반 데이터로 개발을 했던 경험을 살려 개발을 진행하고 있다. 

먼저, 규모를 작게 설정하여 국내. 그 중에서도 서울을 기반으로 소규모로 제작을 하려고 한다.

이후 국내 전체, 해외까지도 확장하여 개발할 예정이다. 

 

  • 지도에 표시할 사진들을 콜라주하여 표시하는 방법에 대해: 이 부분에 대한 고민이 많았다. 일반적으로 클릭 혹은 터치를 통해서 이미지를 팝업해서 보거나, 새로운 창에서 이미지를 확인하는 방식이 보편적이라고 생각이 된다.
    하지만, 내가 개발할 앱에는 특징적으로 지도 자체에 사진들을 콜라주로 표현하는 방식을 사용하고자 한다. 
  •  기술적인 문제: 콜라주하는 방식에 대해서는 기본적으로 pillow의 Image 클래스를 이용하면 쉽게 구현할 수 있다. 
from PIL import Image
import os
import concurrent.futures
import math

def calculate_collage_resolution(num_images, thumb_width=400, thumb_height=300):
    """
    이미지 개수에 따라 콜라주의 해상도 비율을 계산
    
    :param num_images: 콜라주에 포함될 이미지의 총 개수
    :param thumb_width: 이미지의 너비
    :param thumb_height: 이미지의 높이
    :return: (width, height) 형태의 튜플로 콜라주의 권장 해상도 비율
    """
    rows = int(math.sqrt(num_images))
    cols = rows

    if rows * cols < num_images:
        cols += 1
    if rows * cols < num_images:
        rows += 1

    width = cols * thumb_width
    height = rows * thumb_height

    return width, height

def process_image(image_path, thumb_width, thumb_height):
    """이미지를 리사이즈하고, 해당 이미지 객체를 반환
    
    :param image_path: 리사이즈할 이미지 파일 경로
    :param thumb_width: 리사이즈할 이미지의 너비
    :param thumb_height: 리사이즈할 이미지의 높이
    """
    img = Image.open(image_path)
    img = img.resize((thumb_width, thumb_height), Image.Resampling.LANCZOS)
    return img

def create_collage(image_paths, output_path, thumb_width=400, thumb_height=300):
    """ 동적으로 콜라주의 해상도 계산
    
    :param image_paths: 콜라주에 포함될 이미지 파일 경로 리스트
    :param output_path: 콜라주 이미지 파일을 저장할 경로
    :param thumb_width: 이미지의 너비
    :param thumb_height: 이미지의 높이
    
    """
    num_images = len(image_paths)
    width, height = calculate_collage_resolution(num_images)
    
    collage = Image.new('RGB', (width, height), 'white')

    x = y = 0
    
    with concurrent.futures.ThreadPoolExecutor() as executor:
        future_to_image = [executor.submit(process_image, path, thumb_width, thumb_height) for path in image_paths]
        for future in concurrent.futures.as_completed(future_to_image):
            img = future.result()
            collage.paste(img, (x, y))
            x += thumb_width
            if x >= width:
                x = 0
                y += thumb_height
    
    collage.save(output_path)

# 이미지 파일 경로 리스트 생성 및 콜라주 생성
dir_path = input("이미지 파일이 있는 디렉토리 경로 입력: ")
image_paths = [os.path.join(dir_path, file) for file in os.listdir(dir_path) if file.endswith(('jpg', 'jpeg', 'png'))]
create_collage(image_paths, 'collage_image.jpg')

 

위와 같은 방식으로 콜라주된 이미지를 간단하게  생성할 수 있다.

가장 큰 문제점은 두가지가 존재한다.

 

1. 사각형 형태의 콜라주 이미지: 지도 상에 표시할 이미지는 멀티 폴리곤 형태로 사진을 표시하는데 있어 일정한 모양을 가지지 않는다. 특정 지역의 폴리곤 좌표를 가져와서 이미지를 그에 맞춰서 합성하는 방법을 사용할 것이나, 이미지가 합성 된 후 이미지의 특정 부분이 잘려진 형태로 표현될 문제를 해결해야 한다. 

네이버지도 서울 구로구 경계선 캡처

 

2. 연산 속도: 콜라주 이미지를 생성을 하는데 800개 가량의 이미지, 해상도 4032*2268 크기를 기준으로 실행하였을 때 이미지 생성에 걸리는 시간이 대략 10초 내외였다. 서비스로 만들 경우, 이미지 생성에 다량의 요청이 왔을 경우 필요한 리소스가 상당할 것으로 예상되어 이미지 파일에 대한 일정 기준을 잡는 것이 필요할 것으로 보인다. 
고해상도의 이미지를 특정 해상도로 변환을 하는 과정이 필요하고, 한번에 업로드하는 이미지 수 등을 조절할 수 있도록 하는 방법을 사용하려고 한다. 

콜라주 이미지 예시