{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Imports and Setup","metadata":{}},{"cell_type":"code","source":"#for offline run\n%cd ../input/yolov8\n!pip install -e\n#!pip install -r requirements.txt","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nprint(torch.__version__)\n\nimport ultralytics\nfrom ultralytics import YOLO\nultralytics.checks()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nimport seaborn as sns\nimport glob\nimport shutil\nimport torchvision\n\nfrom torchvision.io import read_image\nfrom torchvision.utils import draw_bounding_boxes\nfrom shutil import copyfile\nfrom pathlib import Path\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split\nfrom PIL import Image, ImageDraw, ImageFont\nfrom PIL import __version__ as pil_version\nfrom ultralytics.yolo.utils import LOGGER, TryExcept, plt_settings, threaded\nfrom ultralytics.yolo.utils.plotting import *\nfrom scipy.ndimage import gaussian_filter1d\n\n%matplotlib inline","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Hyperparameters","metadata":{}},{"cell_type":"code","source":"TRAIN_PATH = '/kaggle/input/global-wheat-detection/train/'\nTEST_PATH = '/kaggle/input/global-wheat-detection/test/'\nIMG_SIZE = 1024\nBATCH_SIZE = 16\nEPOCHS = 100","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepare Dataset","metadata":{}},{"cell_type":"code","source":"%cd ../\n\ndf = pd.read_csv('/kaggle/input/global-wheat-detection/train.csv') #读入数据\ndf['path'] = df.apply(lambda row: TRAIN_PATH+row.image_id+'.jpg', axis=1)#在训练的表格上批处理\ndf.head()#输出前五行数据","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"print nine pictures.","metadata":{}},{"cell_type":"code","source":"def display_images(df):\n    # set up the canvas for the subplots\n    plt.figure(figsize=(30,30))#图像大小\n    j = 1\n    for i in range(0,900,100):#输出9张图片\n        # Load an image\n        image = plt.imread(df.path[i])\n        \n        #image = cv2.resize(image, (IMAGE_SIZE, IMAGE_SIZE))\n        plt.subplot(3,3,j)\n        j+=1\n        plt.imshow(image)\n        plt.axis('off')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_images(df)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train-validation split","metadata":{}},{"cell_type":"code","source":"train_list, valid_list = train_test_split(df.image_id.unique(), test_size=0.2, random_state=1)\n#划分训练集和测试集，测试集占比0.2","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_list)#训练集大小","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(valid_list)#测试集大小","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = df.loc[df.image_id.isin(train_list)]#根据行，列的标签进行查询\nvalid_df = df.loc[df.image_id.isin(valid_list)]#根据行，列的标签进行查询\n\ntrain_df.loc[:, 'split'] = 'train'\nvalid_df.loc[:, 'split'] = 'valid'\n\ndf = pd.concat([train_df, valid_df]).reset_index(drop=True)#多个表拼接","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_df), len(valid_df)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Size of dataset: {len(df)}, training images: {len(train_df)}. validation images: {len(valid_df)}')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd ../../\n%cd kaggle/working/\n\n#创建多层目录(目录名,权限模式默认0o777,在目标目录已存在的情况下不会触发FileExistsError异常)\nos.makedirs('dataset/images/train', exist_ok=True)\nos.makedirs('dataset/images/valid', exist_ok=True)\nos.makedirs('dataset/images/test', exist_ok=True)\n\nos.makedirs('dataset/labels/train', exist_ok=True)\nos.makedirs('dataset/labels/valid', exist_ok=True)\nos.makedirs('dataset/labels/test', exist_ok=True)\n\n%cd ../../\n!tree kaggle/working/dataset","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Move the images to relevant split folder.\nfor i in tqdm(range(len(df))):\n    row = df.loc[i]\n    if row.split == 'train':\n        copyfile(row.path, f'kaggle/working/dataset/images/train/{row.image_id}.jpg')\n    else:\n        copyfile(row.path, f'kaggle/working/dataset/images/valid/{row.image_id}.jpg')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Move the test images to relevant split folder.\n# paths\nsrc = 'kaggle/input/global-wheat-detection/test'\ntrg = 'kaggle/working/dataset/images/test'\n\nfiles=os.listdir(src)\n\n# iterating over all the files in\n# the source directory\nfor fname in files:\n    # copying the files to the\n    # destination directory\n    shutil.copy2(os.path.join(src,fname), trg)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create .YAML file","metadata":{}},{"cell_type":"code","source":"%cd kaggle/working/","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%writefile dataset.yaml\npath: ../../../../../kaggle/working/dataset\ntrain: images/train\nval: images/valid\ntest: images/test\n\n# Classes\nnames:\n    0: none\n    1: opacity","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:24:18.894844Z","iopub.execute_input":"2023-10-10T06:24:18.895145Z","iopub.status.idle":"2023-10-10T06:24:18.901493Z","shell.execute_reply.started":"2023-10-10T06:24:18.895119Z","shell.execute_reply":"2023-10-10T06:24:18.900400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#查看dataset.yaml\n%cat dataset.yaml","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepare Bounding Box Coordinated for YOLOv5","metadata":{}},{"cell_type":"code","source":"def get_bbox(row):\n    bboxes = []\n    bbox = []\n    list1 = row.bbox.replace(\"[\", \"\").replace(\"]\",\"\").replace(\",\",\"\")\n    for i in list1.split(\" \"):#list.spplit():以字符串或列表里某个字符把字符串或列表进行分割成新的字符串或列表\n        bboxes.append(float(i))#格式转换\n    return bboxes","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert the bounding boxes in YOLO format.\ndef get_yolo_format_bbox(img_w, img_h, bboxes):\n    yolo_boxes = []\n    x = bboxes[0]\n    y = bboxes[1]\n    w = bboxes[2]\n    h = bboxes[3]\n    #找到中心点坐标\n    xc = x + int(w/2) # xmin + width/2\n    yc = y + int(h/2) # ymin + height/2\n    #归一化\n    yolo_boxes=[1, xc/img_w, yc/img_h, w/img_w, h/img_h] # x_center y_center width height\n    yolo_boxes = str(yolo_boxes).replace(\"[\", \"\").replace(\"]\",\"\").replace(\",\",\"\")\n    return yolo_boxes","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:13:47.556233Z","iopub.execute_input":"2023-10-10T06:13:47.556757Z","iopub.status.idle":"2023-10-10T06:13:47.584713Z","shell.execute_reply.started":"2023-10-10T06:13:47.556712Z","shell.execute_reply":"2023-10-10T06:13:47.583688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prepare the txt files for bounding box\nfor i in tqdm(range(len(df))):#tqdm是一个进度条工具库\n    row = df.loc[i]#根据行，列的标签进行查询\n    # Get image id\n    img_id = row.image_id\n    # Get split\n    split = row.split\n    \n    if row.split=='train':\n        file_name = f'dataset/labels/train/{row.image_id}.txt'\n    else:\n        file_name = f'dataset/labels/valid/{row.image_id}.txt'\n        \n    bboxes = get_bbox(row)\n        \n    # Format for YOLOv5\n    yolo_bboxes = get_yolo_format_bbox(IMG_SIZE, IMG_SIZE, bboxes)\n        \n    #打开fail_name表示的txt文件,'a'表示追加模式,在该文件末尾写入\n    with open(file_name, 'a') as f:\n        f.write(yolo_bboxes)\n        f.write('\\n')\n    #print(file_name)\n    #print(yolo_bboxes)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN_PATH = 'dataset/images/train'\nTRAIN_LABEL_PATH = 'dataset/labels/train'","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_files = os.listdir(TRAIN_LABEL_PATH)#返回TRAIN_LABEL_PATH文件夹包含的文件或文件夹的名字的列表\nprint('Number of test images predicted as opaque: ', len(train_files))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#绘图部分\ndef display_images_with_box(num):\n    pred = []\n    bbox = []\n    image_id = []\n    k = 1\n    plt.figure(figsize=(30,30))\n    for i in train_files[:num]:\n        with open(f'{TRAIN_LABEL_PATH}/{i}') as f:\n            img = read_image(f'{TRAIN_PATH}/{i[:-4]}.jpg')#读取图片\n            bbox = []\n            for j in f:\n                pred = i[:-4] + \" \" + j[:-1]\n                pred = pred.split(\" \")\n                pred.pop(0)\n                pred.pop(0)\n                pred = [eval(i) for i in pred]\n                pred = [i*1024 for i in pred]\n                [x, y, w, h] = pred\n                [xmin, ymin, xmax, ymax] = [x-w/2, y-h/2, x+w/2, y+h/2,]\n                pred = [xmin, ymin, xmax, ymax]\n                bbox.append(pred)\n            bbox = torch.tensor(bbox, dtype=torch.int)\n            img = draw_bounding_boxes(img, bbox, width=10,colors=(255,0,0))#画红框框\n            img = torchvision.transforms.ToPILImage()(img)\n            plt.subplot(num//3+num%3,3,k)\n            k+=1\n            plt.imshow(img)\n            plt.axis('off')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_images_with_box(12)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train with YOLOv5","metadata":{}},{"cell_type":"code","source":"%cd ../../../\n%cd kaggle/working/","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = YOLO(\"yolov8n.yaml\")  # build a new model from scratch\nmodel = YOLO(\"../input/roi-mammography416-yolov8/ROI Mammography 416/yolov8n.pt\")  # load a pretrained model","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!wandb off\n#训练模式\nmodel.train(data='dataset.yaml', epochs=EPOCHS, imgsz=IMG_SIZE, batch=BATCH_SIZE, save_period=1, cls=7)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Evaluation","metadata":{}},{"cell_type":"code","source":"%matplotlib inline\nplot_results('/kaggle/working/runs/detect/train/results.csv')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_results(file):\n    plt.figure(figsize=(30,30))\n    img = np.asarray(Image.open(file))\n    plt.imshow(img)\n    plt.axis('off');","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_results('/kaggle/working/runs/detect/train/results.png')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Copy somefile for later use:","metadata":{}},{"cell_type":"code","source":"copyfile('/kaggle/working/runs/detect/train/results.png','/kaggle/working/results.png')\ncopyfile('/kaggle/working/runs/detect/train/results.csv','/kaggle/working/results.csv')\ncopyfile('/kaggle/working/runs/detect/train/weights/best.pt','/kaggle/working/best.pt')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prediction","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TEST_PATH = 'dataset/images/test'","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MODEL_PATH = 'runs/detect/train/weights/best.pt'","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = YOLO(MODEL_PATH)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.predict(source=TEST_PATH, imgsz=IMG_SIZE, conf=0.5, iou=0.6, save_txt=True, save_conf=True);","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd ../../../\n%cd kaggle/working/","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"PRED_PATH = 'runs/detect/predict/labels'\n!ls {PRED_PATH}","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"prediction_files = os.listdir(PRED_PATH)\nprint('Number of test images predicted as opaque: ', len(prediction_files))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#绘图\ndef display_preds_with_box(num):\n    pred = []\n    bbox = []\n    image_id = []\n    k = 1\n    plt.figure(figsize=(30,30))\n    for i in prediction_files[:num]:\n        with open(f'{PRED_PATH}/{i}') as f:\n            img = read_image(f'{TEST_PATH}/{i[:-4]}.jpg')\n            bbox = []\n            for j in f:\n                pred = i[:-4] + \" \" + j[:-1]\n                pred = pred.split(\" \")\n                pred.pop(0)\n                pred.pop(0)\n                pred.pop(-1)\n                pred = [eval(i) for i in pred]\n                pred = [i*1024 for i in pred]\n                [x, y, w, h] = pred\n                [xmin, ymin, xmax, ymax] = [x-w/2, y-h/2, x+w/2, y+h/2]\n                pred = [xmin, ymin, xmax, ymax]\n                bbox.append(pred)\n            bbox = torch.tensor(bbox, dtype=torch.int)\n            img = draw_bounding_boxes(img, bbox, width=10,colors=(255,0,0))\n            img = torchvision.transforms.ToPILImage()(img)\n            plt.subplot(num//3+num%3,3,k)\n            k+=1\n            plt.imshow(img)\n            plt.axis('off')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_preds_with_box(10)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission file","metadata":{}},{"cell_type":"code","source":"width = IMG_SIZE\nheight = IMG_SIZE\nresults = []\n\nresult_dir = PRED_PATH\n#glob.glob():返回符合匹配条件的所有文件的路径\n#os.path.join():将多个路径组合后返回\nfor filename in glob.glob(os.path.join(result_dir,'*.txt')):\n    prefix = filename.split(\"/\")[-1].split(\".\")[0]\n    predict_str = \"\"\n    with open(filename, 'r') as fp:\n        for cnt, line in enumerate(fp):#打印一个文件同时输出行号\n            entries = np.array(line.strip('\\n').split()).astype(float)#把列表转化为数组\n            #tolist将数组转换为列表\n            bbox = np.round([(entries[1]-entries[3]/2.0)*width,(entries[2]-entries[4]/2.0)*height,entries[3]*width,entries[4]*height],3).tolist()\n            conf = entries[-1]#最后一个元素\n            predict_str = predict_str + str(conf) + \" \" + \" \".join(map(str,bbox)) + \" \" \n        results.append({'image_id':prefix, 'PredictionString':predict_str.rstrip()}) #向列表末尾添加元素\n        \nresultFrame = pd.DataFrame(results)#由results创建二维表","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"temp = []\nfor filename in glob.glob('/kaggle/input/global-wheat-detection/test/*.jpg'):\n    \n    prefix = filename.split(\"/\")[-1].split(\".\")[0]\n    if resultFrame['image_id'].str.contains(prefix).any():\n        pass\n    else:\n        temp.append({'image_id':prefix, 'PredictionString':\"\"})\n        \ndf = pd.DataFrame(temp)\nsubmission_df = pd.concat([resultFrame,df])","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd ../../../\n%cd kaggle/working/\n\nsubmission_df.to_csv('submission.csv', index=False)#将数据框 (DataFrame)中的数据导入csv格式的文件中 \nsubmission_df.tail(11)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf dataset/\n!rm -rf runs/\n!rm -rf wandb/\n!rm dataset.yaml","metadata":{},"execution_count":null,"outputs":[]}]}