ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • HSV ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ • ์ƒ‰์ƒ Object ์ถ”์ถœํ•˜๊ธฐ
    ๊ณต๋ถ€/๋ฉ€ํ‹ฐ๋ฏธ๋””์–ด 2019. 3. 30. 00:46
    728x90

    ๊ตฌํ˜„

    1. RGB ์ด๋ฏธ์ง€๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ HSV ์ด๋ฏธ์ง€๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

    2. ์ƒ‰์ƒ์˜ ๋ฒ”์œ„์— ๋”ฐ๋ผ ํŠน์ • ์ƒ‰์ƒ์˜ ๊ฐ์ฒด๋ฅผ ์ถ”์ถœํ•˜๋Š” ๋งˆ์Šคํฌ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

    3. ์ƒ์„ฑํ•œ ๋งˆ์Šคํฌ์— ๋”ฐ๋ผ ์ด๋ฏธ์ง€๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ํŠน์ •ํ•œ ์ƒ‰์ƒ์˜ ๊ฐ์ฒด๋งŒ ์ถ”์ถœ๋˜๋Š” ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ ๋‹ค.

    4. OpenCV๋ฅผ ์‚ฌ์šฉํ•ด์„œ๋„ ํ•ด๋ณด๊ณ  ์•ˆ์“ฐ๊ณ ๋„ ํ•ด๋ดค๋‹ค.

    ์ž…๋ ฅ ์ด๋ฏธ์ง€์™€ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€(orange ์ƒ‰์ƒ์ธ ๊ฐ์ฒด๋งŒ ์ถ”์ถœ)

     

     

    RGB to HSV

    - ์ผ๋‹จ, ํŠน์ • ์ƒ‰์ƒ ๊ฐ์ฒด๋ฅผ ์ถ”์ถœํ•˜๊ธฐ ์œ„ํ•ด์„œ ์™œ HSV ์ด๋ฏธ์ง€๊ฐ€ ํ•„์š”ํ•œ์ง€๋ถ€ํ„ฐ ์•Œ์•„์•ผ ํ•œ๋‹ค. 

     

    RGB ๋ชจ๋ธ

    ์ถœ์ฒ˜ : https://tattly.com/products/rgb

    - RGB ๋ชจ๋ธ์€ ๋น›์˜ ์‚ผ์›์ƒ‰์„ ์ด์šฉํ•˜์—ฌ ์ƒ‰์„ ํ‘œํ˜„ํ•˜๋Š” ๊ธฐ๋ณธ์ ์ธ ์ƒ‰์ƒ ๋ชจ๋ธ

    - ์ƒ‰์„ ๋นจ๊ฐ•(Red), ์ดˆ๋ก(Green), ํŒŒ๋ž‘(Blue), 3๊ฐ€์ง€ ์„ฑ๋ถ„์˜ ์กฐํ•ฉ์œผ๋กœ ํ‘œํ˜„ํ•œ๋‹ค

    - R, G, B๊ฐ’์€ 0~255 ์‚ฌ์ด์˜ ๊ฐ’๋“ค๋กœ ํ‘œํ˜„๋œ๋‹ค.

     

    HSV ๋ชจ๋ธ

    ์ถœ์ฒ˜ : https://ko.wikipedia.org/wiki/HSV_%EC%83%89_%EA%B3%B5%EA%B0%84#/media/File:HSV_cone.jpg

    - HSV ๋ชจ๋ธ์€ ์ธ๊ฐ„์˜ ์ƒ‰์ธ์ง€์— ๊ธฐ๋ฐ˜์„ ๋‘” ์ƒ‰์ƒ ๋ชจ๋ธ

    - Hue(์ƒ‰์กฐ), Saturation(์ฑ„๋„), Value(๋ช…๋„), 3๊ฐ€์ง€ ์„ฑ๋ถ„์˜ ์กฐํ•ฉ์œผ๋กœ ํ‘œํ˜„

    - Hue(์ƒ‰์กฐ) : ์ƒ‰์˜ ์ข…๋ฅ˜. 0º~360º์˜ ๋ฒ”์œ„๋ฅผ ๊ฐ–๋Š”๋‹ค.

    - Saturation(์ฑ„๋„) : ์ƒ‰์˜ ์„ ๋ช…๋„, ์ง„ํ•จ์˜ ์ •๋„(๊ฐ€์žฅ ์ง„ํ•œ ์ƒํƒœ๋ฅผ 100%๋กœ ํ•œ๋‹ค)

    - Value(๋ช…๋„) : ์ƒ‰์˜ ๋ฐ๊ธฐ, ๋ฐ์€ ์ •๋„(๊ฐ€์žฅ ๋ฐ์€ ์ƒํƒœ๋ฅผ 100%๋กœ ํ•œ๋‹ค)

     

    RGB ์—์„œ HSV๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ด์œ 

    - RGB ์ด๋ฏธ์ง€์—์„œ ์ƒ‰ ์ •๋ณด๋ฅผ ๊ฒ€์ถœํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” R, G, B ์„ธ๊ฐ€์ง€ ์†์„ฑ์„ ๋ชจ๋‘ ์ฐธ๊ณ ํ•ด์•ผํ•œ๋‹ค.

    - ํ•˜์ง€๋งŒ HSV ์ด๋ฏธ์ง€์—์„œ๋Š” H(Hue)๊ฐ€ ์ผ์ •ํ•œ ๋ฒ”์œ„๋ฅผ ๊ฐ–๋Š” ์ˆœ์ˆ˜ํ•œ ์ƒ‰ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— RGB ์ด๋ฏธ์ง€๋ณด๋‹ค ์‰ฝ๊ฒŒ ์ƒ‰์„ ๋ถ„๋ฅ˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    RGB to HSV ๊ณต์‹

    ์ถœ์ฒ˜ : https://www.rapidtables.com/convert/color/rgb-to-hsv.html

    - ์œ„์˜ ๊ณต์‹์—์„œ๋Š” HSV ์ด๋ฏธ์ง€๋ฅผ H์˜ ๋ฒ”์œ„๋Š” 0~360์œผ๋กœ S, V๋Š” 0~1์˜ ๋ฒ”์œ„๋กœ ์ •๊ทœํ™” ํ–ˆ๋‹ค.

    - OpenCV์—์„œ๋Š” HSV ์ด๋ฏธ์ง€๋ฅผ H(0~180), S(0~255), V(0~255)๋กœ ํ‘œํ˜„ํ•œ๋‹ค.

    - H(Hue)๊ฐ€ 360์ด ์•„๋‹Œ 180์œผ๋กœ ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•œ ์ด์œ ๋Š” OpenCV ์ด๋ฏธ์ง€ ๋ณ€์ˆ˜๋“ค์€ 8bit๋กœ ์„ค์ •๋˜์–ด ์žˆ์–ด์„œ ์ตœ๋Œ€ 255๊นŒ์ง€๋งŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

     

    mask ์ƒ์„ฑ

    - ๋ชจ๋“  ์›์†Œ๊ฐ’์ด 0์ธ HSV ์ด๋ฏธ์ง€์™€ ๊ฐ™์€ ํฌ๊ธฐ์˜ ๋งˆ์Šคํฌ ํ–‰๋ ฌ์„ ๋งŒ๋“ ๋‹ค 

    - HSV ์ด๋ฏธ์ง€ ํ”ฝ์…€ ๊ฐ’๊ณผ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ์ƒ‰์ƒ ๋ฒ”์œ„๋ฅผ ๋น„๊ตํ•ด์„œ ํ”ฝ์…€ ๊ฐ’์ด ์ƒ‰์ƒ ๋ฒ”์œ„ ์•ˆ์— ์žˆ์„ ๊ฒฝ์šฐ, ๊ทธ์— ๋Œ€์‘๋˜๋Š” ์œ„์น˜์˜ ๋งˆ์Šคํฌ ํ–‰๋ ฌ์˜ ์›์†Œ ๊ฐ’์— 1์„ ์ž…๋ ฅํ•œ๋‹ค.

    - HSV์˜ ์ƒ‰์ƒ ๋ฒ”์œ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

    ์ถœ์ฒ˜ : https://brunch.co.kr/@chulhochoiucj0/17

    - ๊ตฌํ˜„ ๊ณผ์ •์—์„œ ์ƒ‰์ƒ์˜ ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•˜๋Š”๊ฒŒ ์ œ์ผ ํž˜๋“ค์—ˆ๋‹ค. ์œก์•ˆ์œผ๋กœ ๋‚ด๊ฐ€ ๊ฒ€์ถœํ•˜๋Š” ์ƒ‰์ƒ์˜ H, S, V๊ฐ’์„ ์ •ํ™•ํžˆ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์–ด๋Š์ •๋„ ์˜ˆ์ƒํ•ด์„œ ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•œ ๋‹ค์Œ ์ž˜ ๊ฒ€์ถœ๋˜๋Š” ๋ฒ”์œ„๋กœ ๊ณ„์† ์ˆ˜์ •ํ–ˆ๋‹ค.

    - OpenCV์—์„œ ์ƒ‰์กฐ ๋ฒ”์œ„๋Š” 0~180์ด๋ฏ€๋กœ ์›ํ•˜๋Š” ์ƒ‰์ƒ์„ ์–ป์œผ๋ ค๋ฉด HSV ์ƒ‰์ƒํ‘œ ๊ฐ’์—์„œ 1/2 ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

    โ€ป ์˜ค๋ Œ์ง€ ์ƒ‰๊ณผ ์ดˆ๋ก์ƒ‰์€ ์ƒ‰์ƒํ‘œ์™€ ์ผ์น˜ํ–ˆ๋Š”๋ฐ ํŒŒ๋ž€์ƒ‰์€ ์ „ํ˜€ ๋‹ค๋ฅธ ์ˆ˜์น˜์—์„œ ๊ฒ€์ถœ๋˜์—ˆ๋‹ค. ์™œ ๊ทธ๋Ÿด๊นŒ...?๐Ÿค”

     

    mask๋ฅผ ์ด์šฉํ•œ object ์ถ”์ถœ ์ด๋ฏธ์ง€ ๊ณ„์‚ฐ

    - ์›๋ณธ ์ด๋ฏธ์ง€์— ๋Œ€์‘๋˜๋Š” mask ํ–‰๋ ฌ์˜ ๊ฐ’์— ๋”ฐ๋ผ ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค.

    - mask ๊ฐ’์ด 1์ธ ๋ถ€๋ถ„์€ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ์ƒ‰์ƒ์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— R, G, B๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋‹ค.

    - mask ๊ฐ’์ด 0์ธ ๋ถ€๋ถ„์€ R, G, B๊ฐ’์— 0์„ ๊ณฑํ•ด ๊ฒ€์€ ์ƒ‰์œผ๋กœ ๋งŒ๋“ ๋‹ค.

     

     

    Code

     

    OpenCV๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„

    import cv2
    # matplotlib.image ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„  matplotlib ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ pillow๋„ ๊น”์•„์•ผ ํ•œ๋‹ค.
    import matplotlib.pyplot as plt
    import matplotlib.image as mpimg
    
    
    # ์ƒ‰์ƒ ๋ฒ”์œ„ ์„ค์ •
    lower_orange = (100, 200, 200)
    upper_orange = (140, 255, 255)
    
    lower_green = (30, 80, 80)
    upper_green = (70, 255, 255)
    
    lower_blue = (0, 180, 55)
    upper_blue = (20, 255, 200)
    
    # ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ์ฝ์–ด์˜จ๋‹ค
    img = mpimg.imread("test2.jpg", cv2.IMREAD_COLOR)
    
    # BGR to HSV ๋ณ€ํ™˜
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    
    # ์ƒ‰์ƒ ๋ฒ”์œ„๋ฅผ ์ œํ•œํ•˜์—ฌ mask ์ƒ์„ฑ
    img_mask = cv2.inRange(img_hsv, lower_orange, upper_orange)
    
    # ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ง€๊ณ  Object ์ถ”์ถœ ์ด๋ฏธ์ง€๋กœ ์ƒ์„ฑ
    img_result = cv2.bitwise_and(img, img, mask=img_mask)
    
    # ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
    imgplot = plt.imshow(img_result)
    
    plt.show()

     

    OpenCV์—†์ด ๊ตฌํ˜„

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.image as mping
    
    
    def RGB2HSV(RGB):
        # HSV ์ƒ‰์ƒ์„ ์–ป๊ธฐ ์œ„ํ•ด์„œ๋Š” array ํƒ€์ž…์ด float์ด ๋˜์–ด์•ผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค
        RGB_array = np.array(RGB).astype(np.float64)
        
        # ๋ณ€ํ™˜ํ•  HSV ์ด๋ฏธ์ง€ ์ƒ์„ฑ
        HSV = np.array(RGB).astype(np.float64)
        
        # RGB ์ด๋ฏธ์ง€์˜ width, height ์ €์žฅ
        width, height = RGB_array.shape[:2]
    
        # ์ด๋ฏธ์ง€ ํฌ๊ธฐ๋งŒํผ for ๋ฃจํ”„
        for i in range(width):
            for j in range(height):
                # ๊ณต์‹ ๋”ฐ๋ผ์„œ ๊ตฌํ˜„
                var_R = RGB_array[i, j, 0] / 255.0
                var_G = RGB_array[i, j, 1] / 255.0
                var_B = RGB_array[i, j, 2] / 255.0
    
                C_Min = min(var_R, var_G, var_B)
                C_Max = max(var_R, var_G, var_B)
    
                change = C_Max - C_Min
                V = C_Max
                
                if C_Max == 0:
                    S = 0
                else:
                    S = change / C_Max
                    
                if change == 0:
                    H = 0
                else:
                    if var_R == C_Max:
                        H = 60 * (((var_R - var_B)/change)%6)
                    elif var_G == C_Max:
                        H = 60 * (((var_B - var_R)/change)+2)
                    elif var_B == C_Max:
                        H = 60 * (((var_R - var_B)/change)+4)
                        
                HSV[i, j, 0] = H
                HSV[i, j, 1] = S
                HSV[i, j, 2] = V     
                
        return HSV
    
    def Mask(HSV, color):
        # ๋ฒ”์œ„๊ฐ’๊ณผ ๋น„๊ตํ•  hsv ์ด๋ฏธ์ง€ ์ƒ์„ฑ, ํŒŒ๋ผ๋ฏธํ„ฐ์— ์žˆ๋Š” HSV๋ฅผ ๊ทธ๋ƒฅ ์“ฐ๋ฉด ์›์†Œ๊ฐ’์ด float์ด ์•„๋‹Œ int๋กœ ๋‚˜์˜ด
        hsv = np.array(HSV).astype(np.float64)
    
        # HSV ์ด๋ฏธ์ง€์˜ width, height ์ €์žฅ
        width, height = HSV.shape[:2]
    
        # ๋ชจ๋“  ๊ฐ’์€ ์›์†Œ ๊ฐ’์ด 0 ์ธ ๋งˆ์Šคํฌ ํ–‰๋ ฌ ์ƒ์„ฑ
        mask = np.zeros((width, height))
    
        # hsv ๊ฐ’๊ณผ ๋ฒ”์œ„ ๋น„๊ต
        for i in range(width):
            for j in range(height):
                # H, S, V ๊ฐ’์ด ์›ํ•˜๋Š” ๋ฒ”์œ„ ์•ˆ์— ๋“ค์–ด๊ฐˆ ๊ฒฝ์šฐ mask ์›์†Œ ๊ฐ’์„ 1๋กœ ๋งŒ๋“ ๋‹ค
                if hsv[i, j, 0] > lower[color][0] and hsv[i, j, 1] > lower[color][1] and hsv[i, j, 2] > lower[color][2] and hsv[i, j, 0] < upper[color][0] and hsv[i, j, 1] < upper[color][1] and hsv[i, j, 2] < upper[color][2]:
                    mask[i, j] = 1
                    
        return mask
    
    def Extraction(image, mask):
        # Object๋ฅผ ์ถ”์ถœํ•  ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑ
        result_img = np.array(image)
    
        # RGB ์ด๋ฏธ์ง€์˜ width, height ์ €์žฅ
        width, height = image.shape[:2]
    
        # for ๋ฃจํ”„๋ฅผ ๋Œ๋ฉด์„œ mask ์›์†Œ ๊ฐ’์ด 0์ธ ์ธ๋ฑ์Šค๋Š” ์›๋ณธ ์ด๋ฏธ์ง€๋„ 0์œผ๋กœ ๋งŒ๋“ค์–ด ์ค€๋‹ค.
        for i in range(width):
            for j in range(height):
                if(mask[i, j] == 0):
                    result_img[i, j, 0] = 0
                    result_img[i, j, 1] = 0
                    result_img[i, j, 2] = 0
                    
        return result_img
    
    
    if __name__ == '__main__':
        # ๋งˆ์Šคํฌ ์ƒ‰์ƒ ๋ฒ”์œ„์— ์‚ฌ์šฉํ•  ๋”•์…”๋„ˆ๋ฆฌ ์ •์˜
        upper = {}
        lower = {}
    
        upper['orange'] = [100, 1, 1]
        upper['blue'] = [300, 1, 1]
        upper['green'] = [180, 0.7, 0.5]
    
        lower['orange'] = [0, 0.7, 0.5]
        lower['blue'] = [70, 0.7, 0.2]
        lower['green'] = [101, 0.15, 0]
    
        # ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ์ฝ์–ด์˜จ๋‹ค
        input_image = mping.imread('test2.jpg')
    
        # ์ถ”์ถœํ•˜๊ณ  ์‹ถ์€ ์ƒ‰์ƒ ์ž…๋ ฅ
        input_color = input("์ถ”์ถœํ•˜๊ณ  ์‹ถ์€ ์ƒ‰์ƒ์„ ์ž…๋ ฅํ•˜์„ธ์š” (orange, blue, green) : ")
    
        # RGB to HSV ๋ณ€ํ™˜
        HSV = RGB2HSV(input_image)
    
        # HSV ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ง€๊ณ  ๋งˆ์Šคํฌ ์ƒ์„ฑ
        mask = Mask(HSV, input_color)
    
        # mask๋ฅผ ๊ฐ€์ง€๊ณ  ์›๋ณธ์ด๋ฏธ์ง€๋ฅผ Object ์ถ”์ถœ ์ด๋ฏธ์ง€๋กœ ๋ณ€ํ™˜
        result_image = Extraction(input_image, mask)
    
        #mping.imsave("result.jpg", result_image)
    
        # ์ด๋ฏธ์ง€ ๋ณด์—ฌ์ฃผ๊ธฐ
        imgplot = plt.imshow(result_image)
    
        plt.show()

     

    ๊ฒฐ๊ณผ๋ฌผ

    - ๋งˆ์ง€๋ง‰ ํŒŒ๋ž€์ƒ‰ ์ƒ‰์ƒ์€ ์ง์ ‘ ๊ตฌํ˜„ํ–ˆ์„๋•Œ๋Š” ์ •ํ™•ํžˆ ๊ฒ€์ถœ๋˜์ง€ ์•Š์•˜๋‹ค.

    - RGB to HSV ๊ณต์‹ ๊ตฌํ˜„์— ๋ฌธ์ œ๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์•„๋‹ˆ๋ฉด ์ƒ‰์ƒ ๋ฒ”์œ„๋ฅผ ์ œ๋Œ€๋กœ ์ง€์ •ํ•˜์ง€ ๋ชปํ•œ ๊ฒƒ ๊ฐ™์€๋ฐ ์ข€ ๋” ์ˆ˜์ •์ด ํ•„์š”ํ•˜๋‹ค.

     

    ์ฐธ๊ณ ์‚ฌํ•ญ

    - OpenCV๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฝ์–ด ๋“ค์ธ ์ด๋ฏธ์ง€๋ฅผ matplotlib๋กœ ํ™”๋ฉด์— ์ถœ๋ ฅํ•  ๋•Œ, ์ถœ๋ ฅํ•œ ์ƒ‰์ด ์ด์ƒํ•˜๊ฒŒ ๋‚˜์˜ค๋Š”๋ฐ ๊ทธ ์ด์œ ๋Š” OpenCV์—์„œ๋Š” ์ปฌ๋Ÿฌ ์ด๋ฏธ์ง€๋ฅผ RGB๊ฐ€ ์•„๋‹Œ BRG์ˆœ์„œ๋กœ ์ €์žฅํ•˜๋Š”๋ฐ matplotlib์—์„  RGB ์ˆœ์„œ๋กœ ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋”ฐ๋ผ์„œ matplotlib์—์„œ ์ถœ๋ ฅํ•  ๋•Œ๋Š” BRG๋ฅผ RGB๋กœ ๋ฐ”๊ฟ”์ค˜์•ผ ํ•œ๋‹ค.

    - H, S, V๊ฐ’์„ ์ฐพ๋Š”๊ฒŒ ์ƒ๊ฐ๋ณด๋‹ค ํž˜๋“ค์—ˆ๋‹ค. ์ผ์ผ์ด ์ฐพ๋Š” ๋ฌด์‹ํ•œ ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋ผ ์›ํ•˜๋Š” ํ”ฝ์…€ ์ƒ‰์ƒ์˜ H, S, V ๊ฐ’์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ๋ฒ”์œ„๋ฅผ ์‰ฝ๊ฒŒ ์ •ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. 

     

     

    ๐Ÿค”

    728x90

    ๋Œ“๊ธ€

Designed by Tistory.