본문 바로가기
R&D

포토모자이크 기법

by 도승이 2022. 3. 28.

먼저 포토모자이크 기법은 서로 다른 수많은 사진이나 그림을 
컬러에 맞는 위치에 배열하여  마치 새로운 한장의 큰 이미지를 표현하도록 한 것으로
가까이 보면 각 조각들의 다양한 이미지들이 보이고  멀리서 보면 하나의 그림을 보게 된다.

파이썬을 통해 간단히 구현할 수 있다.

 

구현되어있는 github 예제를 참고했다.

 

GitHub - uvipen/Photomosaic-generator: photomosaic generator (image to image, video to video)

photomosaic generator (image to image, video to video) - GitHub - uvipen/Photomosaic-generator: photomosaic generator (image to image, video to video)

github.com

 

소스코드는 이와같이된다. (python)

import argparse
import cv2
import numpy as np
import glob
from itertools import product


def get_args():
    parser = argparse.ArgumentParser("Viet Nguyen Photomosaic")
    parser.add_argument("--input", type=str, default="data/input.jpg", help="Path to input image")
    parser.add_argument("--output", type=str, default="data/output.jpg", help="Path to output image")
    parser.add_argument("--pool", type=str, default="image_pool", help="Path to directory containing component images")
    parser.add_argument("--stride", type=int, default=30, help="size of each component image")
    args = parser.parse_args()
    return args


def get_component_images(path, size):
    images = []
    avg_colors = []
    for image_path in glob.glob("{}/*.png".format(path)) + glob.glob("{}/*.jpg".format(path)):
        image = cv2.imread(image_path, cv2.IMREAD_COLOR)
        image = cv2.resize(image, (size, size))
        images.append(image)
        avg_colors.append(np.sum(np.sum(image, axis=0), axis=0) / (size ** 2))
    return images, np.array(avg_colors)


def main(opt):
    input_image = cv2.imread(opt.input, cv2.IMREAD_COLOR)
    height, width, num_channels = input_image.shape
    blank_image = np.zeros((height, width, 3), np.uint8)
    images, avg_colors = get_component_images(opt.pool, opt.stride)
    for i, j in product(range(int(width / opt.stride)), range(int(height / opt.stride))):
        partial_input_image = input_image[j * opt.stride: (j + 1) * opt.stride,
                              i * opt.stride: (i + 1) * opt.stride, :]
        partial_avg_color = np.sum(np.sum(partial_input_image, axis=0), axis=0) / (opt.stride ** 2)
        distance_matrix = np.linalg.norm(partial_avg_color - avg_colors, axis=1)
        idx = np.argmin(distance_matrix)
        blank_image[j * opt.stride: (j + 1) * opt.stride, i * opt.stride: (i + 1) * opt.stride, :] = images[idx]
    cv2.imwrite(opt.output, blank_image)


if __name__ == '__main__':
    opt = get_args()
    main(opt)

 

옵션

--input   (Input파일의 경로,이름포함)

--output (output파일의 경로,이름포함)

--pool은 훈련집합으로 사용할 이미지파일들의 경로 (부속으로 사용할 작은이미지)

--stride는 작은이미지의 크기를 말한다.

 

테스트환경은

Anaconda - Spyder (Python 3.9) 에서 테스트했다.

 

테스트결과

원본, stride30, stride60
확대된 이미지

훈련집합 (pool)의 이미지가 부족해서 특정 컬러에 같은 이미지를 여러장씩 사용하는 모습이보인다.

훈련집합크기를 꽃사진, 동물사진, 사물사진등으로 나누어서 옵션에따라 사용하면 더 좋을것같다.

'R&D' 카테고리의 다른 글

딥러닝을 통한 이미지생성과 슈퍼샘플링  (0) 2022.04.29
Video To Image 프로그램  (0) 2022.03.28
[WebRTC] 웹 화면공유, 화상회의  (0) 2021.11.03
오픈소스 한글 입력 문제  (0) 2021.10.08

댓글