import matplotlib import matplotlib.pyplot as plt matplotlib.use('TkAgg') from plantcv import plantcv as pcv import numpy as np import cv2 def process_images_background(full_bil_path, mask, outdir='None', debug="None"): # 初始化参数 class options: def __init__(self): self.image = full_bil_path # 输入的光谱图像路径 self.debug = debug # 设置调试模式:'plot' 或 'print' self.writeimg = False # 是否保存图片 self.result = outdir # 输出结果文件路径 self.outdir = outdir # 输出文件夹路径 args = options() # 设置 PlantCV 的全局参数 pcv.params.debug = args.debug pcv.params.dpi = 100 # 设置 DPI pcv.params.text_size = 1 # 文本大小 pcv.params.text_thickness = 1 # 文本粗细 # 读取光谱图像(ENVI 格式) spectral_array = pcv.readimage(filename=args.image, mode='envi') bath_100 = spectral_array.array_data[:, :, 100] bath_over = pcv.threshold.binary(gray_img=bath_100, threshold=5500, object_type='light') # 将PIL 16位掩膜转换为8位二值化格式 # 如果mask是非零值则设置为255(塑料区域),否则为0(背景) mask_array = np.array(mask) if not isinstance(mask, np.ndarray) else mask b_thresh_unit8 = ((mask_array > 0).astype(np.uint8)) * 255 # 填充小的孔洞,并反转掩膜 b_fill = pcv.fill(bin_img=b_thresh_unit8, size=250) b_fill_inverted = pcv.invert(b_fill) # 创建形态统计和光谱统计掩膜 dilate_img = pcv.dilate(gray_img=b_fill_inverted, ksize=3, i=4) bath_erode = pcv.erode(gray_img=bath_over, ksize=3, i=4) # 塑料掩膜的反转和非黑色背景的掩膜相乘 dilate_img = dilate_img * bath_erode / 255 dilate_img = pcv.fill(bin_img=dilate_img, size=10000) # 使用cv2.connectedComponents代替pcv.create_labels,避免污染plantcv outputs num1, labeled_spectral_mask = cv2.connectedComponents(dilate_img.astype(np.uint8)) # plt.figure(figsize=(10, 8)) # plt.imshow(dilate_img, cmap='nipy_spectral') # plt.colorbar(label='Object Label') # plt.title(f'Labeled Spectral Mask - {num1} objects detected') # plt.xlabel('X coordinate') # plt.ylabel('Y coordinate') # plt.show() print(f"Number of objects (second mask): {num1 - 1}") # -1 because first label is background # 直接计算每个对象的面积并找到最大面积的对象 max_area = 0 max_label = 0 # 遍历所有标签(从1开始,0是背景) for label in range(1, num1): # 创建当前标签的掩膜 obj_mask = labeled_spectral_mask == label # 计算面积 area = np.sum(obj_mask) if area > max_area: max_area = area max_label = label # 提取最大面积对象的光谱 if max_label > 0: max_obj_mask = labeled_spectral_mask == max_label # 获取最大对象在所有波段的光谱值 spectral_values = spectral_array.array_data[max_obj_mask, :] # 计算平均光谱 mean_spectrum = np.mean(spectral_values, axis=0) # 返回最大面积对象的平均光谱 return mean_spectrum/10000 else: # 如果没有找到有效背景对象,返回全零光谱 return np.zeros(spectral_array.array_data.shape[-1]) / 10000