imgboost-ai 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,257 @@
1
+ import cv2
2
+ import numpy as np
3
+ from skimage import exposure
4
+
5
+
6
+ class ImageFilters:
7
+ """
8
+ Filtros e melhorias de imagem usando OpenCV.
9
+ """
10
+
11
+ def __init__(self, denoise_strength=10, contrast_clip=3.0):
12
+ """
13
+ Inicializa os filtros.
14
+
15
+ Args:
16
+ denoise_strength: Força do denoise (0-30)
17
+ contrast_clip: Intensidade do CLAHE (1.0-5.0)
18
+ """
19
+ self.denoise_strength = denoise_strength
20
+ self.contrast_clip = contrast_clip
21
+
22
+ def denoise(self, img, strength=None):
23
+ """
24
+ Remove ruído da imagem.
25
+
26
+ Args:
27
+ img: Imagem BGR
28
+ strength: Força do denoise (sobrescreve padrão)
29
+
30
+ Returns:
31
+ Imagem com ruído reduzido
32
+ """
33
+ if strength is None:
34
+ strength = self.denoise_strength
35
+
36
+ # Converter para o tipo correto se necessário
37
+ if img.dtype != np.uint8:
38
+ img = img.astype(np.uint8)
39
+
40
+ if len(img.shape) == 3:
41
+ # Imagem colorida
42
+ return cv2.fastNlMeansDenoisingColored(
43
+ img, None,
44
+ h=strength,
45
+ hColor=strength,
46
+ templateWindowSize=7,
47
+ searchWindowSize=21
48
+ )
49
+ else:
50
+ # Imagem em escala de cinza
51
+ return cv2.fastNlMeansDenoising(
52
+ img, None,
53
+ h=strength,
54
+ templateWindowSize=7,
55
+ searchWindowSize=21
56
+ )
57
+
58
+ def enhance_contrast(self, img):
59
+ """
60
+ Melhora o contraste usando CLAHE (Contrast Limited Adaptive Histogram Equalization).
61
+
62
+ Args:
63
+ img: Imagem BGR
64
+
65
+ Returns:
66
+ Imagem com contraste melhorado
67
+ """
68
+ # Converter para LAB
69
+ lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
70
+ l, a, b = cv2.split(lab)
71
+
72
+ # Aplicar CLAHE no canal L
73
+ clahe = cv2.createCLAHE(
74
+ clipLimit=self.contrast_clip,
75
+ tileGridSize=(8, 8)
76
+ )
77
+ cl = clahe.apply(l)
78
+
79
+ # Recombinar canais
80
+ limg = cv2.merge((cl, a, b))
81
+
82
+ # Converter de volta para BGR
83
+ return cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)
84
+
85
+ def sharpen(self, img, strength=1.0):
86
+ """
87
+ Aplica sharpening na imagem.
88
+
89
+ Args:
90
+ img: Imagem BGR
91
+ strength: Intensidade do sharpen (0.5-2.0)
92
+
93
+ Returns:
94
+ Imagem com sharpen aplicado
95
+ """
96
+ # Kernel de sharpen
97
+ kernel = np.array([
98
+ [-1, -1, -1],
99
+ [-1, 9, -1],
100
+ [-1, -1, -1]
101
+ ]) * strength / 9
102
+
103
+ kernel[1, 1] = 1 + (8 * strength / 9)
104
+
105
+ return cv2.filter2D(img, -1, kernel)
106
+
107
+ def unsharp_mask(self, img, sigma=1.0, strength=1.5):
108
+ """
109
+ Aplica unsharp mask para sharpening mais refinado.
110
+
111
+ Args:
112
+ img: Imagem BGR
113
+ sigma: Tamanho do blur
114
+ strength: Intensidade do efeito
115
+
116
+ Returns:
117
+ Imagem com unsharp mask aplicado
118
+ """
119
+ # Criar versão borrada
120
+ blurred = cv2.GaussianBlur(img, (0, 0), sigma)
121
+
122
+ # Sharpened = Original + (Original - Blurred) * strength
123
+ sharpened = cv2.addWeighted(img, 1.0 + strength, blurred, -strength, 0)
124
+
125
+ return sharpened
126
+
127
+ def enhance_dark_ui(self, img):
128
+ """
129
+ Otimiza imagens de interfaces escuras (WhatsApp Dark, etc).
130
+
131
+ Args:
132
+ img: Imagem BGR
133
+
134
+ Returns:
135
+ Imagem otimizada
136
+ """
137
+ # Converter para LAB
138
+ lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
139
+ l, a, b = cv2.split(lab)
140
+
141
+ # Ajuste de gamma para realçar áreas escuras
142
+ gamma = 0.8
143
+ l = self._adjust_gamma(l, gamma)
144
+
145
+ # CLAHE mais agressivo
146
+ clahe = cv2.createCLAHE(clipLimit=4.0, tileGridSize=(8, 8))
147
+ l = clahe.apply(l)
148
+
149
+ # Recombinar
150
+ limg = cv2.merge((l, a, b))
151
+ img = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)
152
+
153
+ # Redução seletiva de ruído (menor que normal para não perder detalhes)
154
+ img = cv2.fastNlMeansDenoisingColored(img, None, 5, 5, 7, 21)
155
+
156
+ return img
157
+
158
+ def adjust_brightness_contrast(self, img, brightness=0, contrast=0):
159
+ """
160
+ Ajusta brilho e contraste.
161
+
162
+ Args:
163
+ img: Imagem BGR
164
+ brightness: Ajuste de brilho (-100 a 100)
165
+ contrast: Ajuste de contraste (-100 a 100)
166
+
167
+ Returns:
168
+ Imagem ajustada
169
+ """
170
+ if brightness != 0:
171
+ if brightness > 0:
172
+ shadow = brightness
173
+ highlight = 255
174
+ else:
175
+ shadow = 0
176
+ highlight = 255 + brightness
177
+ alpha_b = (highlight - shadow) / 255
178
+ gamma_b = shadow
179
+
180
+ img = cv2.addWeighted(img, alpha_b, img, 0, gamma_b)
181
+
182
+ if contrast != 0:
183
+ f = 131 * (contrast + 127) / (127 * (131 - contrast))
184
+ alpha_c = f
185
+ gamma_c = 127 * (1 - f)
186
+
187
+ img = cv2.addWeighted(img, alpha_c, img, 0, gamma_c)
188
+
189
+ return img
190
+
191
+ def _adjust_gamma(self, img, gamma=1.0):
192
+ """
193
+ Ajusta gamma da imagem.
194
+
195
+ Args:
196
+ img: Imagem em escala de cinza
197
+ gamma: Valor de gamma
198
+
199
+ Returns:
200
+ Imagem com gamma ajustado
201
+ """
202
+ inv_gamma = 1.0 / gamma
203
+ table = np.array([
204
+ ((i / 255.0) ** inv_gamma) * 255
205
+ for i in range(256)
206
+ ]).astype("uint8")
207
+
208
+ return cv2.LUT(img, table)
209
+
210
+ def enhance_edges(self, img):
211
+ """
212
+ Realça bordas na imagem.
213
+
214
+ Args:
215
+ img: Imagem BGR
216
+
217
+ Returns:
218
+ Imagem com bordas realçadas
219
+ """
220
+ # Converter para escala de cinza
221
+ gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
222
+
223
+ # Detectar bordas
224
+ edges = cv2.Canny(gray, 100, 200)
225
+
226
+ # Dilatar bordas
227
+ kernel = np.ones((2, 2), np.uint8)
228
+ edges = cv2.dilate(edges, kernel, iterations=1)
229
+
230
+ # Converter bordas para BGR
231
+ edges_bgr = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)
232
+
233
+ # Adicionar bordas à imagem original
234
+ enhanced = cv2.addWeighted(img, 0.9, edges_bgr, 0.1, 0)
235
+
236
+ return enhanced
237
+
238
+ def auto_white_balance(self, img):
239
+ """
240
+ Balanço automático de branco.
241
+
242
+ Args:
243
+ img: Imagem BGR
244
+
245
+ Returns:
246
+ Imagem com balanço de branco corrigido
247
+ """
248
+ result = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
249
+ avg_a = np.average(result[:, :, 1])
250
+ avg_b = np.average(result[:, :, 2])
251
+
252
+ result[:, :, 1] = result[:, :, 1] - ((avg_a - 128) * (result[:, :, 0] / 255.0) * 1.1)
253
+ result[:, :, 2] = result[:, :, 2] - ((avg_b - 128) * (result[:, :, 0] / 255.0) * 1.1)
254
+
255
+ result = cv2.cvtColor(result, cv2.COLOR_LAB2BGR)
256
+
257
+ return result
@@ -0,0 +1,252 @@
1
+ import cv2
2
+ import numpy as np
3
+ import warnings
4
+
5
+
6
+ class SuperResolution:
7
+ """
8
+ Processador de super-resolução para upscaling de imagens.
9
+
10
+ Nota: Para usar modelos de IA como Real-ESRGAN, você precisa baixar
11
+ os pesos do modelo separadamente. Esta implementação usa upscaling
12
+ de alta qualidade do OpenCV como fallback.
13
+ """
14
+
15
+ def __init__(self, use_ai=False, model_path=None):
16
+ """
17
+ Inicializa o processador de super-resolução.
18
+
19
+ Args:
20
+ use_ai: Tentar usar modelos de IA (Real-ESRGAN)
21
+ model_path: Caminho para os pesos do modelo
22
+ """
23
+ self.use_ai = use_ai
24
+ self.model_path = model_path
25
+ self.ai_model = None
26
+
27
+ if use_ai:
28
+ self._init_ai_model()
29
+
30
+ def _init_ai_model(self):
31
+ """Inicializa modelo de IA se disponível."""
32
+ try:
33
+ # Tentar importar Real-ESRGAN
34
+ from basicsr.archs.rrdbnet_arch import RRDBNet
35
+ import torch
36
+
37
+ # Configurar modelo
38
+ self.ai_model = RRDBNet(
39
+ num_in_ch=3,
40
+ num_out_ch=3,
41
+ num_feat=64,
42
+ num_block=23,
43
+ num_grow_ch=32,
44
+ scale=4
45
+ )
46
+
47
+ # Carregar pesos se disponível
48
+ if self.model_path and torch.cuda.is_available():
49
+ self.ai_model.load_state_dict(torch.load(self.model_path))
50
+ self.ai_model.eval()
51
+ self.ai_model = self.ai_model.cuda()
52
+ else:
53
+ warnings.warn(
54
+ "Modelo de IA não configurado. Usando upscaling tradicional."
55
+ )
56
+ self.ai_model = None
57
+
58
+ except ImportError:
59
+ warnings.warn(
60
+ "Dependências de IA não encontradas. Instale: pip install basicsr realesrgan"
61
+ )
62
+ self.ai_model = None
63
+
64
+ def upscale(self, img, scale=2):
65
+ """
66
+ Aumenta resolução da imagem.
67
+
68
+ Args:
69
+ img: Imagem BGR
70
+ scale: Fator de escala (2, 4, 8)
71
+
72
+ Returns:
73
+ Imagem com resolução aumentada
74
+ """
75
+ if self.ai_model is not None:
76
+ return self._upscale_with_ai(img, scale)
77
+ else:
78
+ return self._upscale_traditional(img, scale)
79
+
80
+ def _upscale_with_ai(self, img, scale):
81
+ """
82
+ Upscale usando modelo de IA (Real-ESRGAN).
83
+
84
+ Args:
85
+ img: Imagem BGR
86
+ scale: Fator de escala
87
+
88
+ Returns:
89
+ Imagem upscaled
90
+ """
91
+ try:
92
+ import torch
93
+
94
+ # Converter para tensor
95
+ img_tensor = torch.from_numpy(
96
+ np.transpose(img, (2, 0, 1))
97
+ ).float().div(255).unsqueeze(0)
98
+
99
+ if torch.cuda.is_available():
100
+ img_tensor = img_tensor.cuda()
101
+
102
+ # Inferência
103
+ with torch.no_grad():
104
+ output = self.ai_model(img_tensor)
105
+
106
+ # Converter de volta para numpy
107
+ output = output.squeeze().cpu().numpy()
108
+ output = np.transpose(output, (1, 2, 0))
109
+ output = (output * 255).clip(0, 255).astype(np.uint8)
110
+
111
+ return output
112
+
113
+ except Exception as e:
114
+ warnings.warn(f"Erro no upscale com IA: {e}. Usando método tradicional.")
115
+ return self._upscale_traditional(img, scale)
116
+
117
+ def _upscale_traditional(self, img, scale):
118
+ """
119
+ Upscale usando interpolação de alta qualidade.
120
+
121
+ Args:
122
+ img: Imagem BGR
123
+ scale: Fator de escala
124
+
125
+ Returns:
126
+ Imagem upscaled
127
+ """
128
+ height, width = img.shape[:2]
129
+ new_width = int(width * scale)
130
+ new_height = int(height * scale)
131
+
132
+ # LANCZOS4 é a melhor interpolação para upscaling
133
+ upscaled = cv2.resize(
134
+ img,
135
+ (new_width, new_height),
136
+ interpolation=cv2.INTER_LANCZOS4
137
+ )
138
+
139
+ # Aplicar unsharp mask para recuperar detalhes
140
+ upscaled = self._unsharp_mask(upscaled, sigma=1.0, strength=0.5)
141
+
142
+ return upscaled
143
+
144
+ def _unsharp_mask(self, img, sigma=1.0, strength=0.5):
145
+ """
146
+ Aplica unsharp mask para melhorar nitidez.
147
+
148
+ Args:
149
+ img: Imagem BGR
150
+ sigma: Tamanho do blur
151
+ strength: Intensidade
152
+
153
+ Returns:
154
+ Imagem com sharpen aplicado
155
+ """
156
+ blurred = cv2.GaussianBlur(img, (0, 0), sigma)
157
+ sharpened = cv2.addWeighted(img, 1.0 + strength, blurred, -strength, 0)
158
+ return sharpened
159
+
160
+ def upscale_smart(self, img, target_width=None, target_height=None):
161
+ """
162
+ Upscale inteligente para dimensão alvo.
163
+
164
+ Args:
165
+ img: Imagem BGR
166
+ target_width: Largura alvo (opcional)
167
+ target_height: Altura alvo (opcional)
168
+
169
+ Returns:
170
+ Imagem redimensionada
171
+ """
172
+ height, width = img.shape[:2]
173
+
174
+ if target_width and target_height:
175
+ new_width = target_width
176
+ new_height = target_height
177
+ elif target_width:
178
+ ratio = target_width / width
179
+ new_width = target_width
180
+ new_height = int(height * ratio)
181
+ elif target_height:
182
+ ratio = target_height / height
183
+ new_height = target_height
184
+ new_width = int(width * ratio)
185
+ else:
186
+ return img
187
+
188
+ # Calcular escala
189
+ scale = max(new_width / width, new_height / height)
190
+
191
+ if scale > 1:
192
+ # Upscaling
193
+ return self.upscale(img, scale=int(np.ceil(scale)))
194
+ else:
195
+ # Downscaling - usar INTER_AREA
196
+ return cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_AREA)
197
+
198
+ def multi_scale_enhance(self, img):
199
+ """
200
+ Melhoria multi-escala para preservar detalhes.
201
+
202
+ Args:
203
+ img: Imagem BGR
204
+
205
+ Returns:
206
+ Imagem melhorada
207
+ """
208
+ # Criar pirâmide gaussiana
209
+ pyramid = [img]
210
+ for i in range(3):
211
+ pyramid.append(cv2.pyrDown(pyramid[-1]))
212
+
213
+ # Reconstruir com detalhes preservados
214
+ result = pyramid[-1]
215
+ for i in range(len(pyramid) - 2, -1, -1):
216
+ result = cv2.pyrUp(result)
217
+ # Ajustar tamanho se necessário
218
+ if result.shape[:2] != pyramid[i].shape[:2]:
219
+ result = cv2.resize(result, (pyramid[i].shape[1], pyramid[i].shape[0]))
220
+ # Mesclar com detalhes
221
+ result = cv2.addWeighted(result, 0.6, pyramid[i], 0.4, 0)
222
+
223
+ return result
224
+
225
+ def enhance_texture(self, img):
226
+ """
227
+ Realça texturas após upscaling.
228
+
229
+ Args:
230
+ img: Imagem BGR
231
+
232
+ Returns:
233
+ Imagem com texturas realçadas
234
+ """
235
+ # Converter para LAB
236
+ lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
237
+ l, a, b = cv2.split(lab)
238
+
239
+ # Realçar detalhes finos no canal L
240
+ kernel = np.array([
241
+ [0, -1, 0],
242
+ [-1, 5, -1],
243
+ [0, -1, 0]
244
+ ]) / 5.0
245
+
246
+ l_enhanced = cv2.filter2D(l, -1, kernel)
247
+
248
+ # Recombinar
249
+ lab_enhanced = cv2.merge([l_enhanced, a, b])
250
+ result = cv2.cvtColor(lab_enhanced, cv2.COLOR_LAB2BGR)
251
+
252
+ return result
@@ -0,0 +1,7 @@
1
+ """
2
+ Módulo de utilitários.
3
+ """
4
+
5
+ from .image_io import ImageIO
6
+
7
+ __all__ = ['ImageIO']