QC / app.py
xiaoming32236046's picture
Update app.py
96ac448 verified
import numpy as np
import cv2
import matplotlib.pyplot as plt
import gradio as gr
import tempfile
import os
from PIL import Image, ImageDraw
def calculate_snr(channel, rois):
signal_mask = np.zeros(channel.shape, np.uint8)
for roi in rois:
cv2.fillPoly(signal_mask, [np.array(roi)], 255)
signal = cv2.bitwise_and(channel, channel, mask=signal_mask)
background_mask = cv2.bitwise_not(signal_mask)
background = cv2.bitwise_and(channel, channel, mask=background_mask)
signal_mean = np.mean(signal[signal_mask == 255])
background_std = np.std(background[background_mask == 255])
snr = signal_mean / background_std if background_std != 0 else float('inf')
return signal_mean, background_std, snr, signal, background
def process_image(image, roi_sketch):
if image is None or roi_sketch is None:
return None, None
# Convert sketch to binary mask
mask = np.array(roi_sketch)
_, binary_mask = cv2.threshold(mask, 1, 255, cv2.THRESH_BINARY)
# Find contours in the binary mask
contours, _ = cv2.findContours(binary_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Convert contours to list of ROIs
rois = [contour.squeeze().tolist() for contour in contours if len(contour) > 2]
# Convert image to numpy array
img_array = np.array(image)
if len(img_array.shape) == 2:
channels = [img_array]
channel_names = ['灰度']
else:
channels = cv2.split(img_array)
channel_names = ['Red', 'Green', 'Blue']
results = []
plt.figure(figsize=(5*len(channels), 10))
for i, (channel, name) in enumerate(zip(channels, channel_names)):
signal_mean, background_std, snr, signal, background = calculate_snr(channel, rois)
results.append(f"{name} channel:\n"
f"信号平均强度(Signal): {signal_mean:.2f}\n"
f"背景标准差(Noise): {background_std:.2f}\n"
f"信噪比(SNR): {snr:.2f}\n")
plt.subplot(2, len(channels), i+1)
plt.imshow(signal, cmap='gray')
plt.title(f'{name} Signal ROI')
plt.subplot(2, len(channels), i+1+len(channels))
plt.imshow(background, cmap='gray')
plt.title(f'{name} Background ROI')
result_filename = tempfile.mktemp(suffix='.png')
plt.savefig(result_filename)
plt.close()
return ("\n".join(results), result_filename)
with gr.Blocks() as demo:
gr.Markdown("# 图像SNR计算器")
gr.Markdown("上传一张图像,在第二个框中绘制多个感兴趣区域,结果会实时更新。支持单通道和多通道图像。")
with gr.Row():
input_image = gr.Image(label="上传图像", type="numpy")
roi_sketch = gr.Sketchpad(label="绘制ROI", type="numpy", shape=(256, 256))
with gr.Row():
result_text = gr.Textbox(label="结果")
result_image = gr.Image(label="ROI 图像")
inputs = [input_image, roi_sketch]
outputs = [result_text, result_image]
input_image.change(process_image, inputs=inputs, outputs=outputs)
roi_sketch.change(process_image, inputs=inputs, outputs=outputs)
demo.launch()