File size: 4,525 Bytes
67ec2b5
d96b1f4
 
6a0e327
d96b1f4
c3ce727
2ffc79a
 
3637419
f935e33
2ffc79a
 
 
 
494421f
2ffc79a
f935e33
3637419
f935e33
19ab236
2ffc79a
 
 
 
 
 
 
 
 
 
 
9240a2b
2ffc79a
 
9240a2b
 
2ffc79a
9240a2b
 
 
2ffc79a
9240a2b
 
 
 
 
 
2ffc79a
9240a2b
 
 
 
6a0e327
 
 
2ffc79a
 
 
 
 
 
9240a2b
2ffc79a
6a0e327
 
 
 
9240a2b
2ffc79a
9240a2b
6a0e327
 
 
 
 
 
 
 
 
 
 
 
 
 
2ffc79a
 
6a0e327
9240a2b
6a0e327
 
 
9240a2b
2ffc79a
9240a2b
6a0e327
 
9240a2b
 
 
6a0e327
 
 
9240a2b
6a0e327
 
 
 
 
2ffc79a
6a0e327
2ffc79a
 
9240a2b
6a0e327
2ffc79a
6a0e327
 
9240a2b
 
1627a12
2ffc79a
6a0e327
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import gradio as gr
import cv2
import numpy as np
import matplotlib.pyplot as plt
import time
import os
from sklearn.cluster import MiniBatchKMeans
from PIL import Image
from transformers import ViTImageProcessor, ViTForImageClassification
import torch
from numba import jit, prange

# 设置环境变量以防止内存泄漏
os.environ["OMP_NUM_THREADS"] = "1"

# 加载预训练的 ViT 模型和图像处理器
model_name = "google/vit-base-patch16-224"
image_processor = ViTImageProcessor.from_pretrained(model_name)
model = ViTForImageClassification.from_pretrained(model_name)

@jit(nopython=True, parallel=True)
def rgb_to_gray_numba(image):
    """使用 Numba JIT 编译器将 RGB 图像转换为灰度图像"""
    h, w, _ = image.shape
    gray_image = np.empty((h, w), dtype=np.uint8)
    for i in prange(h):
        for j in prange(w):
            r, g, b = image[i, j]
            gray_image[i, j] = 0.2989 * r + 0.5870 * g + 0.1140 * b
    return gray_image

def create_color_palette(colors, size=100):
    """创建颜色调色板"""
    palette = np.zeros((4 * size, 4 * size, 3), dtype=np.uint8)
    for i in range(4):
        for j in range(4):
            palette[i * size:(i + 1) * size, j * size:(j + 1) * size] = colors[i * 4 + j]
    return palette

def identify_image(image):
    """识别图像中的对象"""
    inputs = image_processor(images=image, return_tensors="pt")
    with torch.no_grad():
        outputs = model(**inputs)
    logits = outputs.logits
    probabilities = torch.nn.functional.softmax(logits, dim=-1)[0]
    top_5 = torch.topk(probabilities, 5)

    results = []
    for i in range(5):
        label = model.config.id2label[top_5.indices[i].item()]
        score = top_5.values[i].item()
        results.append(f"{label}: {score:.2f}")
    
    return ", ".join(results)

def analyze_image(image):
    overall_start_time = time.time()
    times = {}

    # 0. 图像分类
    start_time = time.time()
    top_5_classes = identify_image(image)
    times['classification'] = f"{time.time() - start_time:.3f} seconds"

    # 将图像转换为 NumPy 数组以进行 OpenCV 操作
    image_np = np.array(image)

    # 1. 直方图
    start_time = time.time()
    gray_image = cv2.cvtColor(image_np, cv2.COLOR_RGB2GRAY)
    hist = cv2.calcHist([gray_image], [0], None, [256], [0, 256])
    hist = cv2.normalize(hist, hist).flatten()
    
    fig, ax = plt.subplots(figsize=(2.56, 1), dpi=100)
    ax.plot(hist, color='black')
    ax.set_xlim([0, 256])
    ax.set_ylim([0, 1])
    ax.axis('off')
    
    histogram_path = "histogram.png"
    plt.savefig(histogram_path, format='png', bbox_inches='tight', pad_inches=0)
    plt.close(fig)
    times['histogram'] = f"{time.time() - start_time:.3f} seconds"

    # 2. 边缘检测
    start_time = time.time()
    edges = cv2.Canny(gray_image, 100, 200)
    edges_path = "edges.png"
    cv2.imwrite(edges_path, edges)
    times['edge_detection'] = f"{time.time() - start_time:.3f} seconds"

    # 3. 主颜色提取(16种颜色)
    start_time = time.time()
    
    # 调整图像大小以加快处理速度
    small_image = cv2.resize(image_np, (100, 100))
    pixels = small_image.reshape((-1, 3))
    pixels = np.float32(pixels)

    # 使用 MiniBatchKMeans 代替 K-means
    kmeans = MiniBatchKMeans(n_clusters=16, batch_size=100, max_iter=10)
    kmeans.fit(pixels)
    colors = kmeans.cluster_centers_
    
    # 创建颜色调色板
    color_palette = create_color_palette(colors)
    palette_path = "palette.png"
    cv2.imwrite(palette_path, color_palette)
    times['main_colors'] = f"{time.time() - start_time:.3f} seconds"

    # 计算总体耗时
    overall_elapsed_time = time.time() - overall_start_time
    times['overall'] = f"{overall_elapsed_time:.3f} seconds"

    # 准备时间输出
    timing_output = "\n".join([f"{k}: {v}" for k, v in times.items()])

    return top_5_classes, histogram_path, edges_path, palette_path, timing_output

# 定义 Gradio 界面
interface = gr.Interface(
    fn=analyze_image,
    inputs=gr.Image(type="pil", label="上传图像"),
    outputs=[
        gr.Textbox(label="图像分类 (Top 5)"),
        gr.Image(label="灰度直方图"),
        gr.Image(label="边缘检测"),
        gr.Image(label="颜色调色板"),
        gr.Textbox(label="处理时间")
    ],
    title="高级图像分析",
    description="上传图像以分析其分类、直方图、边缘和主要颜色。",
    allow_flagging="never"
)

# 启动界面
interface.launch(share=True)