Files
micro_plastic/shape_spectral_background.py
2026-02-25 09:42:51 +08:00

87 lines
3.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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