Kims12 commited on
Commit
ddcfe75
·
verified ·
1 Parent(s): 95df87a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -87
app.py CHANGED
@@ -9,9 +9,8 @@ import base64
9
  import mimetypes
10
  import logging
11
 
12
- # 기존의 "from google import genai" 대신 다음과 같이 수정
13
- import google.generativeai as genai
14
- from google.generativeai import types
15
 
16
  # .env 파일에 저장된 환경변수 로드 (python-dotenv 설치 필요: pip install python-dotenv)
17
  from dotenv import load_dotenv
@@ -22,14 +21,17 @@ logging.basicConfig(level=logging.DEBUG,
22
  format='%(asctime)s - %(levelname)s - %(message)s')
23
  logger = logging.getLogger(__name__)
24
 
 
25
  def save_binary_file(file_name, data):
26
  logger.debug(f"파일에 이진 데이터 저장 중: {file_name}")
27
  with open(file_name, "wb") as f:
28
  f.write(data)
29
  logger.debug(f"파일 저장 완료: {file_name}")
30
 
31
- def generate(text, file_name, background_file=None, style_file=None, model="gemini-2.0-flash-exp-image-generation"):
 
32
  logger.debug(f"generate 함수 시작 - 텍스트: '{text}', 파일명: '{file_name}', 모델: '{model}'")
 
33
  try:
34
  # API 키는 환경변수에서 불러옴
35
  effective_api_key = os.environ.get("GEMINI_API_KEY")
@@ -42,53 +44,23 @@ def generate(text, file_name, background_file=None, style_file=None, model="gemi
42
  client = genai.Client(api_key=effective_api_key)
43
  logger.debug("Gemini 클라이언트 초기화 완료.")
44
 
45
- # 원본, 배경, 스타일 이미지를 각각 업로드 (존재하는 경우)
46
- uploaded_files = []
47
- uploaded_files.append(client.files.upload(file=file_name))
48
- logger.debug(f"원본 파일 업로드 완료. URI: {uploaded_files[0].uri}, MIME 타입: {uploaded_files[0].mime_type}")
49
-
50
- if background_file is not None:
51
- bg_file = client.files.upload(file=background_file)
52
- uploaded_files.append(bg_file)
53
- logger.debug(f"배경 파일 업로드 완료. URI: {bg_file.uri}, MIME 타입: {bg_file.mime_type}")
54
- if style_file is not None:
55
- style_uploaded = client.files.upload(file=style_file)
56
- uploaded_files.append(style_uploaded)
57
- logger.debug(f"스타일 파일 업로드 완료. URI: {style_uploaded.uri}, MIME 타입: {style_uploaded.mime_type}")
58
-
59
- # 컨텐츠 객체 생성: 업로드한 이미지들을 순서대로(원본, 배경, 스타일) 추가하고 마지막에 텍스트 프롬프트 추가
60
- parts = []
61
- # 원본 이미지 파트
62
- parts.append(
63
- types.Part.from_uri(
64
- file_uri=uploaded_files[0].uri,
65
- mime_type=uploaded_files[0].mime_type,
66
- )
67
- )
68
- # 배경 이미지 파트 (존재 시)
69
- if background_file is not None:
70
- parts.append(
71
- types.Part.from_uri(
72
- file_uri=uploaded_files[1].uri,
73
- mime_type=uploaded_files[1].mime_type,
74
- )
75
- )
76
- # 스타일 이미지 파트 (존재 시)
77
- if style_file is not None:
78
- style_index = 2 if background_file is not None else 1
79
- parts.append(
80
- types.Part.from_uri(
81
- file_uri=uploaded_files[style_index].uri,
82
- mime_type=uploaded_files[style_index].mime_type,
83
- )
84
- )
85
- # 마지막으로 텍스트 파트 추가
86
- parts.append(types.Part.from_text(text=text))
87
 
 
88
  contents = [
89
  types.Content(
90
  role="user",
91
- parts=parts,
 
 
 
 
 
 
92
  ),
93
  ]
94
  logger.debug(f"컨텐츠 객체 생성 완료: {contents}")
@@ -132,47 +104,28 @@ def generate(text, file_name, background_file=None, style_file=None, model="gemi
132
 
133
  logger.debug(f"Raw chunk: {chunk}")
134
 
135
- del uploaded_files
136
  logger.debug("업로드된 파일 정보 삭제 완료.")
137
  return temp_path
138
 
139
  except Exception as e:
140
  logger.exception("이미지 생성 중 오류 발생:")
141
- return None
 
142
 
143
- def process_image_and_prompt(original_pil, prompt, background_pil=None, style_pil=None):
144
  logger.debug(f"process_image_and_prompt 함수 시작 - 프롬프트: '{prompt}'")
145
  try:
146
- # 원본 이미지 저장
147
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
148
- original_path = tmp.name
149
- original_pil.save(original_path)
150
- logger.debug(f"원본 이미지 저장 완료: {original_path}")
151
-
152
- # 배경 이미지 저장 (제공된 경우)
153
- background_path = None
154
- if background_pil is not None:
155
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_bg:
156
- background_path = tmp_bg.name
157
- background_pil.save(background_path)
158
- logger.debug(f"배경 이미지 저장 완료: {background_path}")
159
-
160
- # 스타일 이미지 저장 (제공된 경우)
161
- style_path = None
162
- if style_pil is not None:
163
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_style:
164
- style_path = tmp_style.name
165
- style_pil.save(style_path)
166
- logger.debug(f"스타일 이미지 저장 완료: {style_path}")
167
 
 
168
  input_text = prompt
169
  model = "gemini-2.0-flash-exp-image-generation"
170
 
171
- gemma_edited_image_path = generate(text=input_text,
172
- file_name=original_path,
173
- background_file=background_path,
174
- style_file=style_path,
175
- model=model)
176
 
177
  if gemma_edited_image_path:
178
  logger.debug(f"이미지 생성 완료. 경로: {gemma_edited_image_path}")
@@ -182,10 +135,12 @@ def process_image_and_prompt(original_pil, prompt, background_pil=None, style_pi
182
  return [result_img]
183
  else:
184
  logger.error("generate 함수에서 None 반환됨.")
185
- return []
 
186
  except Exception as e:
187
  logger.exception("process_image_and_prompt 함수에서 오류 발생:")
188
- return []
 
189
 
190
  # --- Gradio 인터페이스 구성 ---
191
  with gr.Blocks() as demo:
@@ -202,13 +157,11 @@ with gr.Blocks() as demo:
202
  </div>
203
  """
204
  )
205
- gr.Markdown("원본, 배경, 스타일 이미지를 업로드하고, 편집할 내용을 입력하세요.")
206
 
207
  with gr.Row():
208
  with gr.Column():
209
- original_input = gr.Image(type="pil", label="원본 이미지", image_mode="RGBA")
210
- background_input = gr.Image(type="pil", label="배경 이미지", image_mode="RGBA")
211
- style_input = gr.Image(type="pil", label="스타일 이미지", image_mode="RGBA")
212
  prompt_input = gr.Textbox(
213
  lines=2,
214
  placeholder="편집할 내용을 입력하세요...",
@@ -220,18 +173,17 @@ with gr.Blocks() as demo:
220
 
221
  submit_btn.click(
222
  fn=process_image_and_prompt,
223
- inputs=[original_input, prompt_input, background_input, style_input],
224
  outputs=output_gallery,
225
  )
226
 
227
  # --- 테스트 코드 ---
228
- dummy_original = Image.new("RGBA", (100, 100), color="red")
229
- dummy_background = Image.new("RGBA", (100, 100), color="green")
230
- dummy_style = Image.new("RGBA", (100, 100), color="blue")
231
- dummy_prompt = "이미지 편집: 원본은 빨강, 배경은 초록, 스타일은 파랑"
232
 
233
  logger.info("process_image_and_prompt 함수를 직접 호출합니다...")
234
- result = process_image_and_prompt(dummy_original, dummy_prompt, dummy_background, dummy_style)
235
 
236
  if result:
237
  logger.info(f"직접 호출 성공. 결과: {result}")
 
9
  import mimetypes
10
  import logging
11
 
12
+ from google import genai
13
+ from google.genai import types
 
14
 
15
  # .env 파일에 저장된 환경변수 로드 (python-dotenv 설치 필요: pip install python-dotenv)
16
  from dotenv import load_dotenv
 
21
  format='%(asctime)s - %(levelname)s - %(message)s')
22
  logger = logging.getLogger(__name__)
23
 
24
+
25
  def save_binary_file(file_name, data):
26
  logger.debug(f"파일에 이진 데이터 저장 중: {file_name}")
27
  with open(file_name, "wb") as f:
28
  f.write(data)
29
  logger.debug(f"파일 저장 완료: {file_name}")
30
 
31
+
32
+ def generate(text, file_name, model="gemini-2.0-flash-exp-image-generation"):
33
  logger.debug(f"generate 함수 시작 - 텍스트: '{text}', 파일명: '{file_name}', 모델: '{model}'")
34
+
35
  try:
36
  # API 키는 환경변수에서 불러옴
37
  effective_api_key = os.environ.get("GEMINI_API_KEY")
 
44
  client = genai.Client(api_key=effective_api_key)
45
  logger.debug("Gemini 클라이언트 초기화 완료.")
46
 
47
+ # 파일 업로드
48
+ files = [
49
+ client.files.upload(file=file_name),
50
+ ]
51
+ logger.debug(f"파일 업로드 완료. URI: {files[0].uri}, MIME 타입: {files[0].mime_type}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
+ # 컨텐츠 객체 생성: 파일 URI와 텍스트 프롬프트를 함께 포함
54
  contents = [
55
  types.Content(
56
  role="user",
57
+ parts=[
58
+ types.Part.from_uri(
59
+ file_uri=files[0].uri,
60
+ mime_type=files[0].mime_type,
61
+ ),
62
+ types.Part.from_text(text=text),
63
+ ],
64
  ),
65
  ]
66
  logger.debug(f"컨텐츠 객체 생성 완료: {contents}")
 
104
 
105
  logger.debug(f"Raw chunk: {chunk}")
106
 
107
+ del files
108
  logger.debug("업로드된 파일 정보 삭제 완료.")
109
  return temp_path
110
 
111
  except Exception as e:
112
  logger.exception("이미지 생성 중 오류 발생:")
113
+ return None # 오류 발생 시 None 반환
114
+
115
 
116
+ def process_image_and_prompt(composite_pil, prompt):
117
  logger.debug(f"process_image_and_prompt 함수 시작 - 프롬프트: '{prompt}'")
118
  try:
 
119
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
120
+ composite_path = tmp.name
121
+ composite_pil.save(composite_path)
122
+ logger.debug(f"합성 이미지 저장 완료: {composite_path}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
+ file_name = composite_path
125
  input_text = prompt
126
  model = "gemini-2.0-flash-exp-image-generation"
127
 
128
+ gemma_edited_image_path = generate(text=input_text, file_name=file_name, model=model)
 
 
 
 
129
 
130
  if gemma_edited_image_path:
131
  logger.debug(f"이미지 생성 완료. 경로: {gemma_edited_image_path}")
 
135
  return [result_img]
136
  else:
137
  logger.error("generate 함수에서 None 반환됨.")
138
+ return [] # 오류 시 빈 리스트 반환
139
+
140
  except Exception as e:
141
  logger.exception("process_image_and_prompt 함수에서 오류 발생:")
142
+ return [] # 오류 시 빈 리스트 반환
143
+
144
 
145
  # --- Gradio 인터페이스 구성 ---
146
  with gr.Blocks() as demo:
 
157
  </div>
158
  """
159
  )
160
+ gr.Markdown("이미지를 업로드하고, 편집할 내용을 입력하세요.")
161
 
162
  with gr.Row():
163
  with gr.Column():
164
+ image_input = gr.Image(type="pil", label="이미지 업로드", image_mode="RGBA")
 
 
165
  prompt_input = gr.Textbox(
166
  lines=2,
167
  placeholder="편집할 내용을 입력하세요...",
 
173
 
174
  submit_btn.click(
175
  fn=process_image_and_prompt,
176
+ inputs=[image_input, prompt_input],
177
  outputs=output_gallery,
178
  )
179
 
180
  # --- 테스트 코드 ---
181
+ # 테스트용 더미 이미지 (실제 이미지로 대체 가능)
182
+ dummy_image = Image.new("RGBA", (100, 100), color="red")
183
+ dummy_prompt = "이미지를 파란색으로 변경해줘"
 
184
 
185
  logger.info("process_image_and_prompt 함수를 직접 호출합니다...")
186
+ result = process_image_and_prompt(dummy_image, dummy_prompt)
187
 
188
  if result:
189
  logger.info(f"직접 호출 성공. 결과: {result}")