Python去除琼脂平板图像中类菌落噪声的预处理技术咨询
琼脂平板图像去噪与菌落计数优化方案
针对你遇到的“噪声与菌落形态相似,传统滤波/形态学操作无效”的问题,推荐以下几种Python实现的针对性方法:
1. 自适应阈值分割+连通域面积过滤
虽然噪声和菌落形态相似,但多数情况下噪声的面积远小于真实菌落。结合自适应阈值分割(应对光照不均)+ 连通域面积过滤,可以精准剔除小噪声:
import cv2 import numpy as np # 读取图像 img = cv2.imread("Or1Om.png", cv2.IMREAD_GRAYSCALE) # 自适应阈值分割(高斯加权) thresh = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 寻找连通域 num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh, connectivity=8) # 过滤小连通域(根据实际菌落大小调整面积阈值,比如这里设为50) min_area = 50 filtered_img = np.zeros_like(thresh) for i in range(1, num_labels): # 跳过背景(标签0) if stats[i, cv2.CC_STAT_AREA] >= min_area: filtered_img[labels == i] = 255 # 显示结果 cv2.imshow("Filtered Result", filtered_img) cv2.waitKey(0)
注:面积阈值需要根据你的实际图像调整,可通过统计真实菌落的最小面积确定。
2. 非局部均值去噪(Non-Local Means Denoising)
传统滤波只考虑局部邻域,非局部均值通过寻找图像中相似的像素块进行加权平均,对与菌落形态相似但分布零散的噪声效果更好:
import cv2 img = cv2.imread("Or1Om.png", cv2.IMREAD_GRAYSCALE) # 非局部均值去噪(参数调整:h越大去噪越强,可能模糊菌落;templateWindowSize和searchWindowSize按需调整) denoised_img = cv2.fastNlMeansDenoising(img, h=10, templateWindowSize=7, searchWindowSize=21) # 后续可结合阈值分割提取菌落 thresh = cv2.threshold(denoised_img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] cv2.imshow("Non-Local Means Denoising", thresh) cv2.waitKey(0)
建议先调整h值,找到去噪效果和菌落清晰度的平衡点。
3. 帧间时序分析去噪
由于是延时拍摄,真实菌落会随时间生长(面积/形态变化),而噪声在多帧中基本无变化。可以利用多帧差分或帧间一致性过滤噪声:
import cv2 import numpy as np # 假设读取3帧延时图像(实际可根据你的序列调整) frame1 = cv2.imread("frame1.png", cv2.IMREAD_GRAYSCALE) frame2 = cv2.imread("frame2.png", cv2.IMREAD_GRAYSCALE) frame3 = cv2.imread("frame3.png", cv2.IMREAD_GRAYSCALE) # 计算帧间差异 diff1 = cv2.absdiff(frame1, frame2) diff2 = cv2.absdiff(frame2, frame3) # 取两帧差异的交集(只保留连续变化的区域,即菌落) stable_diff = cv2.bitwise_and(diff1, diff2) # 阈值化后过滤小区域 thresh = cv2.threshold(stable_diff, 20, 255, cv2.THRESH_BINARY)[1] num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh, connectivity=8) filtered = np.zeros_like(thresh) min_area = 30 for i in range(1, num_labels): if stats[i, cv2.CC_STAT_AREA] >= min_area: filtered[labels == i] = 255 cv2.imshow("Temporal Denoising", filtered) cv2.waitKey(0)
这种方法能从根源上区分“静态噪声”和“动态生长的菌落”,是延时图像的特有优势。
4. 小样本深度学习分割(U-Net)
如果上述传统方法仍无效,可尝试用U-Net训练一个小型分割模型,仅需标注少量图像即可精准区分菌落和噪声:
# 示例用Keras实现简易U-Net(需提前准备标注数据) from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D, concatenate def build_unet(input_size=(256,256,1)): inputs = Input(input_size) # 编码器 c1 = Conv2D(16, (3,3), activation='relu', padding='same')(inputs) c1 = Conv2D(16, (3,3), activation='relu', padding='same')(c1) p1 = MaxPooling2D((2,2))(c1) # 解码器 u2 = UpSampling2D((2,2))(p1) u2 = concatenate([u2, c1]) c2 = Conv2D(16, (3,3), activation='relu', padding='same')(u2) c2 = Conv2D(16, (3,3), activation='relu', padding='same')(c2) outputs = Conv2D(1, (1,1), activation='sigmoid')(c2) model = Model(inputs=[inputs], outputs=[outputs]) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) return model # 训练(需替换为你的数据加载逻辑) model = build_unet() # model.fit(train_images, train_masks, epochs=20, batch_size=8) # 预测 # test_img = cv2.imread("Or1Om.png", cv2.IMREAD_GRAYSCALE)/255.0 # test_img = np.expand_dims(test_img, axis=(0,-1)) # pred_mask = model.predict(test_img)[0,:,:,0] # pred_mask = (pred_mask > 0.5).astype(np.uint8)*255
这种方法对形态高度相似的噪声/目标区分度最高,适合复杂场景。
内容的提问来源于stack exchange,提问作者Keshav Todi
相关产品推荐
相关产品推荐

