Rzx008 commited on
Commit
da93df5
verified
1 Parent(s): cf57dc0

Update iphone.py

Browse files
Files changed (1) hide show
  1. iphone.py +102 -145
iphone.py CHANGED
@@ -13,6 +13,7 @@ class IPhoneEditor:
13
  def process_image(self, image_path, anggota):
14
  image = cv2.imread(image_path)
15
  if image is None:
 
16
  return
17
  result = self._process_core(image, anggota, show_preview=True)
18
  return result
@@ -24,6 +25,7 @@ class IPhoneEditor:
24
  image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
25
  result = self._process_core(image, anggota, show_preview=False, return_theme=True)
26
  if result is None:
 
27
  return None, None
28
  result_image, theme = result
29
  if result_image is not None:
@@ -32,6 +34,7 @@ class IPhoneEditor:
32
  pil_result.save(output_io, format='PNG')
33
  img_b64 = base64.b64encode(output_io.getvalue()).decode('utf-8')
34
  return img_b64, theme
 
35
  return None, None
36
  except Exception as e:
37
  print(f"Error in process_image_bytes: {str(e)}")
@@ -41,189 +44,144 @@ class IPhoneEditor:
41
  try:
42
  extracted_data = pytesseract.image_to_data(image, output_type=pytesseract.Output.DICT)
43
  text_list = extracted_data['text']
44
- group_position = None
45
- split_position = None
46
- member_position = None
47
- member_count_position = None
48
- lang = ''
49
-
50
- # Find all occurrences of "Grup" or "Group"
51
- group_indices = []
52
  for i, text in enumerate(text_list):
53
- if text in ["Grup", "Group"]:
54
- group_indices.append(i)
55
-
56
- # Try each occurrence of Group until we find a valid one
57
- for group_idx in group_indices:
58
- i = group_idx
59
-
60
- # Cari teks "members" atau "anggota" setelah "Group"
61
- member_idx = None
62
- for j in range(i, min(i + 10, len(text_list))):
63
- if text_list[j].lower() in ["anggota", "members", "member"]:
64
- member_idx = j
65
- break
66
-
67
- if member_idx is not None:
68
- # Cari posisi "-" antara "Group" dan "members"
69
- split_idx = None
70
- for j in range(i, member_idx):
71
- if text_list[j] == "-":
72
- split_idx = j
73
- break
74
-
75
- # Cari angka sebelum "members"
76
- number_idx = None
77
- for j in range(member_idx - 1, max(i, member_idx - 5), -1):
78
- if text_list[j].isdigit():
79
- number_idx = j
80
- break
81
-
82
- # Jika semua elemen ditemukan, proses gambar
83
- if split_idx is not None and number_idx is not None:
84
- lang = 'id' if text_list[i] == "Grup" else 'en'
85
-
86
- group_position = {
87
- "left": extracted_data['left'][i],
88
- "top": extracted_data['top'][i],
89
- "width": extracted_data['width'][i],
90
- "height": extracted_data['height'][i],
91
- }
92
-
93
- split_position = {
94
- "left": extracted_data['left'][split_idx],
95
- "top": extracted_data['top'][split_idx],
96
- "width": extracted_data['width'][split_idx],
97
- "height": extracted_data['height'][split_idx],
98
- }
99
-
100
- member_position = {
101
- "left": extracted_data['left'][member_idx],
102
- "top": extracted_data['top'][member_idx],
103
- "width": extracted_data['width'][member_idx],
104
- "height": extracted_data['height'][member_idx],
105
- }
106
-
107
- member_count_position = {
108
- "left": extracted_data['left'][number_idx],
109
- "top": extracted_data['top'][number_idx],
110
- "width": extracted_data['width'][number_idx],
111
- "height": extracted_data['height'][number_idx],
112
- }
113
- break # Keluar dari loop jika semua elemen ditemukan
114
- else:
115
- return None
116
-
117
- if member_position is None:
118
  return None
119
-
120
- # Get background color for masking
121
- x = member_position['left'] + member_position['width'] + 100
122
- y = member_position['top'] + member_position['height'] - 100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  bg_color = image[y, x]
124
  rgb = (int(bg_color[0]), int(bg_color[1]), int(bg_color[2]))
125
-
126
- # Detect theme based on background color brightness
127
  r, g, b = float(bg_color[0]), float(bg_color[1]), float(bg_color[2])
128
  brightness = (r * 299 + g * 587 + b * 114) / 1000
129
  is_dark = brightness < 128
130
  theme = 'Dark Mode' if is_dark else 'Light Mode'
131
-
132
- # Set font color based on theme
133
  font_color = (145, 144, 144, 255) if is_dark else (90, 94, 95, 255)
134
-
135
- # Mask the original text areas with margin
136
- margin = 10 # Margin dalam pixel
137
-
138
- if group_position:
139
- cv2.rectangle(
140
- image,
141
- (group_position['left'] - margin, group_position['top'] - margin),
142
- (group_position['left'] + group_position['width'] + margin, group_position['top'] + group_position['height'] + margin),
143
- rgb,
144
- -1,
145
- )
146
-
147
- if split_position:
148
- cv2.rectangle(
149
- image,
150
- (split_position['left'] - margin, split_position['top'] - margin),
151
- (split_position['left'] + split_position['width'] + margin, split_position['top'] + split_position['height'] + margin),
152
- rgb,
153
- -1,
154
- )
155
-
156
- if member_position:
157
- cv2.rectangle(
158
- image,
159
- (member_position['left'] - margin, member_position['top'] - margin),
160
- (member_position['left'] + member_position['width'] + margin, member_position['top'] + member_position['height'] + margin),
161
- rgb,
162
- -1,
163
- )
164
-
165
- if member_count_position:
166
- cv2.rectangle(
167
- image,
168
- (member_count_position['left'] - margin, member_count_position['top'] - margin),
169
- (member_count_position['left'] + member_count_position['width'] + margin, member_count_position['top'] + member_count_position['height'] + margin),
170
- rgb,
171
- -1,
172
- )
173
-
174
- # Add new member count text
175
  updated_member_count = {
176
  'id': f"Grup 路 {anggota} anggota",
177
  'en': f"Group 路 {anggota} members"
178
- }.get(lang)
179
-
180
  original_height = member_count_position['height']
181
  original_width = member_count_position['width']
182
-
183
  font_size = int(original_height * 1.9)
184
- font = ImageFont.truetype(self.font_path, font_size)
185
-
186
  image_pil = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
187
  draw = ImageDraw.Draw(image_pil)
188
-
189
  min_size = int(original_height * 1.4)
190
  max_size = int(original_height * 2.3)
191
  max_iterations = 10
192
  iteration = 0
193
-
194
  while min_size <= max_size and iteration < max_iterations:
195
  font = ImageFont.truetype(self.font_path, font_size)
196
  text_bbox = draw.textbbox((0, 0), updated_member_count, font=font)
197
  text_height = text_bbox[3] - text_bbox[1]
198
  text_width = text_bbox[2] - text_bbox[0]
199
-
200
- if abs(text_height - original_height) <= 2 and text_width <= original_width * 1.5:
201
  break
202
-
203
- if text_height > original_height or text_width > original_width * 1.5:
204
  font_size = int(font_size * 0.95)
205
  else:
206
  font_size = int(font_size * 1.05)
207
-
208
  font_size = max(min_size, min(max_size, font_size))
209
  iteration += 1
210
-
211
- # Calculate center position
 
 
 
 
 
212
  text_bbox = draw.textbbox((0, 0), updated_member_count, font=font)
213
  text_width = text_bbox[2] - text_bbox[0]
214
  text_height = text_bbox[3] - text_bbox[1]
215
-
216
- # Calculate center position based on the masked area with margin
217
- center_x = (group_position['left'] - margin + member_position['left'] + member_position['width'] + margin) // 2
218
- center_y = (group_position['top'] - margin + member_position['top'] + member_position['height'] + margin) // 2
219
-
220
- # Adjust position to center the text
221
  text_x = center_x - (text_width // 2)
222
  text_y = center_y - (text_height // 2)
223
-
224
  draw.text((text_x, text_y), updated_member_count, font=font, fill=font_color)
225
  image = cv2.cvtColor(np.array(image_pil), cv2.COLOR_BGR2RGB)
226
-
227
  cv2.imwrite('output.png', image)
228
  if show_preview:
229
  cv2.imshow('Preview (Tekan q untuk keluar)', image)
@@ -243,7 +201,6 @@ if __name__ == '__main__':
243
  parser = argparse.ArgumentParser(description='Proses gambar grup iPhone')
244
  parser.add_argument('image_path', help='Path ke file gambar')
245
  parser.add_argument('anggota', help='Jumlah anggota')
246
-
247
  args = parser.parse_args()
248
  editor = IPhoneEditor()
249
  editor.process_image(args.image_path, args.anggota)
 
13
  def process_image(self, image_path, anggota):
14
  image = cv2.imread(image_path)
15
  if image is None:
16
+ print("Error: Could not read image")
17
  return
18
  result = self._process_core(image, anggota, show_preview=True)
19
  return result
 
25
  image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
26
  result = self._process_core(image, anggota, show_preview=False, return_theme=True)
27
  if result is None:
28
+ print("Error: _process_core returned None")
29
  return None, None
30
  result_image, theme = result
31
  if result_image is not None:
 
34
  pil_result.save(output_io, format='PNG')
35
  img_b64 = base64.b64encode(output_io.getvalue()).decode('utf-8')
36
  return img_b64, theme
37
+ print("Error: result_image is None")
38
  return None, None
39
  except Exception as e:
40
  print(f"Error in process_image_bytes: {str(e)}")
 
44
  try:
45
  extracted_data = pytesseract.image_to_data(image, output_type=pytesseract.Output.DICT)
46
  text_list = extracted_data['text']
47
+
48
+ # Cari semua pasangan angka + anggota/members/member
49
+ candidates = []
 
 
 
 
 
50
  for i, text in enumerate(text_list):
51
+ if text.isdigit():
52
+ for offset in [1,2]:
53
+ idx = i + offset
54
+ if idx < len(text_list):
55
+ next_text = text_list[idx].lower()
56
+ if next_text in ["anggota", "members", "member"]:
57
+ # Cari Grup/Group terdekat di atas
58
+ group_idx = None
59
+ for j in range(i-1, max(-1, i-10), -1):
60
+ if text_list[j] in ["Grup", "Group"]:
61
+ group_idx = j
62
+ break
63
+ # Cari split '-' di antara
64
+ split_idx = None
65
+ for j in range(group_idx+1 if group_idx is not None else i, i):
66
+ if text_list[j] == "-":
67
+ split_idx = j
68
+ break
69
+ # Simpan kandidat
70
+ candidates.append({
71
+ 'group_idx': group_idx,
72
+ 'split_idx': split_idx,
73
+ 'number_idx': i,
74
+ 'member_idx': idx
75
+ })
76
+ # Pilih kandidat dengan group_idx valid dan posisi vertikal berdekatan
77
+ best = None
78
+ min_dist = 1e9
79
+ for c in candidates:
80
+ if c['group_idx'] is not None:
81
+ y_group = extracted_data['top'][c['group_idx']]
82
+ y_member = extracted_data['top'][c['member_idx']]
83
+ dist = abs(y_group - y_member)
84
+ if dist < min_dist:
85
+ min_dist = dist
86
+ best = c
87
+ if not best:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  return None
89
+ group_idx = best['group_idx']
90
+ split_idx = best['split_idx']
91
+ number_idx = best['number_idx']
92
+ member_idx = best['member_idx']
93
+ lang = 'id' if text_list[group_idx] == "Grup" else 'en'
94
+ # Ambil posisi
95
+ group_position = {
96
+ "left": extracted_data['left'][group_idx],
97
+ "top": extracted_data['top'][group_idx],
98
+ "width": extracted_data['width'][group_idx],
99
+ "height": extracted_data['height'][group_idx],
100
+ }
101
+ member_position = {
102
+ "left": extracted_data['left'][member_idx],
103
+ "top": extracted_data['top'][member_idx],
104
+ "width": extracted_data['width'][member_idx],
105
+ "height": extracted_data['height'][member_idx],
106
+ }
107
+ member_count_position = {
108
+ "left": extracted_data['left'][number_idx],
109
+ "top": extracted_data['top'][number_idx],
110
+ "width": extracted_data['width'][number_idx],
111
+ "height": extracted_data['height'][number_idx],
112
+ }
113
+ split_position = None
114
+ if split_idx is not None:
115
+ split_position = {
116
+ "left": extracted_data['left'][split_idx],
117
+ "top": extracted_data['top'][split_idx],
118
+ "width": extracted_data['width'][split_idx],
119
+ "height": extracted_data['height'][split_idx],
120
+ }
121
+ # Ambil warna background di sekitar member_position
122
+ x = member_position['left'] + member_position['width'] + 10
123
+ y = member_position['top'] + member_position['height'] // 2
124
  bg_color = image[y, x]
125
  rgb = (int(bg_color[0]), int(bg_color[1]), int(bg_color[2]))
126
+ # Deteksi tema
 
127
  r, g, b = float(bg_color[0]), float(bg_color[1]), float(bg_color[2])
128
  brightness = (r * 299 + g * 587 + b * 114) / 1000
129
  is_dark = brightness < 128
130
  theme = 'Dark Mode' if is_dark else 'Light Mode'
 
 
131
  font_color = (145, 144, 144, 255) if is_dark else (90, 94, 95, 255)
132
+ margin = 10
133
+ # Masking area
134
+ for pos in [group_position, split_position, member_position, member_count_position]:
135
+ if pos:
136
+ cv2.rectangle(
137
+ image,
138
+ (pos['left'] - margin, pos['top'] - margin),
139
+ (pos['left'] + pos['width'] + margin, pos['top'] + pos['height'] + margin),
140
+ rgb,
141
+ -1,
142
+ )
143
+ # Teks baru
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  updated_member_count = {
145
  'id': f"Grup 路 {anggota} anggota",
146
  'en': f"Group 路 {anggota} members"
147
+ }.get(lang, f"Group 路 {anggota} members")
148
+ # Penyesuaian font size
149
  original_height = member_count_position['height']
150
  original_width = member_count_position['width']
 
151
  font_size = int(original_height * 1.9)
 
 
152
  image_pil = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
153
  draw = ImageDraw.Draw(image_pil)
 
154
  min_size = int(original_height * 1.4)
155
  max_size = int(original_height * 2.3)
156
  max_iterations = 10
157
  iteration = 0
 
158
  while min_size <= max_size and iteration < max_iterations:
159
  font = ImageFont.truetype(self.font_path, font_size)
160
  text_bbox = draw.textbbox((0, 0), updated_member_count, font=font)
161
  text_height = text_bbox[3] - text_bbox[1]
162
  text_width = text_bbox[2] - text_bbox[0]
163
+ if abs(text_height - original_height) <= 2 and text_width <= original_width * 2:
 
164
  break
165
+ if text_height > original_height or text_width > original_width * 2:
 
166
  font_size = int(font_size * 0.95)
167
  else:
168
  font_size = int(font_size * 1.05)
 
169
  font_size = max(min_size, min(max_size, font_size))
170
  iteration += 1
171
+ # Center posisi antara group dan member
172
+ top_y = min(group_position['top'], member_position['top']) - margin
173
+ bot_y = max(group_position['top'] + group_position['height'], member_position['top'] + member_position['height']) + margin
174
+ left_x = min(group_position['left'], member_position['left']) - margin
175
+ right_x = max(member_position['left'] + member_position['width'], group_position['left'] + group_position['width']) + margin
176
+ center_x = (left_x + right_x) // 2
177
+ center_y = (top_y + bot_y) // 2
178
  text_bbox = draw.textbbox((0, 0), updated_member_count, font=font)
179
  text_width = text_bbox[2] - text_bbox[0]
180
  text_height = text_bbox[3] - text_bbox[1]
 
 
 
 
 
 
181
  text_x = center_x - (text_width // 2)
182
  text_y = center_y - (text_height // 2)
 
183
  draw.text((text_x, text_y), updated_member_count, font=font, fill=font_color)
184
  image = cv2.cvtColor(np.array(image_pil), cv2.COLOR_BGR2RGB)
 
185
  cv2.imwrite('output.png', image)
186
  if show_preview:
187
  cv2.imshow('Preview (Tekan q untuk keluar)', image)
 
201
  parser = argparse.ArgumentParser(description='Proses gambar grup iPhone')
202
  parser.add_argument('image_path', help='Path ke file gambar')
203
  parser.add_argument('anggota', help='Jumlah anggota')
 
204
  args = parser.parse_args()
205
  editor = IPhoneEditor()
206
  editor.process_image(args.image_path, args.anggota)