ImgAnalysis / app.py
Cookiesukaze's picture
Update app.py
c3ce727 verified
Raw History Blame Contribute Delete
4.53 kB
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)