【FP60】林业害虫数据集——目标检测、图像分类

文章目录

1、FP60(Forest Pest60)基本介绍

根据中国江苏省林业有害生物分布情况,筛选出 **15 **个科 60 种,见表,常见且易于获取的林业害虫。主要从互联网上收集林业害虫图像。在收集过程中,以每种林业有害生物的拉丁文学名作为查询关键词,然后在常见的图片搜索引擎中搜索,包括 Google、Bing 和百度。手动筛选搜索结果以过滤低质量图像。我们总共有 7253 张高质量的林业害虫图像,大小从 93×140 到 6016×4106 不等。

此外,对FP60数据集又进行了二次划分,分别为FP40(40种)、FP15(15种),每个数据集已经预处理为YOLO格式。

下图显示了该数据集中 60 种林业有害生物的图像,每张图片代表一种林业有害生物。


每个数据集的文件结构如下:

python 复制代码
   FP60
	|
	|___dataset
	|	  |______images
    |     |        |_______train
    |	  |        |         |__________1-1-1.jpg
    |	  |        |         |__________ ......
    |     |        |_______test
    |	  |        |         |__________2-4-82.jpg
    |	  |        |         |__________ ......
    |     |        |_______val
    |	  |        |         |__________2-4-1.jpg
    |	  |        |         |__________ ......
	|	  |
	|	  |______labels	  
    |     |        |_______train
    |	  |        |         |__________1-1-1.txt
    |	  |        |         |__________ ......
    |     |        |_______test
    |	  |        |         |__________2-4-82.txt
    |	  |        |         |__________ ......
    |     |        |_______val
    |	  |        |         |__________2-4-1.txt
    |	  |        |         |__________ ......

同时,文件中也有对应的处理代码。

2、一些数据处理

下面这些代码不仅仅只针对当前数据集,对其他目标检测数据集同样适用(注意要求改文件路径)。

2.1、数据划分

python 复制代码
import os
import shutil
def get_dataset_name(file):
    file_names = []
    with open(file, 'r', encoding='utf-8') as f:
        lines = f.readlines()
        for line in lines:
            file_names.append(line.split('\n')[0])
    return file_names
def copy_file(s_folder,d_folder,file_name,type='.jpg'):
    s_file = os.path.join(s_folder,file_name+type)
    d_file = os.path.join(d_folder,file_name+type)
    if not os.path.exists(d_file):
        shutil.copyfile(s_file,d_file)
def process_multi_files(file_names,s_folder,d_folder,type):
    for name in file_names:
        copy_file(s_folder,d_folder,name,type)
def main():
    train_file_txt = './labels/train.txt'
    val_file_txt = './labels/trainval.txt'
    test_file_txt_1 = './labels/test.txt'
    test_file_txt_2 = './labels/val.txt'
    
    image_path = './images'
    xml_path = './annotations'

    train_img_fold = './datasets/images/train'
    test_img_fold = './datasets/images/test'
    val_img_fold = './datasets/images/val'

    # train_txt_fold = './datasets/txt/train'
    # test_txt_fold = './datasets/txt/test'
    # val_txt_fold = './datasets/txt/val'

    train_xml_fold = './datasets/xml/train'
    test_xml_fold = './datasets/xml/test'
    val_xml_fold = './datasets/xml/val'
    
    train_file_names = get_dataset_name(train_file_txt)
    val_file_names = get_dataset_name(val_file_txt)
    test_file_names_1 = get_dataset_name(test_file_txt_1)
    test_file_names_2 = get_dataset_name(test_file_txt_2)
    test_file_names_1.extend(test_file_names_2)
    # 复制训练集图片
    process_multi_files(train_file_names,image_path,train_img_fold,'.jpg')
    # 复制验证集图片
    process_multi_files(val_file_names,image_path,val_img_fold,'.jpg')
    #复制测试集图片
    process_multi_files(test_file_names_1,image_path,test_img_fold,'.jpg')
    
    # 复制训练集xml
    process_multi_files(train_file_names,xml_path,train_xml_fold,'.xml')
    # 复制验证集xml
    process_multi_files(val_file_names,xml_path,val_xml_fold,'.xml')
    #复制测试集xml
    process_multi_files(test_file_names_1,xml_path,test_xml_fold,'.xml')
if __name__ == "__main__":
    main()

2.2、xml格式转yolo格式

python 复制代码
# 导入相关库
import os
from lxml import etree
from tqdm import tqdm


def voc2txt():
    # 获取xml文件夹下的所有xml文件名,存入列表
    xmls_list = os.listdir(xmls_ori_path)
    for xml_name in tqdm(xmls_list):
        # 打开写入文件
        txt_name = xml_name.replace('xml', 'txt')

        f = open(os.path.join(txts_save_path, txt_name), 'w')  # 代开待写入的txt文件
        with open(os.path.join(xmls_ori_path, xml_name), 'rb') as fp:
            # 开始解析xml文件
            xml = etree.HTML(fp.read())
            width = int(xml.xpath('//size/width/text()')[0])
            height = int(xml.xpath('//size/height/text()')[0])
            # 获取对象标签
            obj = xml.xpath('//object')
            for each in obj:
                name = each.xpath("./name/text()")[0]
                classes = dic[name]
                xmin = int(each.xpath('./bndbox/xmin/text()')[0])
                xmax = int(each.xpath('./bndbox/xmax/text()')[0])
                ymin = int(each.xpath('./bndbox/ymin/text()')[0])
                ymax = int(each.xpath('./bndbox/ymax/text()')[0])
                # 归一化
                dw = 1 / width
                dh = 1 / height
                x_center = (xmin + xmax) / 2
                y_center = (ymax + ymin) / 2
                w = (xmax - xmin)
                h = (ymax - ymin)
                x, y, w, h = x_center * dw, y_center * dh, w * dw, h * dh
                # 写入
                f.write(str(classes) + ' ' + str(x) + ' ' + str(y) + ' ' + str(w) + ' ' + str(h) + ' ' + '\n')
        f.close()  # 关闭txt文件


if __name__ == '__main__':
    dic = {'2-4': "0",  
           '3-1': "1",   
           '5-2': "2",
           '5-3': "3",
           '6-3': "4",
           '6-4': "5",
           '8-3': "6",
           '11-4': "7",
           '12-3': "8",
           '12-4': "9",
           '13-1': "10",
           '14-1': "11",
           '14-3': "12",
           '14-5': "13",
           '15-1': "14",
           }

    #训练数据
    # xmls_ori_path = r"./datasets/xml/train"         # xml文件所在的文件夹
    # txts_save_path = r"./datasets/txt/train"         # txt文件所在的文件夹
    #验证数据
    # xmls_ori_path = r"./datasets/xml/val"         # xml文件所在的文件夹
    # txts_save_path = r"./datasets/txt/val"         # txt文件所在的文件夹
    #测试数据
    xmls_ori_path = r"./datasets/xml/test"         # xml文件所在的文件夹
    txts_save_path = r"./datasets/txt/test"         # txt文件所在的文件夹
    voc2txt()
    

2.3、check标注框

python 复制代码
import os
import cv2

class check_label:
    def __init__(self, classes:list, label_path:str, img_path:str, result_path:str=None):
        self.classes = classes
        self.line_width = 5 #线宽
        self.rec_color = (0, 0, 255) #颜色
        self.font_color = (255, 255, 255) #字体颜色
        self.font = cv2.FONT_HERSHEY_SIMPLEX
        self.font_size = 5 #字体大小
        self.font_thickness = 4
        self.font_x_offset = 0#字体x坐标偏移
        self.font_y_offset = -15#字体y坐标偏移

        self.isDrawFontRec = False#是否绘制字体矩形框
        self.isShowFont = False#是否绘制字体
        self.isShowConfidence = False#是否绘制置信度

        self.label_path =  label_path # 数据集标注结果文件(yolo格式)
        self.img_path = img_path  # 图像文件
        self.result_path = result_path  # 在图像上画好标注框文件

        self.label_files = os.listdir(label_path)
        self.img_files = os.listdir(img_path)
        #self.label_files.sort(key=lambda x: int(x[:-4]))
        #self.img_files.sort(key=lambda x: int(x[:-4]))

    def paint(self, imgName, pos):
        img = cv2.imread(self.img_path + "/" + imgName)
        size = img.shape
        imgW = size[1]
        imgH = size[0]
        # print("pos:", len(pos))
        for pos_i in pos:
            # a, x, y, w, h, b = "orange", pos_i[1], pos_i[2], pos_i[3], pos_i[4], pos_i[4]
            pos_i = pos_i.split(' ')
            x_center = float(pos_i[1]) * imgW + 1
            y_center = float(pos_i[2]) * imgH + 1
            x_min = int(x_center - 0.5 * float(pos_i[3]) * imgW)
            y_min = int(y_center - 0.5 * float(pos_i[4]) * imgH)
            x_max = int(x_center + 0.5 * float(pos_i[3]) * imgW)
            y_max = int(y_center + 0.5 * float(pos_i[4]) * imgH)
            x = x_min
            y = y_min
            w = x_max - x_min
            h = y_max - y_min
            # rotate90(imgW, imgH, x_min, y_min, w, h, x_center, y_center)
            # rotate180(imgW, imgH, x_min, y_min, w, h, x_center, y_center)
            # rotate270(imgW, imgH, x_min, y_min, w, h, x_center, y_center)
            # b = float(pos_i[5])
            b = 0.5
            if self.isShowConfidence:
                a = self.classes[int(pos_i[0])]
            else:
                a = ""
            cv2.rectangle(img, (x, y), (x + w, y + h), self.rec_color, self.line_width)
            if self.isDrawFontRec:
                cv2.rectangle(img, (x + self.font_x_offset, y + self.font_y_offset), (x + w, y + abs(self.font_y_offset)), self.rec_color,
                              -1)
            if self.isShowFont:
                cv2.putText(img, '{} {:.3f}'.format(a, b), (x + self.font_x_offset, y + self.font_y_offset), self.font, self.font_size,
                            self.font_color, self.font_thickness)
        cv2.imshow("img", img)
        cv2.waitKey(0)
        # cv2.imwrite(self.result_path + "/" + imgName, img)

    def process(self):
        for label_file, img_file in zip(self.label_files, self.img_files):
            print(img_file, label_file)
            if not os.path.isdir(label_file):
                f = open(self.label_path + "/" + label_file, "r", encoding='utf-8')
                result = f.read().splitlines()
                # print(result)
                self.paint(img_file, result)
                f.close()
classes = ['2-4','3-1','5-2','5-3','6-3','6-4','8-3','11-4',
           '12-3','12-4','13-1','14-1','14-3','14-5','15-1',]
cl = check_label(classes,'./txt','./images')
cl.process()

3、数据集获取

林业害虫数据集下载链接

相关推荐
mozun20201 分钟前
产业观察:哈工大机器人公司2025.4.22
大数据·人工智能·机器人·创业创新·哈尔滨·名校
-一杯为品-3 分钟前
【深度学习】#9 现代循环神经网络
人工智能·rnn·深度学习
硅谷秋水6 分钟前
ORION:通过视觉-语言指令动作生成的一个整体端到端自动驾驶框架
人工智能·深度学习·机器学习·计算机视觉·语言模型·自动驾驶
Java中文社群28 分钟前
最火向量数据库Milvus安装使用一条龙!
java·人工智能·后端
豆芽81936 分钟前
强化学习(Reinforcement Learning, RL)和深度学习(Deep Learning, DL)
人工智能·深度学习·机器学习·强化学习
山北雨夜漫步42 分钟前
机器学习 Day14 XGboost(极端梯度提升树)算法
人工智能·算法·机器学习
yzx9910131 小时前
集成学习实际案例
人工智能·机器学习·集成学习
CodeJourney.1 小时前
DeepSeek与WPS的动态数据可视化图表构建
数据库·人工智能·信息可视化
jndingxin1 小时前
OpenCV 图形API(62)特征检测-----在图像中查找最显著的角点函数goodFeaturesToTrack()
人工智能·opencv·计算机视觉
努力犯错1 小时前
昆仑万维开源SkyReels-V2,解锁无限时长电影级创作,总分83.9%登顶V-Bench榜单
大数据·人工智能·语言模型·开源