File size: 8,001 Bytes
bbe1ed5
f586132
c98abc8
 
f586132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1a1812a
 
 
f586132
1a1812a
 
f586132
1a1812a
 
 
f586132
 
 
1a1812a
f586132
1a1812a
 
 
 
f586132
1a1812a
 
 
f586132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bbe1ed5
e1f10a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f586132
e1f10a7
 
f586132
 
 
 
d34cf4e
e1f10a7
f586132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ae4d776
f586132
ae4d776
 
 
f586132
 
 
 
 
 
 
1a1812a
 
 
 
 
 
 
 
 
 
 
f586132
1a1812a
f586132
 
 
 
1a1812a
 
 
 
 
 
 
 
f586132
1a1812a
 
 
 
 
 
 
 
44f2452
efd1ae9
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import streamlit as st
import streamlit.components.v1 as components
import cv2
import numpy as np
from PIL import Image, ExifTags

# κ°€μž₯ λ¨Όμ € set_page_config() 호좜
st.set_page_config(page_title="λ”₯페이크 사전 λ°©μ§€ ν•„ν„°(ν…ŒμŠ€νŠΈ)", layout="wide")

ga_code = """
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-PZPBGNENQG"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-PZPBGNENQG');
</script>
"""

# Streamlit에 GA μ½”λ“œ μ‚½μž…
components.html(ga_code, height=0)

# λ°˜μ‘ν˜• λ””μžμΈμ„ μœ„ν•œ CSS
css = """
    <style>
    .container {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 20px;
        align-items: center;
        justify-items: center;
    }

    .custom-caption-1, .custom-caption-2 {
        font-size: 20px;
        font-weight: bold;
        text-align: center;
        margin-top: 10px;
        color: white;
    }

    @media only screen and (max-width: 768px) {
        .container {
            grid-template-columns: 1fr;
        }

        .custom-caption-1, .custom-caption-2 {
            font-size: 16px;
        }
    }
    </style>
"""

# CSSλ₯Ό HTML둜 μ‚½μž…
st.markdown(css, unsafe_allow_html=True)

st.title("λ”₯페이크 사전 λ°©μ§€ ν•„ν„°(ν…ŒμŠ€νŠΈ)")
st.markdown("")
st.markdown("<span style='font-size: 18px;'>μ•ˆλ…•ν•˜μ„Έμš”! μ €ν¬λŠ” λ”₯νŽ˜μ΄ν¬λ‘œλΆ€ν„° μ—¬λŸ¬λΆ„μ˜ 사진을 λ³΄ν˜Έν•˜λŠ” μ†”λ£¨μ…˜μ„ κ°œλ°œν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.</span>", unsafe_allow_html=True)
st.markdown("<span style='font-size: 18px;'>μ €ν¬μ˜ λͺ©ν‘œλŠ” μ˜¨λΌμΈμ— κ²Œμ‹œλœ 개인의 사진이 μ•…μ„± λ”₯페이크 μ˜μƒμ— μ‚¬μš©λ˜μ§€ μ•Šλ„λ‘ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. ν˜„μž¬λŠ” κ°œλ°œμ„ λ§ˆλ¬΄λ¦¬ν•˜κ³  μ„œλΉ„μŠ€ν™” ν•˜κΈ° μ „, μ—¬λŸ¬λΆ„μ˜ μ˜κ²¬μ„ λ“£κΈ° μœ„ν•΄ κ°„λ‹¨ν•œ ν…ŒμŠ€νŠΈλ₯Ό μ§„ν–‰ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.</span>", unsafe_allow_html=True)
st.markdown("<span style='font-size: 18px;'>졜근 SNS에 μ—…λ‘œλ“œλœ 이미지가 λ”₯페이크 포λ₯΄λ…Έλ¬Όμ— μ•…μš©λ˜λŠ” 사둀가 맀일 보고되고 μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ 해결책을 κ°•κ΅¬ν•˜κΈ° μœ„ν•΄, μ—¬λŸ¬λΆ„μ˜ μ†Œμ€‘ν•œ 의견이 ν•„μš”ν•©λ‹ˆλ‹€.</span>", unsafe_allow_html=True)
st.markdown("<span style='font-size: 18px;'>μ•„λž˜ 링크λ₯Ό 톡해 저희 μ„œλΉ„μŠ€λ₯Ό μ΄μš©ν•΄ 보신 ν›„, 인터뷰에 μ°Έμ—¬ν•΄ μ£Όμ‹œλ©΄ 큰 도움이 λ˜κ² μŠ΅λ‹ˆλ‹€. μ—¬λŸ¬λΆ„μ˜ ν”Όλ“œλ°±μ€ μ„œλΉ„μŠ€ κ°œμ„ μ— κ·€μ€‘ν•œ μžλ£Œκ°€ 될 κ²ƒμž…λ‹ˆλ‹€.</span>", unsafe_allow_html=True)
st.markdown("")
st.markdown("<span style='font-size: 18px;'>λ™μž‘ 원리 : 1. 이미지λ₯Ό μ—…λ‘œλ“œν•˜λ©΄, 사전 λ°©μ§€ ν•„ν„°κ°€ 적용된 이미지λ₯Ό λ³΄μ—¬λ“œλ¦½λ‹ˆλ‹€. 2. ν•˜λ‹¨μ˜ 흰 λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ λ”₯페이크 λͺ¨λΈμ„ 톡해 μƒμ„±λœ κ²°κ³Όλ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.</span>", unsafe_allow_html=True)
st.markdown("<span style='font-size: 18px;'>μ—¬λŸ¬λΆ„μ˜ 참여에 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€!</span>", unsafe_allow_html=True)
st.markdown("<span style='font-size: 14px;'> *사전 λ°©μ§€ ν•„ν„°λž€: μ—¬λŸ¬λΆ„μ˜ 사진이 λ”₯페이크 λͺ¨λΈμ— ν•™μŠ΅λ˜μ§€ λͺ»ν•˜λ„둝 λ°©ν•΄ν•˜λŠ” λ…Έμ΄μ¦ˆ(noise)ν˜•νƒœμ˜ ν•„ν„°.</span>", unsafe_allow_html=True)

def change_hair_to_blonde(image):
    # Convert to OpenCV format
    image = np.array(image)
    # Convert the image to HSV color space
    hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)

    # Define the range for hair color (dark colors)
    lower_hair = np.array([0, 0, 0])
    upper_hair = np.array([180, 255, 30])

    # Create a mask for hair
    mask = cv2.inRange(hsv, lower_hair, upper_hair)

    # Change hair color to blonde (light yellow)
    hsv[mask > 0] = (30, 255, 200)

    # Convert back to RGB color space
    image_blonde = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)
    return image_blonde

def add_noise(image):
    # Convert to OpenCV format
    image_np = np.array(image)
    # Generate random noise
    noise = np.random.normal(0, 25, image_np.shape).astype(np.uint8)
    # Add noise to the image
    noisy_image = cv2.add(image_np, noise)
    return noisy_image

def correct_image_orientation(image):
    try:
        for orientation in ExifTags.TAGS.keys():
            if ExifTags.TAGS[orientation] == 'Orientation':
                break
        exif = image._getexif()
        if exif is not None:
            orientation = exif.get(orientation, 1)
            if orientation == 3:
                image = image.rotate(180, expand=True)
            elif orientation == 6:
                image = image.rotate(270, expand=True)
            elif orientation == 8:
                image = image.rotate(90, expand=True)
    except (AttributeError, KeyError, IndexError):
        pass
    return image

uploaded_file = st.file_uploader("이미지λ₯Ό μ—…λ‘œλ“œν•˜μ„Έμš”...", type=["jpg", "png", "jpeg"])

if uploaded_file is not None:
    image = Image.open(uploaded_file)
    image = correct_image_orientation(image)
    
    st.write("이미지 처리 쀑...")

    # Save the original image as a numpy array
    image_np = np.array(image)

    st.markdown('<div class="container">', unsafe_allow_html=True)

    st.markdown('<div>', unsafe_allow_html=True)
    st.image(image, use_column_width=True)
    st.markdown('<div class="custom-caption-1">μ—…λ‘œλ“œν•œ 이미지</div>', unsafe_allow_html=True)
    st.markdown('</div>', unsafe_allow_html=True)

    st.markdown('<div>', unsafe_allow_html=True)
    st.image(image, use_column_width=True)
    st.markdown('<div class="custom-caption-1">ν•„ν„°λ₯Ό μž…νžŒ 이미지</div>', unsafe_allow_html=True)
    st.markdown('</div>', unsafe_allow_html=True)

    st.markdown('</div>', unsafe_allow_html=True)

    button_clicked = st.button("μƒλ‹¨μ˜ 두 사진을 λ”₯페이크 λͺ¨λΈμ— ν•™μŠ΅μ‹œν‚€κΈ°")

    if button_clicked:
        st.markdown('<div class="container">', unsafe_allow_html=True)

        st.markdown('<div>', unsafe_allow_html=True)
        processed_image = change_hair_to_blonde(image)
        st.image(processed_image, use_column_width=True)
        st.markdown('<div class="custom-caption-2">원본 이미지λ₯Ό λ”₯페이크 λͺ¨λΈμ— λ„£μ—ˆμ„ 경우</div>', unsafe_allow_html=True)
        st.markdown("<span>이해λ₯Ό 돕기 μœ„ν•΄ 사진에 λ…Έλž€μƒ‰μ„ μž…νžˆλŠ” λ”₯페이크 μ•Œκ³ λ¦¬μ¦˜ 적용. 원본 μ΄λ―Έμ§€λŠ” λ”₯페이크 μ•Œκ³ λ¦¬μ¦˜μ˜ 영ν–₯을 λ°›μŒ.</span>", unsafe_allow_html=True)
        st.markdown('</div>', unsafe_allow_html=True)
        
        st.markdown('<div>', unsafe_allow_html=True)
        deepfake_image = add_noise(image)
        st.image(deepfake_image, use_column_width=True)
        st.markdown('<div class="custom-caption-2">사전 λ°©μ§€ ν•„ν„° 이미지λ₯Ό λ”₯페이크 λͺ¨λΈμ— λ„£μ—ˆμ„ 경우</div>', unsafe_allow_html=True)
        st.markdown("<span>사전 λ°©μ§€ ν•„ν„°λ₯Ό μž…νžŒ μ΄λ―Έμ§€λŠ” λ”₯페이크 μ•Œκ³ λ¦¬μ¦˜μ˜ 영ν–₯을 λ°›μ§€ μ•Šκ³  λ…Έμ΄μ¦ˆ μ²˜λ¦¬κ°€ λ˜μ–΄ μ•Œμ•„λ³΄κΈ° νž˜λ“  사진을 좜λ ₯. 즉, λ”₯페이크 사진 합성을 방해함.</span>", unsafe_allow_html=True)
        st.markdown('</div>', unsafe_allow_html=True)

        st.markdown('</div>', unsafe_allow_html=True)

        # 인터뷰 κ΄€λ ¨ 문ꡬλ₯Ό λ²„νŠΌ 클릭 ν›„ μ•„λž˜μ— ν‘œμ‹œ
        st.markdown('<p class="survey">μœ„ μ„œλΉ„μŠ€λ₯Ό μ‚¬μš©ν•΄ λ³΄μ…¨κ±°λ‚˜, 저희 기술적 원리에 관심이 μžˆμœΌμ‹  λΆ„λ“€κ»˜μ„  μ•„λž˜μ˜ κ°„λ‹¨ν•œ 인터뷰에 μ°Έμ—¬ν•΄ μ£Όμ‹œλ©΄ μ§„μ‹¬μœΌλ‘œ κ°μ‚¬λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€.</p>', unsafe_allow_html=True)
        st.markdown('<p class="survey-1"><a href="https://docs.google.com/forms/d/e/1FAIpQLSdzRtuvQyp3CQDhlxEag40v2yDM7u9NYpJ2gv5kgwuNbo1gUA/viewform?usp=sf_link" target="_blank" class="a-tag">μ—¬κΈ°λ₯Ό ν΄λ¦­ν•˜μ—¬ 인터뷰에 응해 μ£Όμ‹ λ‹€λ©΄ 큰 도움이 될 것 κ°™μŠ΅λ‹ˆλ‹€!!</a></p>', unsafe_allow_html=True)
        st.markdown('<p class="survey-2">μ„œλΉ„μŠ€λ₯Ό μ΄μš©ν•΄ μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€! 쒋은 ν•˜λ£¨ λ³΄λ‚΄μ„Έμš”!</p>', unsafe_allow_html=True)