Image_Filter-1 / app.py
ssboost's picture
Create app.py
34a5d93 verified
raw
history blame
9.52 kB
import cv2
import numpy as np
from PIL import Image, ImageEnhance, ImageFilter
import gradio as gr
from io import BytesIO
import tempfile
import logging
# 로깅 설정 - INFO 레벨로 변경
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def adjust_brightness(image, value):
"""이미지 밝기 조절"""
value = float(value - 1) * 100 # 0-2 범위를 -100에서 +100으로 변환
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
v = cv2.add(v, value)
v = np.clip(v, 0, 255)
final_hsv = cv2.merge((h, s, v))
return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
def adjust_contrast(image, value):
"""이미지 대비 조절"""
value = float(value)
return np.clip(image * value, 0, 255).astype(np.uint8)
def adjust_saturation(image, value):
"""이미지 채도 조절"""
value = float(value - 1) * 100 # 0-2 범위를 -100에서 +100으로 변환
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
s = cv2.add(s, value)
s = np.clip(s, 0, 255)
final_hsv = cv2.merge((h, s, v))
return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
def adjust_temperature(image, value):
"""이미지 색온도 조절 (색상 밸런스)"""
value = float(value) * 30 # 효과 스케일 조절
b, g, r = cv2.split(image)
if value > 0: # 따뜻하게
r = cv2.add(r, value)
b = cv2.subtract(b, value)
else: # 차갑게
r = cv2.add(r, value)
b = cv2.subtract(b, value)
r = np.clip(r, 0, 255)
b = np.clip(b, 0, 255)
return cv2.merge([b, g, r])
def adjust_tint(image, value):
"""이미지 색조 조절"""
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv_image)
h = cv2.add(h, int(value))
h = np.clip(h, 0, 179) # Hue 값은 0-179 범위
final_hsv = cv2.merge((h, s, v))
return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
def adjust_exposure(image, value):
"""이미지 노출 조절"""
enhancer = ImageEnhance.Brightness(Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)))
img_enhanced = enhancer.enhance(1 + float(value) / 5.0)
return cv2.cvtColor(np.array(img_enhanced), cv2.COLOR_RGB2BGR)
def adjust_vibrance(image, value):
"""이미지 활기 조절"""
img = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
converter = ImageEnhance.Color(img)
factor = 1 + (float(value) / 100.0)
img = converter.enhance(factor)
return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
def adjust_color_mixer_blues(image, value):
"""이미지 컬러 믹서 (블루) 조절"""
b, g, r = cv2.split(image)
b = cv2.add(b, float(value))
b = np.clip(b, 0, 255)
return cv2.merge([b, g, r])
def adjust_shadows(image, value):
"""이미지 그림자 조절"""
pil_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
enhancer = ImageEnhance.Brightness(pil_image)
factor = 1 + (float(value) / 100.0)
pil_image = enhancer.enhance(factor)
return cv2.cvtColor(np.array(pil_image), cv2.COLOR_BGR2RGB)
def process_image(image, brightness, contrast, saturation, temperature, tint, exposure, vibrance, color_mixer_blues, shadows):
"""모든 조정 사항을 이미지에 적용"""
if image is None:
return None
# PIL 이미지를 OpenCV 형식으로 변환
image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
# 조정 사항 순차 적용
image = adjust_brightness(image, brightness)
image = adjust_contrast(image, contrast)
image = adjust_saturation(image, saturation)
image = adjust_temperature(image, temperature)
image = adjust_tint(image, tint)
image = adjust_exposure(image, exposure)
image = adjust_vibrance(image, vibrance)
image = adjust_color_mixer_blues(image, color_mixer_blues)
image = adjust_shadows(image, shadows)
# PIL 이미지로 다시 변환
return Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
def download_image(image, input_image_name):
"""이미지를 JPG 형식으로 저장하고 경로 반환"""
if image is None:
return None
# 한국 시간 타임스탬프 생성 함수
from datetime import datetime, timedelta
def get_korean_timestamp():
korea_time = datetime.utcnow() + timedelta(hours=9)
return korea_time.strftime('%Y%m%d_%H%M%S')
timestamp = get_korean_timestamp()
if input_image_name and hasattr(input_image_name, 'name'):
base_name = input_image_name.name.split('.')[0] # 파일 객체에서 이름 추출
else:
base_name = "이미지"
file_name = f"[끝장AI]끝장필터_{base_name}_{timestamp}.jpg"
# 파일 저장
temp_file_path = tempfile.gettempdir() + "/" + file_name
image.save(temp_file_path, format="JPEG")
return temp_file_path
def create_interface():
css = """
footer {
visibility: hidden;
}
.download-button, .download-output {
width: 100%;
}
.download-container {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
#gradio-app {
margin: 0 !important; /* 모든 방향 여백 제거 */
text-align: left !important; /* 왼쪽 정렬 강제 */
padding: 20px !important; /* 패딩 추가 */
}
.gradio-container {
max-width: 100% !important; /* 가로 폭 전체 사용 */
margin-left: 0 !important; /* 왼쪽 정렬 */
padding: 20px !important; /* 패딩 추가 */
}
.download-button {
background-color: black !important;
color: white !important;
border: none !important;
padding: 10px !important;
font-size: 16px !important;
}
"""
with gr.Blocks(theme=gr.themes.Soft(
primary_hue=gr.themes.Color(
c50="#FFF7ED", # 가장 밝은 주황
c100="#FFEDD5",
c200="#FED7AA",
c300="#FDBA74",
c400="#FB923C",
c500="#F97316", # 기본 주황
c600="#EA580C",
c700="#C2410C",
c800="#9A3412",
c900="#7C2D12", # 가장 어두운 주황
c950="#431407",
),
secondary_hue="zinc", # 모던한 느낌의 회색 계열
neutral_hue="zinc",
font=("Pretendard", "sans-serif")
), css=css) as interface:
with gr.Row():
# 왼쪽 열: 비율 3
with gr.Column(scale=3):
# 이미지 업로드
input_image = gr.Image(type="pil", label="이미지 업로드")
# 조정 슬라이더
brightness_slider = gr.Slider(0.0, 2.0, value=1.0, step=0.1, label="밝기 조절")
contrast_slider = gr.Slider(0.5, 1.5, value=1.0, step=0.1, label="대비 조절")
saturation_slider = gr.Slider(0.0, 2.0, value=1.0, step=0.1, label="채도 조절")
temperature_slider = gr.Slider(-1.0, 1.0, value=0.0, step=0.1, label="색온도 조절")
tint_slider = gr.Slider(-100, 100, value=0, step=1, label="색조 조절")
exposure_slider = gr.Slider(-5.0, 5.0, value=0.0, step=0.1, label="노출 조절")
vibrance_slider = gr.Slider(-100.0, 100.0, value=0.0, step=1.0, label="활기 조절")
color_mixer_blues_slider = gr.Slider(-100.0, 100.0, value=0.0, step=1.0, label="컬러 믹서 (블루)")
shadows_slider = gr.Slider(-100.0, 100.0, value=0.0, step=1.0, label="그림자 조절")
# 오른쪽 열: 비율 7
with gr.Column(scale=7):
# 처리된 이미지 출력
output_image = gr.Image(type="pil", label="처리된 이미지")
# 변환된 이미지 다운로드 버튼
with gr.Row(elem_classes="download-container"):
download_button = gr.Button("JPG로 변환하기", elem_classes="download-button")
with gr.Row(elem_classes="download-container"):
download_output = gr.File(label="JPG 이미지 다운로드", elem_classes="download-output")
# 이미지 처리 함수 연결
inputs = [
input_image,
brightness_slider,
contrast_slider,
saturation_slider,
temperature_slider,
tint_slider,
exposure_slider,
vibrance_slider,
color_mixer_blues_slider,
shadows_slider
]
input_components = [
brightness_slider,
contrast_slider,
saturation_slider,
temperature_slider,
tint_slider,
exposure_slider,
vibrance_slider,
color_mixer_blues_slider,
shadows_slider
]
for input_component in input_components:
input_component.change(
fn=process_image,
inputs=inputs,
outputs=output_image
)
# 다운로드 버튼 기능
download_button.click(
fn=download_image,
inputs=[output_image, input_image],
outputs=download_output
)
return interface
# 인터페이스 생성 및 실행
if __name__ == "__main__":
logger.info("애플리케이션 시작")
interface = create_interface()
interface.queue()
interface.launch()