随着智能农业的发展,果蔬成熟度识别逐渐成为自动化采摘与质量控制中的核心问题之一。为了支持基于深度学习的目标检测算法对西红柿不同成熟阶段进行识别与分类,我们构建了一个西红柿成熟度目标检测数据集,该数据集包含三种成熟度类别:green(未成熟)、half_ripened(半成熟)和 fully_ripened(完全成熟)。

一、数据集概述

本数据集主要采集自自然光条件下的温室或露天种植环境,图像具有良好的代表性,涵盖了不同角度、不同遮挡程度、不同光照强度下的西红柿样本。

  • 📸 数量:图片共计 643张、总框数7781个其中green 框数为5134个,half_ripened 框数为 1317个,fully_ripened 框数为1330个

  • 🏷 标注类别:

    • green:果实呈绿色,尚未进入成熟阶段;

    • half_ripened:果实部分转红,处于成熟过渡期;

    • fully_ripened:果实整体呈红色,达到采摘标准。

所有图像均已按目标检测任务进行了手工标注,每个目标框标注了类别与位置坐标。如下所示:

二、数据标注说明

该数据集包含三种成熟度类别:green(未成熟)、half_ripened(半成熟)和 fully_ripened(完全成熟)。并提供了三种格式的标签,分别为json、xml和YOLO格式。在json和xml标签中,标签名称为英文。在yolo标签中,标签名字为从0开始的阿拉伯数字。其中类别编号与中英文名称的对应关系如下表所示:

类别编号 类别名称 英文名称
0 完全成熟 fully_ripened
1 未成熟 green
2 半成熟 half_ripened

三、数据增强

为提升模型对复杂环境下西红柿图像的鲁棒性,本项目在原始图像基础上引入了多种数据增强手段。增强方法主要模拟了自然环境中的光照变化与成像模糊等常见扰动,增强后的图像与原始标签一一对应,扩展了训练样本的多样性,帮助模型更好泛化。(如果需要,请自己运行下面代码进行扩充

具体包括以下三种增强方式:

1. 光照变暗(Gamma 校正)

使用随机范围在 1.6 - 2.6 的伽马值对图像进行非线性调整,模拟阴天或背光等低照度场景,增强模型在弱光环境下的检测能力。

2. 光照变亮(Gamma 校正)

设置伽马值在 0.3 - 0.7 之间,对图像进行亮度增强,模拟强光直射、正午阳光等过曝场景,提升模型在高光条件下的稳定性。

3. 模糊处理(均值模糊)

通过 11×11 的卷积核进行均值模糊,模拟摄像头抖动、对焦不准等真实采集中的模糊情况,有助于模型识别边缘不清晰的目标。

🔧 标签同步处理

每次增强后,图像的对应标签(YOLO 格式)文件会被自动复制并重命名,确保增强样本与其目标框信息一致,从而可直接用于训练。

import random
import shutil
import cv2
import numpy as np
import os
from tqdm import tqdm



# 光照变暗
def gamma_transform_low(name, img, label_path, output_path):
    gamma = random.uniform(1.6, 2.6)  # 变暗
    is_gray = img.ndim == 2 or img.shape[1] == 1
    if is_gray:
        img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    illum = hsv[..., 2] / 255.
    illum = np.power(illum, gamma)
    v = illum * 255.
    v[v > 255] = 255
    v[v < 0] = 0
    hsv[..., 2] = v.astype(np.uint8)
    img = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
    if is_gray:
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    out_image_path = os.path.join(output_path, "images", "Low_" + name)
    cv2.imwrite(out_image_path, img)
    out_label_path = os.path.join(output_path, "labels_yolo", "Low_" + name.split(".jpg")[0] + ".txt")
    shutil.copyfile(label_path, out_label_path)



# 光照变亮
def gamma_transform_high(name, img, label_path, output_path):
    gamma = random.uniform(0.3, 0.7)   # 变亮
    is_gray = img.ndim == 2 or img.shape[1] == 1
    if is_gray:
        img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    illum = hsv[..., 2] / 255.
    illum = np.power(illum, gamma)
    v = illum * 255.
    v[v > 255] = 255
    v[v < 0] = 0
    hsv[..., 2] = v.astype(np.uint8)
    img = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
    if is_gray:
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    out_image_path = os.path.join(output_path, "images", "High_" + name)
    cv2.imwrite(out_image_path, img)
    out_label_path = os.path.join(output_path, "labels_yolo", "High_" + name.split(".jpg")[0] + ".txt")
    shutil.copyfile(label_path, out_label_path)




# 光照变亮
def Mohu(name, img, label_path, output_path):

    img1 = cv2.blur(img, (11, 11))  # 模糊处理,卷积核越大,效果越明显
    out_path = os.path.join(output_path, "images", "MoHu_" + name)
    cv2.imwrite(out_path, img1)
    out_label_path = os.path.join(output_path, "labels_yolo", "MoHu_" + name.split(".jpg")[0] + ".txt")
    shutil.copyfile(label_path, out_label_path)





def main():
    images_input_path = "./data_sum\images"
    label_input_path = "./labels_yolo"
    output_path = "./output"

    image_list = os.listdir(images_input_path)

    for name in tqdm(image_list):
        img_path = os.path.join(images_input_path, name)
        label_path = os.path.join(label_input_path, name.split(".jpg")[0] + ".txt")
        image = cv2.imread(img_path)

        gamma_transform_low(name, image, label_path, output_path)
        gamma_transform_high(name, image, label_path, output_path)
        Mohu(name, image, label_path, output_path)



if __name__ == "__main__":
    main()

四、数据集划分

下面代码主要作用是将原始数据集按比例划分为训练集、验证集和测试集,并分别保存对应的图像和YOLO格式标签文件。具体过程如下:

  1. 读取数据源路径:程序首先定义了包含所有图像和YOLO标签的原始路径。

  2. 获取图像列表并打乱顺序:通过读取图像文件名列表并使用 random.shuffle() 随机打乱,实现数据的随机分布。

  3. 按照7:2:1的比例划分数据集:分别确定训练集、验证集和测试集的数量,并获取对应文件名。(可自行地定义划分比例)

  4. 创建目标文件夹并复制文件:程序依次为训练集、验证集和测试集创建对应的图像与标签保存路径,并将图像文件和标签文件分别复制过去。

import os
import random
import shutil

root_dir = r"./data_sum"
save_root_dir = r"./data_split"

image_sum_dir = os.path.join(root_dir, "images")
label_yolo_sum_dir = os.path.join(root_dir, "labels_yolo")

# 获取文件夹下所有图片名称
image_list = os.listdir(image_sum_dir)
image_list = [name for name in image_list if name.endswith(".jpg")]

# 随机打乱文件名列表
random.shuffle(image_list)

# 划分训练集和验证集
train_ratio = 0.7
val_ratio = 0.2
test_ratio = 0.1

num_images = len(image_list)
num_train = int(num_images * train_ratio)
num_val = int(num_images * val_ratio)
num_test = num_images - num_train - num_val
print("num_images:{}  num_train:{}  num_val:{}  num_test:{}".format(num_images, num_train, num_val, num_test))

# 获取训练集和验证集名字
train_names = image_list[:num_train]
val_names = image_list[num_train: num_train + num_val]
test_names = image_list[num_train + num_val: num_images]



# 训练集图片及标签保存路径
save_train_images_path = os.path.join(save_root_dir, "images", "train")
save_train_labels_path = os.path.join(save_root_dir, "labels", "train")

if not os.path.exists(save_train_images_path):
    os.makedirs(save_train_images_path)

if not os.path.exists(save_train_labels_path):
    os.makedirs(save_train_labels_path)

for name in train_names:
    # 图像
    image_path = os.path.join(image_sum_dir, name)
    label_path = os.path.join(label_yolo_sum_dir, name.split(".jpg")[0] + ".txt")
    assert os.path.exists(image_path), "file:{} not exist ...".format(image_path)
    assert os.path.exists(label_path), "file:{} not exist ...".format(label_path)
    shutil.copy(image_path, save_train_images_path)
    shutil.copy(label_path, save_train_labels_path)


# 验证集图片及标签保存路径
save_val_images_path = os.path.join(save_root_dir, "images", "val")
save_val_labels_path = os.path.join(save_root_dir, "labels", "val")

if not os.path.exists(save_val_images_path):
    os.makedirs(save_val_images_path)

if not os.path.exists(save_val_labels_path):
    os.makedirs(save_val_labels_path)

for name in val_names:
    # 图像
    image_path = os.path.join(image_sum_dir, name)
    label_path = os.path.join(label_yolo_sum_dir, name.split(".jpg")[0] + ".txt")
    assert os.path.exists(image_path), "file:{} not exist ...".format(image_path)
    assert os.path.exists(label_path), "file:{} not exist ...".format(label_path)
    shutil.copy(image_path, save_val_images_path)
    shutil.copy(label_path, save_val_labels_path)


# 测试图片及标签保存路径
save_test_images_path = os.path.join(save_root_dir, "images", "test")
save_test_labels_path = os.path.join(save_root_dir, "labels", "test")

if not os.path.exists(save_test_images_path):
    os.makedirs(save_test_images_path)

if not os.path.exists(save_test_labels_path):
    os.makedirs(save_test_labels_path)

for name in test_names:
    # 图像
    image_path = os.path.join(image_sum_dir, name)
    label_path = os.path.join(label_yolo_sum_dir, name.split(".jpg")[0] + ".txt")
    assert os.path.exists(image_path), "file:{} not exist ...".format(image_path)
    assert os.path.exists(label_path), "file:{} not exist ...".format(label_path)
    shutil.copy(image_path, save_test_images_path)
    shutil.copy(label_path, save_test_labels_path)

 本文数据集是在一些网站上搜集的,由于搜集的图片大多不带标注,自己进行了准确地标注,识别效果良好。如有需求,请支持。

(1 封私信 / 4 条消息) 西红柿番茄成熟度目标检测数据集介绍 - 知乎

Logo

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

更多推荐