destroy / app.py
minhwai's picture
Update app.py
efd1ae9 verified
raw
history blame
8 kB
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)