一.项目背景

根据了解传统的煤质分类方法主要依赖人工采样和实验室分析,存在效率低、成本高、实时性差等问题。针对这些问题,本论文旨在设计一种煤矿煤质自动分类识别方法,主要为以下目标:

  • (1)提高效率与自动化程度:利用自动化设备和技术,减少人工干预,提升煤质分类的效率。
  • (2)降低成本:通过自动化减少人力成本,并优化资源利用。
  • (3)增强实时性与准确性:实现煤质的实时在线检测,确保分类结果更加准确可靠。

 二.数据集

数据集共五个类别,目录如下:

部分图片数据展示:

数据集获取链接: https://pan.quark.cn/s/dc3bfbe81f07

三.设计思路

模块划分与功能说明

1. 数据增强与图像预处理模块(DataAugmenter

🎯 目标:

提升模型泛化能力,增强样本多样性,同时对图像进行去噪处理质量评价(PSNR、MAE、信息熵等)

🔧 方法:
  • 增强操作

    • 水平翻转

    • 颜色抖动

    • 雾化效果

    • 模糊(高斯模糊模拟运动模糊)

代码如下:

    def __init__(self, original_data_dir, demo_dir, denoised_dir,augment_interval=10):
        self.original_data_dir = original_data_dir
        self.demo_dir = demo_dir
        self.augment_interval = augment_interval

        # 定义增强变换(仅水平翻转+颜色抖动)
        self.aug_transform = transforms.Compose([
            transforms.RandomHorizontalFlip(p=1.0),  # 强制水平翻转
            transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1)
        ])

        self.flip_transform = transforms.RandomHorizontalFlip(p=1.0)  # 强制水平翻转
        self.color_transform = transforms.ColorJitter(
            brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1
        )

    @staticmethod
    def _add_fog_effect(img):
        """ 添加雾化效果 """
        # 创建雾效图层(随机灰度层)
        fog = Image.new('RGB', img.size,
                      color=(np.random.randint(200,255),
                      np.random.randint(200,255),
                      np.random.randint(200,255)))
        # 混合原图和雾效(随机透明度)
        return Image.blend(img, fog, alpha=np.random.uniform(0.3, 0.6))

    @staticmethod
    def _add_motion_blur(img):
        """ 添加运动模糊 """
        # 随机运动方向和强度
        radius = np.random.randint(5, 15)
        angle = np.random.randint(0, 180)

        # 先应用高斯模糊
        img = img.filter(ImageFilter.GaussianBlur(radius=radius))
        # 再应用运动模糊
        # img = img.filter(ImageFilter.MotionBlur(radius=radius, angle=angle))

        return img
  • 去噪方法

    • 中值滤波

    • 高斯滤波

    • 双边滤波

代码如下:

    @staticmethod
    def _denoise_image(img):
        """ 使用中值滤波去噪 """
        return img.filter(ImageFilter.MedianFilter(size=3))  # 中值滤波去噪

    @staticmethod
    def _denoise_image_gaussian(img):
        """ 使用高斯滤波去噪 """
        # 将图像转换为 numpy 数组并应用高斯滤波
        img_array = np.array(img)
        denoised_array = cv2.GaussianBlur(img_array, (15, 15), 0)  # 高斯滤波
        return Image.fromarray(denoised_array)

    @staticmethod
    def _denoise_image_bilateral(img):
        """ 使用双边滤波去噪 """
        # 将图像转换为 numpy 数组并应用双边滤波
        img_array = np.array(img)
        denoised_array = cv2.bilateralFilter(img_array, 15, 75, 75)  # 双边滤波
        return Image.fromarray(denoised_array)
  • 质量评价指标

    • PSNR(峰值信噪比)

    • MAE(平均绝对误差)

    • 图像均值、标准差

    • 信息熵、平均梯度

计算代码如下:

@staticmethod
    def calculate_psnr(img1, img2):
        """ 计算峰值噪声比(PSNR) """
        img1 = np.array(img1)
        img2 = np.array(img2)
        mse = np.mean((img1 - img2) ** 2)
        if mse == 0:
            return 100
        max_pixel = 255.0
        psnr = 20 * np.log10(max_pixel / np.sqrt(mse))
        return psnr

    @staticmethod
    def calculate_mae(img1, img2):
        """ 计算平均绝对误差(MAE) """
        img1 = np.array(img1)
        img2 = np.array(img2)
        mae = np.mean(np.abs(img1 - img2))
        return mae

    @staticmethod
    def calculate_std(img):
        """ 计算图像的标准差(STD) """
        img = np.array(img)
        std = np.std(img)
        return std

    @staticmethod
    def calculate_mean(img):
        """ 计算图像的平均值 """
        img_array = np.array(img)
        return np.mean(img_array)

    @staticmethod
    def calculate_mean_gradient(img):
        """ 计算图像的平均梯度 """
        img_array = np.array(img)
        gradient = np.gradient(img_array, axis=(0, 1))  # 计算梯度
        magnitude = np.sqrt(gradient[0]**2 + gradient[1]**2)
        return np.mean(magnitude)

    @staticmethod
    def calculate_entropy(img):
        """ 计算图像的信息熵 """
        img_array = np.array(img)
        entropy = measure.shannon_entropy(img_array)
        return entropy
📂 输出:
  • 增强图像保存在 demo_dir

  • 去噪图像和原图保存在 denoised_dir

  • 所有图像质量指标保存为 .txt 文件

图像指标结果如下:

 

分别为图像去燥和图像增强后的评价指标


2. 特征提取模块(FeatureExtractor

🎯 目标:

利用预训练的 ResNet18 网络,提取图像的深层语义特征。

🛠️ 特征提取流程:
  • 使用 torchvision.models.resnet18 去掉最后的全连接层(只保留卷积部分)

  • 对所有图像进行 Resize → CenterCrop → Normalize 的标准预处理

  • 提取每张图的特征向量(维度通常为 512)

  • 保存为 features.npz(包含 features, labels, classes

代码定义如下:

class FeatureExtractor:
    def __init__(self):
        self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        # self.device = torch.device("cpu")
        # 加载预训练模型(以ResNet18为例)
        self.model = torchvision.models.resnet18(weights='IMAGENET1K_V1')
        # self.model = torchvision.models.resnet18(pretrained=True)
        # 移除最后的全连接层
        self.model = nn.Sequential(*list(self.model.children())[:-1])
        self.model = self.model.to(self.device).eval()

        # 图像预处理(根据预训练模型要求设置)
        self.transform = transforms.Compose([
            transforms.Resize(256),
            transforms.CenterCrop(224),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
        ])

3. 模型训练模块(ModelTrainer

🎯 目标:

对提取的特征进行分类器训练(使用自定义的 ModelTrainer,可能内部用了 SVM / MLP / RandomForest)。

📈 步骤:
  • .npz 文件中读取 featureslabels

  • 进行训练/测试集划分

  • 模型训练

  • 最终保存为 pest_classifier.pkl

我们设计一个通用的 ModelTrainer 类,用于封装特征分类的完整流程。该模块不仅支持常见的机器学习模型(如 SVM、KNN、Random Forest),还可以扩展到更复杂的深度学习网络(如 ResNet18)。整个训练流程从 .npz 文件中加载提取好的特征和标签,完成标准化处理、训练/测试集划分、模型选择、交叉验证评估以及最终模型保存。

训练过程中,模块会自动:

  • 对不同分类器进行交叉验证,比较其准确率、召回率与 F1 分数;

  • 绘制每个模型的学习曲线及混淆矩阵;

  • 最终选择表现最优的模型进行全量训练,并保存为 pest_classifier.pkl,供后续使用。

此外,该模块还为深度学习模型单独实现了训练与评估流程,确保可以兼容图像分类任务下的端到端训练与推理需求,适用于更大规模或复杂的数据集。

代码设计如下:

🔁 主执行流程(__main__

主函数执行逻辑: 

1. 创建 ModelTrainer 实例 

2. 使用 DataAugmenter 对原始数据进行增强与去噪,保存示例图像及指标 

3. 使用 FeatureExtractor 提取特征(若已有则跳过) 

4. 将特征传入 ModelTrainer 进行训练 

5. 保存训练好的分类器模型

if __name__ == "__main__":
    # 参数配置
    DATA_DIR = "./data"  # 替换为实际路径
    DEMO_DIR = "./augmented_demo"
    denoised_DIR = "./denoised_demo"
    SAVE_PATH = "./features.npz"  # 特征保存路径

    trainer = ModelTrainer()

    # Step 0: 执行数据增强
    print("正在进行数据增强处理...")
    augmenter = DataAugmenter(DATA_DIR, DEMO_DIR, SAVE_PATH)
    augmenter.process_dataset()
    print(f"增强后的示例图片已保存至: {DEMO_DIR}")

    trainer.resnet_train(DATA_DIR)

    # 实例化特征提取器
    extractor = FeatureExtractor()

    # 特征提取(若未保存则执行)
    if not os.path.exists(SAVE_PATH):
        features, labels, classes = extractor.extract_features(DATA_DIR)
        np.savez(SAVE_PATH, features=features, labels=labels, classes=classes)
    else:
        data = np.load(SAVE_PATH)
        features = data['features']
        labels = data['labels']

    # 准备训练数据(按8:2划分)
    X, y = features, labels


    # 训练模型

    model = trainer.train_model(X, y)

    # 保存模型(示例)
    import joblib
    joblib.dump(model, 'pest_classifier.pkl')

四.成果展示

本项目构建了一个完整的煤矿煤质图像识别系统,涵盖了从特征提取、模型训练到最终分类器部署的完整流程。我们分别对传统机器学习模型(如 SVM、Random Forest、KNN)和基于深度学习的 ResNet18 模型进行了训练与评估,以下是模型效果的具体展示:


📊 1. 传统机器学习模型表现

在使用 .npz 文件提取的特征基础上,我们对多个经典分类器进行了训练、交叉验证和评估:

  • 交叉验证准确率最高可达 85%+,F1 分数整体稳定

  • 📈 自动绘制 学习曲线,展示模型在不同训练规模下的拟合能力

  • 🔍 混淆矩阵清晰展示了各类别之间的分类效果

  • 🏆 系统自动选择表现最好的模型(以 F1 分数为依据)作为最终输出,并保存为 pest_classifier.pkl

你可以在 model_plots/ 目录中查看每个模型对应的:

  • *_learning_curve.png:学习曲线

  • *_confusion_matrix.png:测试集混淆矩阵


🧠 2. ResNet18 图像分类结果

除了传统机器学习方法,我们还训练了一个基于预训练 ResNet18 的深度学习模型,对图像进行端到端分类:

  • 📦 图像加载后经过标准预处理与训练/测试划分

  • 🧠 使用 迁移学习 技术,仅微调最后一层,全模型收敛更快,泛化能力强

  • 🔁 训练过程动态输出每个 Epoch 的损失变化,便于跟踪学习进度

  • 📉 最终测试准确率表现稳定,可用于实际推理部署

成果输出:

  • ✅ 训练好的模型保存在 results/resnet18_best.pth

  • 📊 性能评估结果自动生成,包括:

    • results/metrics.png:Accuracy / Recall / F1 分数柱状图

    • results/confusion_matrix.png:图像分类混淆矩阵

    • results/report.txt:详细的分类报告文本

 这里我只用cpu跑了三十轮,效果如下:

项目最终结果和源码获取:https://www.klgeek.com/i/8160997493 

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐