Huxxshadow commited on
Commit
3b01b55
·
verified ·
1 Parent(s): 6048622

Upload 4 files

Browse files
Files changed (4) hide show
  1. app_zh_private.py +130 -0
  2. color_quantization.py +61 -0
  3. pixelation.py +123 -0
  4. requirements.txt +4 -0
app_zh_private.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from color_quantization import (
3
+ kmeans_quantization,
4
+ median_cut_quantization,
5
+ floyd_steinberg_dithering,
6
+ median_cut_perceptual_weighting
7
+ )
8
+ from pixelation import pixelate_image, mosaic_pixelation, oil_paint_pixelation, hierarchical_pixelation
9
+ import math
10
+
11
+
12
+ # 定义像素化和颜色量化处理函数
13
+ def pixelate_and_quantize(image, pixel_size, n_colors, methods, interpolation, pixelation_types):
14
+ results = []
15
+
16
+ # 根据用户选择的像素化方法进行像素化处理
17
+ for pixelation_type in pixelation_types:
18
+ if pixelation_type == "Classic Nearest Neighbor":
19
+ pixelated_img = pixelate_image(image, pixel_size, interpolation)
20
+ elif pixelation_type == "Mosaic":
21
+ pixelated_img = mosaic_pixelation(image, pixel_size)
22
+ elif pixelation_type == "Oil Painting":
23
+ pixelated_img = oil_paint_pixelation(image, pixel_size)
24
+ elif pixelation_type == "Hierarchical":
25
+ pixelated_img = hierarchical_pixelation(image, pixel_size, pixel_size * 2)
26
+ else:
27
+ raise ValueError(f"未知的像素化方法: {pixelation_type}")
28
+
29
+ # 根据用户选择的量化方法进行颜色量化,并将量化后的图像添加到列表中
30
+ for method in methods:
31
+ if method == "K-Means":
32
+ quantized_img = kmeans_quantization(pixelated_img, n_colors)
33
+ elif method == "Median Cut":
34
+ quantized_img = median_cut_quantization(pixelated_img, n_colors)
35
+ elif method == "Floyd-Steinberg Dithering":
36
+ quantized_img = floyd_steinberg_dithering(pixelated_img, n_colors)
37
+ elif method == "Median Cut (Perceptual Weighting)":
38
+ quantized_img = median_cut_perceptual_weighting(pixelated_img, n_colors)
39
+ else:
40
+ raise ValueError(f"未知的量化方法: {method}")
41
+
42
+ # 只返回量化后的图像
43
+ results.append(quantized_img)
44
+
45
+ return results
46
+
47
+
48
+ # Gradio 用户界面
49
+ def gradio_interface():
50
+ with gr.Blocks(title="Image Pixelation Tool") as demo:
51
+ gr.Markdown("## 像素化图片工具 (AI像素修补)")
52
+ with gr.Row():
53
+ with gr.Column(scale=4):
54
+ gr.Markdown("""
55
+ 此工具提供了多种图像像素化效果和颜色量化算法,包括经典的邻近像素化、马赛克效果、油画效果以及层次像素化。
56
+ 用户可以根据需要选择不同的像素化方法并对图像进行颜色量化处理。
57
+
58
+ ### 许可协议(License)
59
+ 本工具基于 **MPL 2.0(Mozilla Public License 2.0)** 协议发布。该协议允许修改和分发源代码,且允许商业使用,前提是对源代码的修改部分仍需保持开源。
60
+
61
+ - **允许**:修改、分发、用于商业用途。
62
+ - **限制**:修改过的源代码必须继续保持开源。
63
+
64
+ [查看详细的 MPL 2.0 协议](https://www.mozilla.org/en-US/MPL/2.0/)
65
+
66
+ **注意:如需将本工具用于商业用途,请联系作者以获得进一步的授权。**
67
+
68
+ 联系方式:[email protected]
69
+
70
+ 版权所有 © 2024
71
+ """)
72
+ with gr.Column(scale=1):
73
+ gr.Image(value="https://gravatar.com/avatar/483611663515c5a569c10664f3abf78c8d01498febd864a3413ecc8fe01dd740.jpg?s=256", show_download_button=False,interactive=False,show_fullscreen_button=False)
74
+
75
+ with gr.Row():
76
+ with gr.Column():
77
+ image_input = gr.Image(type="pil", label="上传图片")
78
+
79
+ with gr.Column():
80
+ pixel_size_slider = gr.Slider(minimum=2, maximum=100, value=10, step=1, label="选择像素块大小")
81
+ color_slider = gr.Slider(minimum=2, maximum=128, value=16, step=1, label="选择颜色数量")
82
+
83
+ method_checkboxes = gr.CheckboxGroup(
84
+ choices=["K-Means", "Median Cut", "Floyd-Steinberg Dithering", "MedianCut(PerceptualWeighting)"],
85
+ value=["K-Means"],
86
+ label="选择颜色量化方法"
87
+ )
88
+ pixelation_checkboxes = gr.CheckboxGroup(
89
+ choices=["Classic Nearest Neighbor", "Mosaic", "Oil Painting", "Hierarchical"],
90
+ value=["Classic Nearest Neighbor"],
91
+ label="选择像素化方法"
92
+ )
93
+ interpolation_radio = gr.Radio(
94
+ choices=["Nearest", "Bilinear", "Bicubic", "Lanczos"],
95
+ value="Nearest",
96
+ label="选择插值方法(仅对Classic Nearest Neighbour有效)"
97
+ )
98
+
99
+ btn = gr.Button("生成像素化图片")
100
+
101
+ @gr.render(inputs=[image_input, pixel_size_slider, color_slider, method_checkboxes, interpolation_radio,
102
+ pixelation_checkboxes], triggers=[btn.click])
103
+ def show_pictures(img_input, pixel_size, n_colors, methods, interpolation, pixelation_types):
104
+ num_outputs = len(methods) * len(pixelation_types)
105
+ num_outputs = min(num_outputs, 16)
106
+ images = pixelate_and_quantize(img_input, pixel_size, n_colors, methods, interpolation, pixelation_types)
107
+ cols = math.ceil(math.sqrt(num_outputs))
108
+ rows = math.ceil(num_outputs / cols)
109
+ for i in range(rows):
110
+ single_row = gr.Row()
111
+ with single_row:
112
+ for j in range(cols):
113
+ single_col = gr.Column()
114
+ idx = i * cols + j
115
+ with single_col:
116
+ if idx < num_outputs:
117
+ # 计算当前的 pixelation 和 quantization 方法
118
+ current_pixelation = pixelation_types[idx // len(methods)]
119
+ current_method = methods[idx % len(methods)]
120
+ # 更新图片的标签,包含像素化方法和颜色量化方法
121
+ label = f"像素化: {current_pixelation}, 颜色量化: {current_method}"
122
+ gr.Image(images[idx], label=label, format="png")
123
+ idx += 1
124
+ return demo
125
+
126
+
127
+ # 启动 Gradio 界面
128
+ if __name__ == "__main__":
129
+ demo = gradio_interface()
130
+ demo.launch()
color_quantization.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image
2
+ from sklearn.cluster import KMeans
3
+ import numpy as np
4
+
5
+
6
+ # K-Means 颜色量化
7
+ def kmeans_quantization(image, n_colors):
8
+ img = image.convert("RGB")
9
+ img_np = np.array(img)
10
+ w, h, d = img_np.shape
11
+ img_flat = img_np.reshape((w * h, d))
12
+ kmeans = KMeans(n_clusters=n_colors, random_state=0).fit(img_flat)
13
+ centroids = kmeans.cluster_centers_.astype(int)
14
+ labels = kmeans.labels_
15
+ quantized_img_flat = centroids[labels]
16
+ quantized_img = quantized_img_flat.reshape((w, h, d))
17
+ return Image.fromarray(np.uint8(quantized_img))
18
+
19
+
20
+ # Median Cut 颜色量化
21
+ def median_cut_quantization(image, n_colors):
22
+ quantized_img = image.convert("P", palette=Image.ADAPTIVE, colors=n_colors)
23
+ return quantized_img.convert("RGB")
24
+
25
+
26
+ # Floyd-Steinberg Dithering
27
+ def floyd_steinberg_dithering(image, n_colors):
28
+ quantized_img = image.convert("P", palette=Image.ADAPTIVE, colors=n_colors)
29
+ return quantized_img.convert("RGB")
30
+
31
+
32
+ # Median Cut with Perceptual Weighting 颜色量化
33
+ def median_cut_perceptual_weighting(image, n_colors):
34
+ """
35
+ 使用感知加权的 Median Cut 颜色量化。
36
+
37
+ 参数:
38
+ - image: 输入的 PIL 图像对象
39
+ - n_colors: 目标颜色数量
40
+
41
+ 返回:
42
+ - 量化后的 PIL 图像对象
43
+ """
44
+ img = image.convert("RGB")
45
+
46
+ # 定义 RGB 通道的感知加权
47
+ perceptual_weights = np.array([0.299, 0.587, 0.114])
48
+
49
+ # 将图像转为 numpy 数组
50
+ img_np = np.array(img)
51
+
52
+ # 计算加权后的颜色距离
53
+ weighted_img_np = img_np.astype(float)
54
+ for i in range(3): # 对 R, G, B 通道分别加权
55
+ weighted_img_np[:, :, i] *= perceptual_weights[i]
56
+
57
+ # 使用 Pillow 的 Median Cut 算法进行基于加权的颜色量化
58
+ weighted_image = Image.fromarray(np.uint8(img_np)) # 不对图像像素值进行改变
59
+ quantized_img = weighted_image.convert("P", palette=Image.ADAPTIVE, colors=n_colors)
60
+
61
+ return quantized_img.convert("RGB")
pixelation.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image
2
+ import numpy as np
3
+ from collections import Counter
4
+
5
+ def pixelate_image(image, pixel_size, interpolation):
6
+ """
7
+ 对图像进行像素化。
8
+
9
+ 参数:
10
+ - image: 输入的 PIL 图像对象
11
+ - pixel_size: 像素块大小
12
+ - interpolation: 插值方法 ("Nearest", "Bilinear", "Bicubic", "Lanczos")
13
+
14
+ 返回:
15
+ - 像素化后的 PIL 图像对象
16
+ """
17
+ # 将输入图像转为 RGB 模式
18
+ img = image.convert("RGB")
19
+
20
+ # 获取原图像的尺寸
21
+ width, height = img.size
22
+
23
+ # 选择插值方式
24
+ if interpolation == "Nearest":
25
+ resample_method = Image.NEAREST
26
+ elif interpolation == "Bilinear":
27
+ resample_method = Image.BILINEAR
28
+ elif interpolation == "Bicubic":
29
+ resample_method = Image.BICUBIC
30
+ elif interpolation == "Lanczos":
31
+ resample_method = Image.LANCZOS
32
+ else:
33
+ raise ValueError(f"未知的插值方法: {interpolation}")
34
+
35
+ # 第一步:缩小图像,使用邻近插值保持像素块的正方形效果
36
+ small_img = img.resize(
37
+ (width // pixel_size, height // pixel_size),
38
+ resample=resample_method
39
+ )
40
+
41
+ # 第二步:放大图像,使用用户选择的插值方法
42
+ pixelated_img = small_img.resize(
43
+ (width, height),
44
+ resample=resample_method
45
+ )
46
+
47
+ return pixelated_img
48
+
49
+
50
+ def mosaic_pixelation(image, pixel_size):
51
+ """
52
+ 使用马赛克方法对图像进行像素化。
53
+
54
+ 参数:
55
+ - image: 输入的 PIL 图像对象
56
+ - pixel_size: 像素块大小
57
+
58
+ 返回:
59
+ - 马赛克效果的 PIL 图像对象
60
+ """
61
+ img = image.convert("RGB")
62
+ img_np = np.array(img)
63
+ h, w, _ = img_np.shape
64
+
65
+ for y in range(0, h, pixel_size):
66
+ for x in range(0, w, pixel_size):
67
+ block = img_np[y:y + pixel_size, x:x + pixel_size]
68
+ mean_color = block.mean(axis=(0, 1)).astype(int)
69
+ img_np[y:y + pixel_size, x:x + pixel_size] = mean_color
70
+
71
+ return Image.fromarray(img_np)
72
+
73
+
74
+ def oil_paint_pixelation(image, pixel_size):
75
+ """
76
+ 使用油画滤镜方法对图像进行像素化。
77
+
78
+ 参数:
79
+ - image: 输入的 PIL 图像对象
80
+ - pixel_size: 像素块大小
81
+
82
+ 返回:
83
+ - 油画滤镜效果的 PIL 图像对象
84
+ """
85
+ img = image.convert("RGB")
86
+ img_np = np.array(img)
87
+ h, w, _ = img_np.shape
88
+
89
+ for y in range(0, h, pixel_size):
90
+ for x in range(0, w, pixel_size):
91
+ block = img_np[y:y + pixel_size, x:x + pixel_size]
92
+ block_colors = [tuple(color) for color in block.reshape(-1, 3)]
93
+ most_common_color = Counter(block_colors).most_common(1)[0][0]
94
+ img_np[y:y + pixel_size, x:x + pixel_size] = most_common_color
95
+
96
+ return Image.fromarray(img_np)
97
+
98
+
99
+ def hierarchical_pixelation(image, min_pixel_size, max_pixel_size):
100
+ """
101
+ 使用层次像素化方法对图像进行像素化。
102
+
103
+ 参数:
104
+ - image: 输入的 PIL 图像对象
105
+ - min_pixel_size: 最小像素块大小
106
+ - max_pixel_size: 最大像素块大小
107
+
108
+ 返回:
109
+ - 层次像素化效果的 PIL 图像对象
110
+ """
111
+ img = image.convert("RGB")
112
+ img_np = np.array(img)
113
+ h, w, _ = img_np.shape
114
+ step = max((max_pixel_size - min_pixel_size) // (w // min_pixel_size), 1)
115
+
116
+ for pixel_size in range(min_pixel_size, max_pixel_size + 1, step):
117
+ for y in range(0, h, pixel_size):
118
+ for x in range(0, w, pixel_size):
119
+ block = img_np[y:y + pixel_size, x:x + pixel_size]
120
+ mean_color = block.mean(axis=(0, 1)).astype(int)
121
+ img_np[y:y + pixel_size, x:x + pixel_size] = mean_color
122
+
123
+ return Image.fromarray(img_np)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio==4.44.0
2
+ numpy==2.0.2
3
+ pillow==10.4.0
4
+ scikit-learn==1.5.2