<jupyter_start><jupyter_text>**This notebook is in beta**Expect some instabilities and bugs.**Currently missing features include:**- Augmentation cannot be disabled- Exported results include only a simple CSV file. More options will be included in the next releases- Training and QC reports are not generated  **Detectron2 (2D)** Detectron2 is a deep-learning method designed to perform object detection and classification of objects in images. Detectron2 is Facebook AI Research's next generation software system that implements state-of-the-art object detection algorithms. It is a ground-up rewrite of the previous version, Detectron, and it originates from maskrcnn-benchmark. More information on Detectron2 can be found on the Detectron2 github pages (https://github.com/facebookresearch/detectron2).**This particular notebook enables object detection and classification on 2D images given ground truth bounding boxes. If you are interested in image segmentation, you should use our U-net or Stardist notebooks instead.**---*Disclaimer*:This notebook is part of the Zero-Cost Deep-Learning to Enhance Microscopy project (https://github.com/HenriquesLab/DeepLearning_Collab/wiki). Jointly developed by the Jacquemet (link to https://cellmig.org/) and Henriques (https://henriqueslab.github.io/) laboratories.  **License**---<jupyter_code>#@markdown ##Double click to see the license information

#------------------------- LICENSE FOR ZeroCostDL4Mic------------------------------------
#This ZeroCostDL4Mic notebook is distributed under the MIT licence



#------------------------- LICENSE FOR CycleGAN ------------------------------------


#Apache License
#Version 2.0, January 2004
#http://www.apache.org/licenses/

#TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

#1. Definitions.

#"License" shall mean the terms and conditions for use, reproduction,
#and distribution as defined by Sections 1 through 9 of this document.

#"Licensor" shall mean the copyright owner or entity authorized by
#the copyright owner that is granting the License.

#"Legal Entity" shall mean the union of the acting entity and all
#other entities that control, are controlled by, or are under common
#control with that entity. For the purposes of this definition,
#"control" means (i) the power, direct or indirect, to cause the
#direction or management of such entity, whether by contract or
#otherwise, or (ii) ownership of fifty percent (50%) or more of the
#outstanding shares, or (iii) beneficial ownership of such entity.

#"You" (or "Your") shall mean an individual or Legal Entity
#exercising permissions granted by this License.

#"Source" form shall mean the preferred form for making modifications,
#including but not limited to software source code, documentation
#source, and configuration files.

#"Object" form shall mean any form resulting from mechanical
#transformation or translation of a Source form, including but
#not limited to compiled object code, generated documentation,
#and conversions to other media types.

#"Work" shall mean the work of authorship, whether in Source or
#Object form, made available under the License, as indicated by a
#copyright notice that is included in or attached to the work
#(an example is provided in the Appendix below).

#"Derivative Works" shall mean any work, whether in Source or Object
#form, that is based on (or derived from) the Work and for which the
#editorial revisions, annotations, elaborations, or other modifications
#represent, as a whole, an original work of authorship. For the purposes
#of this License, Derivative Works shall not include works that remain
#separable from, or merely link (or bind by name) to the interfaces of,
#the Work and Derivative Works thereof.

#"Contribution" shall mean any work of authorship, including
#the original version of the Work and any modifications or additions
#to that Work or Derivative Works thereof, that is intentionally
#submitted to Licensor for inclusion in the Work by the copyright owner
#or by an individual or Legal Entity authorized to submit on behalf of
#the copyright owner. For the purposes of this definition, "submitted"
#means any form of electronic, verbal, or written communication sent
#to the Licensor or its representatives, including but not limited to
#communication on electronic mailing lists, source code control systems,
#and issue tracking systems that are managed by, or on behalf of, the
#Licensor for the purpose of discussing and improving the Work, but
#excluding communication that is conspicuously marked or otherwise
#designated in writing by the copyright owner as "Not a Contribution."

#"Contributor" shall mean Licensor and any individual or Legal Entity
#on behalf of whom a Contribution has been received by Licensor and
#subsequently incorporated within the Work.

#2. Grant of Copyright License. Subject to the terms and conditions of
#this License, each Contributor hereby grants to You a perpetual,
#worldwide, non-exclusive, no-charge, royalty-free, irrevocable
#copyright license to reproduce, prepare Derivative Works of,
#publicly display, publicly perform, sublicense, and distribute the
#Work and such Derivative Works in Source or Object form.

#3. Grant of Patent License. Subject to the terms and conditions of
#this License, each Contributor hereby grants to You a perpetual,
#worldwide, non-exclusive, no-charge, royalty-free, irrevocable
#(except as stated in this section) patent license to make, have made,
#use, offer to sell, sell, import, and otherwise transfer the Work,
#where such license applies only to those patent claims licensable
#by such Contributor that are necessarily infringed by their
#Contribution(s) alone or by combination of their Contribution(s)
#with the Work to which such Contribution(s) was submitted. If You
#institute patent litigation against any entity (including a
#cross-claim or counterclaim in a lawsuit) alleging that the Work
#or a Contribution incorporated within the Work constitutes direct
#or contributory patent infringement, then any patent licenses
#granted to You under this License for that Work shall terminate
#as of the date such litigation is filed.

#4. Redistribution. You may reproduce and distribute copies of the
#Work or Derivative Works thereof in any medium, with or without
#modifications, and in Source or Object form, provided that You
#meet the following conditions:

#(a) You must give any other recipients of the Work or
#Derivative Works a copy of this License; and

#(b) You must cause any modified files to carry prominent notices
#stating that You changed the files; and

#(c) You must retain, in the Source form of any Derivative Works
#that You distribute, all copyright, patent, trademark, and
#attribution notices from the Source form of the Work,
#excluding those notices that do not pertain to any part of
#the Derivative Works; and

#(d) If the Work includes a "NOTICE" text file as part of its
#distribution, then any Derivative Works that You distribute must
#include a readable copy of the attribution notices contained
#within such NOTICE file, excluding those notices that do not
#pertain to any part of the Derivative Works, in at least one
#of the following places: within a NOTICE text file distributed
#as part of the Derivative Works; within the Source form or
#documentation, if provided along with the Derivative Works; or,
#within a display generated by the Derivative Works, if and
#wherever such third-party notices normally appear. The contents
#of the NOTICE file are for informational purposes only and
#do not modify the License. You may add Your own attribution
#notices within Derivative Works that You distribute, alongside
#or as an addendum to the NOTICE text from the Work, provided
#that such additional attribution notices cannot be construed
#as modifying the License.

#You may add Your own copyright statement to Your modifications and
#may provide additional or different license terms and conditions
#for use, reproduction, or distribution of Your modifications, or
#for any such Derivative Works as a whole, provided Your use,
#reproduction, and distribution of the Work otherwise complies with
#the conditions stated in this License.

#5. Submission of Contributions. Unless You explicitly state otherwise,
#any Contribution intentionally submitted for inclusion in the Work
#by You to the Licensor shall be under the terms and conditions of
#this License, without any additional terms or conditions.
#Notwithstanding the above, nothing herein shall supersede or modify
#the terms of any separate license agreement you may have executed
#with Licensor regarding such Contributions.

#6. Trademarks. This License does not grant permission to use the trade
#names, trademarks, service marks, or product names of the Licensor,
#except as required for reasonable and customary use in describing the
#origin of the Work and reproducing the content of the NOTICE file.

#7. Disclaimer of Warranty. Unless required by applicable law or
#agreed to in writing, Licensor provides the Work (and each
#Contributor provides its Contributions) on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
#implied, including, without limitation, any warranties or conditions
#of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
#PARTICULAR PURPOSE. You are solely responsible for determining the
#appropriateness of using or redistributing the Work and assume any
#risks associated with Your exercise of permissions under this License.

#8. Limitation of Liability. In no event and under no legal theory,
#whether in tort (including negligence), contract, or otherwise,
#unless required by applicable law (such as deliberate and grossly
#negligent acts) or agreed to in writing, shall any Contributor be
#liable to You for damages, including any direct, indirect, special,
#incidental, or consequential damages of any character arising as a
#result of this License or out of the use or inability to use the
#Work (including but not limited to damages for loss of goodwill,
#work stoppage, computer failure or malfunction, or any and all
#other commercial damages or losses), even if such Contributor
#has been advised of the possibility of such damages.

#9. Accepting Warranty or Additional Liability. While redistributing
#the Work or Derivative Works thereof, You may choose to offer,
#and charge a fee for, acceptance of support, warranty, indemnity,
#or other liability obligations and/or rights consistent with this
#License. However, in accepting such obligations, You may act only
#on Your own behalf and on Your sole responsibility, not on behalf
#of any other Contributor, and only if You agree to indemnify,
#defend, and hold each Contributor harmless for any liability
#incurred by, or claims asserted against, such Contributor by reason
#of your accepting any such warranty or additional liability.

#END OF TERMS AND CONDITIONS

#APPENDIX: How to apply the Apache License to your work.

#To apply the Apache License to your work, attach the following
#boilerplate notice, with the fields enclosed by brackets "[]"
#replaced with your own identifying information. (Don't include
#the brackets!)  The text should be enclosed in the appropriate
#comment syntax for the file format. We also recommend that a
#file or class name and description of purpose be included on the
#same "printed page" as the copyright notice for easier
#identification within third-party archives.

#Copyright [yyyy] [name of copyright owner]


#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at

#http://www.apache.org/licenses/LICENSE-2.0

#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.<jupyter_output><empty_output><jupyter_text>**How to use this notebook?**---Video describing how to use our notebooks are available on youtube:  - [**Video 1**](https://www.youtube.com/watch?v=GzD2gamVNHI&feature=youtu.be): Full run through of the workflow to obtain the notebooks and the provided test datasets as well as a common use of the notebook  - [**Video 2**](https://www.youtube.com/watch?v=PUuQfP5SsqM&feature=youtu.be): Detailed description of the different sections of the notebook---**Structure of a notebook**The notebook contains two types of cell:  **Text cells** provide information and can be modified by douple-clicking the cell. You are currently reading the text cell. You can create a new text by clicking `+ Text`.**Code cells** contain code and the code can be modfied by selecting the cell. To execute the cell, move your cursor on the `[ ]`-mark on the left side of the cell (play button appears). Click to execute the cell. After execution is done the animation of play button stops. You can create a new coding cell by clicking `+ Code`.---**Table of contents, Code snippets** and **Files**On the top left side of the notebook you find three tabs which contain from top to bottom:*Table of contents* = contains structure of the notebook. Click the content to move quickly between sections.*Code snippets* = contain examples how to code certain tasks. You can ignore this when using this notebook.*Files* = contain all available files. After mounting your google drive (see section 1.) you will find your files and folders here. **Remember that all uploaded files are purged after changing the runtime.** All files saved in Google Drive will remain. You do not need to use the Mount Drive-button; your Google Drive is connected in section 1.2.**Note:** The "sample data" in "Files" contains default files. Do not upload anything in here!---**Making changes to the notebook****You can make a copy** of the notebook and save it to your Google Drive. To do this click file -> save a copy in drive.To **edit a cell**, double click on the text. This will show you either the source code (in code cells) or the source text (in text cells).You can use the ``-mark in code cells to comment out parts of the code. This allows you to keep the original code piece in the cell as a comment. **0. Before getting started**--- Preparing the dataset carefully is essential to make this Detectron2 notebook work. This model requires as input a set of images  and as target a list of annotation files in Pascal VOC format. The annotation files should have the exact same name as the input files, except with an .xml instead of the .jpg extension. The annotation files contain the class labels and all bounding boxes for the objects for each image in your dataset. Most datasets will give the option of saving the annotations in this format or using software for hand-annotations will automatically save the annotations in this format.  If you want to assemble your own dataset we recommend using the open source https://www.makesense.ai/ resource. You can follow our instructions on how to label your dataset with this tool on our [wiki](https://github.com/HenriquesLab/ZeroCostDL4Mic/wiki/Object-Detection-(YOLOv2)).**We strongly recommend that you generate extra paired images. These images can be used to assess the quality of your trained model (Quality control dataset)**. The quality control assessment can be done directly in this notebook. **Additionally, the corresponding input and output files need to have the same name**. Please note that you currently can **only use .png files!**Here's a common data structure that can work:*   Experiment A    - **Training dataset**      - Input images (Training_source)        - img_1.png, img_2.png, ...      - High SNR images (Training_source_annotations)        - img_1.xml, img_2.xml, ...    - **Quality control dataset**     - Input images        - img_1.png, img_2.png      - High SNR images        - img_1.xml, img_2.xml    - **Data to be predicted**    - **Results**---**Important note**- If you wish to **Train a network from scratch** using your own dataset (and we encourage everyone to do that), you will need to run **sections 1 - 4**, then use **section 5** to assess the quality of your model and **section 6** to run predictions using the model that you trained.- If you wish to **Evaluate your model** using a model previously generated and saved on your Google Drive, you will only need to run **sections 1 and 2** to set up the notebook, then use **section 5** to assess the quality of your model.- If you only wish to **run predictions** using a model previously generated and saved on your Google Drive, you will only need to run **sections 1 and 2** to set up the notebook, then use **section 6** to run the predictions on the desired model.---  **1. Install Detectron2 and dependencies**---  **1.1. Install key dependencies**---<jupyter_code>#@markdown ##Install dependencies and Detectron2

from builtins import any as b_any

def get_requirements_path():
    # Store requirements file in 'contents' directory
    current_dir = os.getcwd()
    dir_count = current_dir.count('/') - 1
    path = '../' * (dir_count) + 'requirements.txt'
    return path

def filter_files(file_list, filter_list):
    filtered_list = []
    for fname in file_list:
        if b_any(fname.split('==')[0] in s for s in filter_list):
            filtered_list.append(fname)
    return filtered_list

def build_requirements_file(before, after):
    path = get_requirements_path()

    # Exporting requirements.txt for local run
    !pip freeze > $path

    # Get minimum requirements file
    df = pd.read_csv(path, delimiter = "\n")
    mod_list = [m.split('.')[0] for m in after if not m in before]
    req_list_temp = df.values.tolist()
    req_list = [x[0] for x in req_list_temp]

    # Replace with package name and handle cases where import name is different to module name
    mod_name_list = [['sklearn', 'scikit-learn'], ['skimage', 'scikit-image']]
    mod_replace_list = [[x[1] for x in mod_name_list] if s in [x[0] for x in mod_name_list] else s for s in mod_list]
    filtered_list = filter_files(req_list, mod_replace_list)

    file=open(path,'w')
    for item in filtered_list:
        file.writelines(item + '\n')

    file.close()

import sys
before = [str(m) for m in sys.modules]

# install dependencies
#!pip install -U torch torchvision cython
!pip install -U 'git+https://github.com/facebookresearch/fvcore.git' 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI'
import torch, torchvision
import os
import pandas as pd
torch.__version__
 
!git clone https://github.com/facebookresearch/detectron2 detectron2_repo
!pip install -e detectron2_repo

!pip install wget

#Force session restart
exit(0)

# Build requirements file for local run
after = [str(m) for m in sys.modules]
build_requirements_file(before, after)<jupyter_output><empty_output><jupyter_text>**1.2. Restart your runtime**---** Ignore the following message error message. Your Runtime has automatically restarted. This is normal.**    **1.3. Load key dependencies**---<jupyter_code>Notebook_version = '1.13'
Network = 'Detectron 2D'


#@markdown ##Play this cell to load the required dependencies
import wget
# Some basic setup: 
import detectron2
from detectron2.utils.logger import setup_logger
setup_logger()
 
# import some common libraries
import numpy as np
import os, json, cv2, random
from google.colab.patches import cv2_imshow
 
import yaml
 
#Download the script to convert XML into COCO
 
wget.download("https://github.com/HenriquesLab/ZeroCostDL4Mic/raw/master/Tools/voc2coco.py", "/content")
 
 
# import some common detectron2 utilities
from detectron2 import model_zoo
from detectron2.engine import DefaultPredictor
from detectron2.config import get_cfg
from detectron2.utils.visualizer import Visualizer
from detectron2.data import MetadataCatalog, DatasetCatalog
from detectron2.utils.visualizer import ColorMode

from detectron2.data import DatasetCatalog, MetadataCatalog, build_detection_test_loader
from datetime import datetime
from detectron2.data.catalog import Metadata

from detectron2.config import get_cfg
from detectron2.data import DatasetCatalog, MetadataCatalog, build_detection_test_loader
from detectron2.evaluation import COCOEvaluator, inference_on_dataset
from detectron2.engine import DefaultTrainer
from detectron2.data.datasets import register_coco_instances
from detectron2.utils.visualizer import ColorMode
import glob
from detectron2.checkpoint import Checkpointer
from detectron2.config import get_cfg
import os
 
 
# ------- Common variable to all ZeroCostDL4Mic notebooks -------
import numpy as np
from matplotlib import pyplot as plt
import urllib
import os, random
import shutil 
import zipfile
from tifffile import imread, imsave
import time
import sys
 
from pathlib import Path
import pandas as pd
import csv
from glob import glob
from scipy import signal
from scipy import ndimage
from skimage import io
from sklearn.linear_model import LinearRegression
from skimage.util import img_as_uint
import matplotlib as mpl
from skimage.metrics import structural_similarity
from skimage.metrics import peak_signal_noise_ratio as psnr
from astropy.visualization import simple_norm
from skimage import img_as_float32
 
# Colors for the warning messages
class bcolors:
  WARNING = '\033[31m'
W  = '\033[0m'  # white (normal)
R  = '\033[31m' # red
 
#Disable some of the tensorflow warnings
import warnings
warnings.filterwarnings("ignore")
 
 
from detectron2.engine import DefaultTrainer
from detectron2.evaluation import COCOEvaluator
 
class CocoTrainer(DefaultTrainer):
 
  @classmethod
  def build_evaluator(cls, cfg, dataset_name, output_folder=None):
 
    if output_folder is None:
        os.makedirs("coco_eval", exist_ok=True)
        output_folder = "coco_eval"
 
    return COCOEvaluator(dataset_name, cfg, False, output_folder)
 
 
 
print("Librairies loaded")
 
# Check if this is the latest version of the notebook
All_notebook_versions = pd.read_csv("https://raw.githubusercontent.com/HenriquesLab/ZeroCostDL4Mic/master/Colab_notebooks/Latest_Notebook_versions.csv", dtype=str)
print('Notebook version: '+Notebook_version)
Latest_Notebook_version = All_notebook_versions[All_notebook_versions["Notebook"] == Network]['Version'].iloc[0]
print('Latest notebook version: '+Latest_Notebook_version)
if Notebook_version == Latest_Notebook_version:
  print("This notebook is up-to-date.")
else:
  print(bcolors.WARNING +"A new version of this notebook has been released. We recommend that you download it at https://github.com/HenriquesLab/ZeroCostDL4Mic/wiki")


 
#Failsafes
cell_ran_prediction = 0
cell_ran_training = 0
cell_ran_QC_training_dataset = 0
cell_ran_QC_QC_dataset = 0<jupyter_output><empty_output><jupyter_text>**2. Initialise the Colab session**---  **2.1. Check for GPU access**---By default, the session should be using Python 3 and GPU acceleration, but it is possible to ensure that these are set properly by doing the following:Go to **Runtime -> Change the Runtime type****Runtime type: Python 3** *(Python 3 is programming language in which this program is written)***Accelerator: GPU** *(Graphics processing unit)*<jupyter_code>#@markdown ##Run this cell to check if you have GPU access
#%tensorflow_version 1.x


import tensorflow as tf
if tf.test.gpu_device_name()=='':
  print('You do not have GPU access.') 
  print('Did you change your runtime ?') 
  print('If the runtime setting is correct then Google did not allocate a GPU for your session')
  print('Expect slow performance. To access GPU try reconnecting later')

else:
  print('You have GPU access')
  !nvidia-smi<jupyter_output><empty_output><jupyter_text>**2.2. Mount your Google Drive**--- To use this notebook on the data present in your Google Drive, you need to mount your Google Drive to this notebook. Play the cell below to mount your Google Drive and follow the link. In the new browser window, select your drive and select 'Allow', copy the code, paste into the cell and press enter. This will give Colab access to the data on the drive.  Once this is done, your data are available in the **Files** tab on the top left of notebook.<jupyter_code>#@markdown ##Play the cell to connect your Google Drive to Colab
 
#@markdown * Click on the URL. 
 
#@markdown * Sign in your Google Account. 
 
#@markdown * Copy the authorization code. 
 
#@markdown * Enter the authorization code. 
 
#@markdown * Click on "Files" site on the right. Refresh the site. Your Google Drive folder should now be available here as "drive". 
 
# mount user's Google Drive to Google Colab.
from google.colab import drive
drive.mount('/content/gdrive')<jupyter_output><empty_output><jupyter_text>** If you cannot see your files, reactivate your session by connecting to your hosted runtime.**  Connect to a hosted runtime.   **3. Select your parameters and paths**  **3.1. Setting main training parameters**---   **Paths for training, predictions and results****`Training_source:`, `Training_target`:** These are the paths to your folders containing the Training_source and the annotation data respectively. To find the paths of the folders containing the respective datasets, go to your Files on the left of the notebook, navigate to the folder containing your files and copy the path by right-clicking on the folder, **Copy path** and pasting it into the right box below.**`labels`:** Input the name of the differentes labels used to annotate your dataset (separated by a comma).**`model_name`:** Use only my_model -style, not my-model (Use "_" not "-"). Do not use spaces in the name. Avoid using the name of an existing model (saved in the same folder) as it will be overwritten.**`model_path`**: Enter the path where your model will be saved once trained (for instance your result folder).**Training Parameters****`number_of_iteration`:** Input how many iterations to use to train the network. Initial results can be observed using 1000 iterations but consider using 5000 or more iterations to train your models.  **Default value: 2000**    **Advanced Parameters - experienced users only****`batch_size:`** This parameter defines the number of patches seen in each training step.  Noise2Void requires a large batch size for stable training. Reduce this parameter if your GPU runs out of memory. **Default value: 128****`number_of_steps`:** Define the number of training steps by epoch. By default this parameter is calculated so that each image / patch is seen at least once per epoch. **Default value: Number of patch / batch_size****`percentage_validation`:**  Input the percentage of your training dataset you want to use to validate the network during the training. **Default value: 10****`initial_learning_rate`:** Input the initial value to be used as learning rate. **Default value: 0.0001**<jupyter_code># create DataGenerator-object.


#@markdown ###Path to training image(s): 
Training_source = "" #@param {type:"string"}
Training_target = "" #@param {type:"string"}

#@markdown ###Labels
#@markdown Input the name of the differentes labels present in your training dataset separated by a comma
labels = ""  #@param {type:"string"}


#@markdown ### Model name and path:
model_name = "" #@param {type:"string"}
model_path = "" #@param {type:"string"}

full_model_path = model_path+'/'+model_name+'/'


#@markdown ###Training Parameters
#@markdown Number of iterations:
number_of_iteration =  2000#@param {type:"number"}


#Here we store the informations related to our labels

list_of_labels = labels.split(", ")
with open('/content/labels.txt', 'w') as f:
    for item in list_of_labels:
        print(item, file=f)

number_of_labels = len(list_of_labels)


#@markdown ###Advanced Parameters

Use_Default_Advanced_Parameters = True#@param {type:"boolean"}

#@markdown ###If not, please input:
batch_size =  4#@param {type:"number"}
percentage_validation =  10#@param {type:"number"}
initial_learning_rate = 0.001 #@param {type:"number"}


if (Use_Default_Advanced_Parameters): 
  print("Default advanced parameters enabled")
  batch_size = 4
  percentage_validation = 10
  initial_learning_rate = 0.001

# Here we disable pre-trained model by default (in case the next cell is not ran)
Use_pretrained_model = True

# Here we disable data augmentation by default (in case the cell is not ran)

Use_Data_augmentation = True

# Here we split the data between training and validation
# Here we count the number of files in the training target folder
Filelist = os.listdir(Training_target)
number_files = len(Filelist)

File_for_validation = int((number_files)/percentage_validation)+1

#Here we split the training dataset between training and validation
# Everything is copied in the /Content Folder

Training_source_temp = "/content/training_source"

if os.path.exists(Training_source_temp):
  shutil.rmtree(Training_source_temp)
os.makedirs(Training_source_temp)

Training_target_temp = "/content/training_target"
if os.path.exists(Training_target_temp):
  shutil.rmtree(Training_target_temp)
os.makedirs(Training_target_temp)

Validation_source_temp = "/content/validation_source"

if os.path.exists(Validation_source_temp):
  shutil.rmtree(Validation_source_temp)
os.makedirs(Validation_source_temp)

Validation_target_temp = "/content/validation_target"
if os.path.exists(Validation_target_temp):
  shutil.rmtree(Validation_target_temp)
os.makedirs(Validation_target_temp)

list_source = os.listdir(os.path.join(Training_source))
list_target = os.listdir(os.path.join(Training_target))

#Move files into the temporary source and target directories:

  
for f in os.listdir(os.path.join(Training_source)):
  shutil.copy(Training_source+"/"+f, Training_source_temp+"/"+f)

for p in os.listdir(os.path.join(Training_target)):
  shutil.copy(Training_target+"/"+p, Training_target_temp+"/"+p)


list_source_temp = os.listdir(os.path.join(Training_source_temp))
list_target_temp = os.listdir(os.path.join(Training_target_temp))


#Here we move images to be used for validation
for i in range(File_for_validation):

  name = list_source_temp[i]
  shutil.move(Training_source_temp+"/"+name, Validation_source_temp+"/"+name)

  shortname_no_extension = name[:-4]

  shutil.move(Training_target_temp+"/"+shortname_no_extension+".xml", Validation_target_temp+"/"+shortname_no_extension+".xml")

# Here we convert the XML files into COCO format to be loaded in detectron2

#First we need to create list of labels to generate the json dictionaries

list_source_training_temp = os.listdir(os.path.join(Training_source_temp))
list_source_validation_temp = os.listdir(os.path.join(Validation_source_temp))


name_no_extension_training = []
for n in list_source_training_temp:
  name_no_extension_training.append(os.path.splitext(n)[0])

name_no_extension_validation = []
for n in list_source_validation_temp:
  name_no_extension_validation.append(os.path.splitext(n)[0])

#Save the list of labels as text file

with open('/content/training_files.txt', 'w') as f:
    for item in name_no_extension_training:
        print(item, end='\n', file=f)

with open('/content/validation_files.txt', 'w') as f:
    for item in name_no_extension_validation:
        print(item, end='\n', file=f)


file_output_training = Training_target_temp+"/output.json"
file_output_validation = Validation_target_temp+"/output.json"


os.chdir("/content")
!python voc2coco.py --ann_dir "$Training_target_temp" --output "$file_output_training" --ann_ids "/content/training_files.txt"  --labels "/content/labels.txt" --ext xml
!python voc2coco.py --ann_dir "$Validation_target_temp" --output "$file_output_validation" --ann_ids "/content/validation_files.txt" --labels "/content/labels.txt" --ext xml


os.chdir("/")

#Here we load the dataset to detectron2
if cell_ran_training == 0:
  from detectron2.data.datasets import register_coco_instances
  register_coco_instances("my_dataset_train", {}, Training_target_temp+"/output.json", Training_source_temp)
  register_coco_instances("my_dataset_val", {}, Validation_target_temp+"/output.json", Validation_source_temp)


#visualize training data
my_dataset_train_metadata = MetadataCatalog.get("my_dataset_train")

dataset_dicts = DatasetCatalog.get("my_dataset_train")

import random
from detectron2.utils.visualizer import Visualizer

for d in random.sample(dataset_dicts, 1):
    img = cv2.imread(d["file_name"])
    visualizer = Visualizer(img[:, :, ::-1], metadata=my_dataset_train_metadata, instance_mode=ColorMode.SEGMENTATION, scale=0.8)
    vis = visualizer.draw_dataset_dict(d)
    cv2_imshow(vis.get_image()[:, :, ::-1])

# failsafe
cell_ran_training = 1<jupyter_output><empty_output><jupyter_text>**3.2. Data augmentation** --- Data augmentation is currently enabled by default in this notebook. The option to disable data augmentation is not yet avaialble.   **3.3. Using weights from a pre-trained model as initial weights**---  Here, you can set the the path to a pre-trained model from which the weights can be extracted and used as a starting point for this training session. **This pre-trained model needs to be a Detectron2 model**.<jupyter_code># @markdown ##Loading weights from a pre-trained network

Use_pretrained_model = True #@param {type:"boolean"}

pretrained_model_choice = "Faster R-CNN" #@param ["Faster R-CNN","RetinaNet", "Model_from_file"]

#pretrained_model_choice = "Faster R-CNN" #@param ["Faster R-CNN", "RetinaNet", "RPN & Fast R-CNN", "Model_from_file"]



#@markdown ###If you chose "Model_from_file", please provide the path to the model folder:
pretrained_model_path = "" #@param {type:"string"}

# --------------------- Check if we load a previously trained model ------------------------
if Use_pretrained_model:

# --------------------- Load the model from the choosen path ------------------------
  if pretrained_model_choice == "Model_from_file":
    h5_file_path = pretrained_model_path
    print('Weights found in:')
    print(h5_file_path)
    print('will be loaded prior to training.')

    if not os.path.exists(h5_file_path) and Use_pretrained_model:
      print('WARNING pretrained model does not exist')
      h5_file_path = "COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml"
      print('The Faster R-CNN model will be used.')
      
  if pretrained_model_choice == "Faster R-CNN":
    h5_file_path = "COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml"
    print('The Faster R-CNN model will be used.')
  
  if pretrained_model_choice == "RetinaNet":
    h5_file_path = "COCO-Detection/retinanet_R_101_FPN_3x.yaml"
    print('The RetinaNet model will be used.')

  if pretrained_model_choice == "RPN & Fast R-CNN":
    h5_file_path = "COCO-Detection/fast_rcnn_R_50_FPN_1x.yaml"


if not Use_pretrained_model:
  h5_file_path = "COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml"
  print('The Faster R-CNN model will be used.')<jupyter_output><empty_output><jupyter_text>**4. Train the network**---  **4.1. Start Trainning**---When playing the cell below you should see updates after each epoch (round). Network training can take some time.* **CRITICAL NOTE:** Google Colab has a time limit for processing (to prevent using GPU power for datamining). Training time must be less than 12 hours! If training takes longer than 12 hours, please decrease the number of epochs or number of patches. Another way circumvent this is to save the parameters of the model after training and start training again from this point.<jupyter_code>#@markdown ##Start training

# Create the model folder

if os.path.exists(full_model_path):
  shutil.rmtree(full_model_path)
os.makedirs(full_model_path)

#Copy the label names in the model folder
shutil.copy("/content/labels.txt", full_model_path+"/"+"labels.txt")

#PDF export
#######################################
## MISSING 
#######################################
#To be added

start = time.time()

#Load the config files
cfg = get_cfg()

if pretrained_model_choice == "Model_from_file":
  cfg.merge_from_file(pretrained_model_path+"/config.yaml")

if not pretrained_model_choice == "Model_from_file":
  cfg.merge_from_file(model_zoo.get_config_file(h5_file_path))

cfg.DATASETS.TRAIN = ("my_dataset_train",)
cfg.DATASETS.TEST = ("my_dataset_val",)
cfg.OUTPUT_DIR= (full_model_path)
cfg.DATALOADER.NUM_WORKERS = 4

if pretrained_model_choice == "Model_from_file":
  cfg.MODEL.WEIGHTS = pretrained_model_path+"/model_final.pth"  # Let training initialize from model zoo

if not pretrained_model_choice == "Model_from_file":
  cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(h5_file_path)  # Let training initialize from model zoo

cfg.SOLVER.IMS_PER_BATCH = int(batch_size)
cfg.SOLVER.BASE_LR = initial_learning_rate

cfg.SOLVER.WARMUP_ITERS = 1000
cfg.SOLVER.MAX_ITER = int(number_of_iteration) #adjust up if val mAP is still rising, adjust down if overfit
cfg.SOLVER.STEPS = (1000, 1500)
cfg.SOLVER.GAMMA = 0.05

cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 512

if pretrained_model_choice == "Faster R-CNN":
  cfg.MODEL.ROI_HEADS.NUM_CLASSES = (number_of_labels) 

if pretrained_model_choice == "RetinaNet":
  cfg.MODEL.RETINANET.NUM_CLASSES = (number_of_labels) 

cfg.TEST.EVAL_PERIOD = 500
trainer = CocoTrainer(cfg)

trainer.resume_or_load(resume=False)
trainer.train()

#Save the config file after trainning
config= cfg.dump()  # print formatted configs

file1 = open(full_model_path+"/config.yaml", 'w') 
 
file1.writelines(config) 
file1.close() #to change file access modes

#Save the label file after trainning

dt = time.time() - start
mins, sec = divmod(dt, 60) 
hour, mins = divmod(mins, 60) 
print("Time elapsed:",hour, "hour(s)",mins,"min(s)",round(sec),"sec(s)")<jupyter_output><empty_output><jupyter_text>**4.2. Download your model(s) from Google Drive**---Once training is complete, the trained model is automatically saved on your Google Drive, in the **model_path** folder that was selected in Section 3. It is however wise to download the folder as all data can be erased at the next training if using the same folder.  **5. Evaluate your model**---This section allows the user to perform important quality checks on the validity and generalisability of the trained model. Detectron 2 requires you to reload your training dataset in order to perform the quality control step.**We highly recommend to perform quality control on all newly trained models.**<jupyter_code># model name and path
#@markdown ###Do you want to assess the model you just trained ?
Use_the_current_trained_model = True #@param {type:"boolean"}

#@markdown ###If not, please provide the path to the model folder as well as the location of your training dataset:

#@markdown ####Path to trained model to be assessed: 

QC_model_folder = "" #@param {type:"string"}

#@markdown ####Path to the image(s) used for training: 
Training_source = "" #@param {type:"string"}
Training_target = "" #@param {type:"string"}


#Here we define the loaded model name and path
QC_model_name = os.path.basename(QC_model_folder)
QC_model_path = os.path.dirname(QC_model_folder)


if (Use_the_current_trained_model): 
  QC_model_name = model_name
  QC_model_path = model_path


full_QC_model_path = QC_model_path+'/'+QC_model_name+'/'
if os.path.exists(full_QC_model_path):
  print("The "+QC_model_name+" network will be evaluated")

else:  
  print(bcolors.WARNING + '!! WARNING: The chosen model does not exist !!')
  print('Please make sure you provide a valid model path and model name before proceeding further.')

# Here we load the list of classes stored in the model folder
list_of_labels_QC =[]
with open(full_QC_model_path+'labels.txt', newline='') as csvfile:
    reader = csv.reader(csvfile)
    for row in csv.reader(csvfile):
        list_of_labels_QC.append(row[0])

#Here we create a list of color for later display
color_list = []
for i in range(len(list_of_labels_QC)):
  color = list(np.random.choice(range(256), size=3))
  color_list.append(color)

#Save the list of labels as text file  
if not (Use_the_current_trained_model):
  with open('/content/labels.txt', 'w') as f:
      for item in list_of_labels_QC:
          print(item, file=f)

  # Here we split the data between training and validation
  # Here we count the number of files in the training target folder
  Filelist = os.listdir(Training_target)
  number_files = len(Filelist)
  percentage_validation= 10

  File_for_validation = int((number_files)/percentage_validation)+1

  #Here we split the training dataset between training and validation
  # Everything is copied in the /Content Folder

  Training_source_temp = "/content/training_source"

  if os.path.exists(Training_source_temp):
    shutil.rmtree(Training_source_temp)
  os.makedirs(Training_source_temp)

  Training_target_temp = "/content/training_target"
  if os.path.exists(Training_target_temp):
    shutil.rmtree(Training_target_temp)
  os.makedirs(Training_target_temp)

  Validation_source_temp = "/content/validation_source"

  if os.path.exists(Validation_source_temp):
    shutil.rmtree(Validation_source_temp)
  os.makedirs(Validation_source_temp)

  Validation_target_temp = "/content/validation_target"
  if os.path.exists(Validation_target_temp):
    shutil.rmtree(Validation_target_temp)
  os.makedirs(Validation_target_temp)

  list_source = os.listdir(os.path.join(Training_source))
  list_target = os.listdir(os.path.join(Training_target))

#Move files into the temporary source and target directories:
  
  for f in os.listdir(os.path.join(Training_source)):
    shutil.copy(Training_source+"/"+f, Training_source_temp+"/"+f)

  for p in os.listdir(os.path.join(Training_target)):
    shutil.copy(Training_target+"/"+p, Training_target_temp+"/"+p)

  list_source_temp = os.listdir(os.path.join(Training_source_temp))
  list_target_temp = os.listdir(os.path.join(Training_target_temp))


#Here we move images to be used for validation
  for i in range(File_for_validation):

    name = list_source_temp[i]
    shutil.move(Training_source_temp+"/"+name, Validation_source_temp+"/"+name)

    shortname_no_extension = name[:-4]

    shutil.move(Training_target_temp+"/"+shortname_no_extension+".xml", Validation_target_temp+"/"+shortname_no_extension+".xml")


#First we need to create list of labels to generate the json dictionaries

  list_source_training_temp = os.listdir(os.path.join(Training_source_temp))
  list_source_validation_temp = os.listdir(os.path.join(Validation_source_temp))

  name_no_extension_training = []
  for n in list_source_training_temp:
    name_no_extension_training.append(os.path.splitext(n)[0])

  name_no_extension_validation = []
  for n in list_source_validation_temp:
    name_no_extension_validation.append(os.path.splitext(n)[0])

#Save the list of labels as text file

  with open('/content/training_files.txt', 'w') as f:
      for item in name_no_extension_training:
          print(item, end='\n', file=f)

  with open('/content/validation_files.txt', 'w') as f:
      for item in name_no_extension_validation:
          print(item, end='\n', file=f)

  file_output_training = Training_target_temp+"/output.json"
  file_output_validation = Validation_target_temp+"/output.json"

  os.chdir("/content")
  !python voc2coco.py --ann_dir "$Training_target_temp" --output "$file_output_training" --ann_ids "/content/training_files.txt"  --labels "/content/labels.txt" --ext xml
  !python voc2coco.py --ann_dir "$Validation_target_temp" --output "$file_output_validation" --ann_ids "/content/validation_files.txt" --labels "/content/labels.txt" --ext xml

  os.chdir("/")

#Here we load the dataset to detectron2
  if cell_ran_QC_training_dataset == 0:
    from detectron2.data.datasets import register_coco_instances
    register_coco_instances("my_dataset_train", {}, Training_target_temp+"/output.json", Training_source_temp)
    register_coco_instances("my_dataset_val", {}, Validation_target_temp+"/output.json", Validation_source_temp)
 
#Failsafe for later
cell_ran_QC_training_dataset = 1<jupyter_output><empty_output><jupyter_text>**5.1. Inspection of the loss function**---It is good practice to evaluate the training progress by studying if your model is slowly improving over time. The following cell will allow you to load Tensorboard and investigate how several metric evolved over time (iterations).<jupyter_code>#@markdown ##Play the cell to load tensorboard
%load_ext tensorboard
%tensorboard --logdir "$full_QC_model_path"<jupyter_output><empty_output><jupyter_text>**5.2. Error mapping and quality metrics estimation**---This section will compare the predictions generated by your model against ground-truth. Additionally, the below cell will show the mAP value of the model on the QC data If you want to read in more detail about this score, we recommend [this brief explanation](https://medium.com/@jonathan_hui/map-mean-average-precision-for-object-detection-45c121a31173). The images provided in the "Source_QC_folder" and "Target_QC_folder" should contain images (e.g. as .png) and annotations (.xml files)!**mAP score:** This refers to the mean average precision of the model on the given dataset. This value gives an indication how precise the predictions of the classes on this dataset are when compared to the ground-truth. Values closer to 1 indicate a good fit.<jupyter_code>#@markdown ##Choose the folders that contain your Quality Control dataset

Source_QC_folder = "" #@param{type:"string"}
Target_QC_folder = "" #@param{type:"string"}

if cell_ran_QC_QC_dataset == 0:
#Save the list of labels as text file  
  with open('/content/labels_QC.txt', 'w') as f:
      for item in list_of_labels_QC:
          print(item, file=f)

#Here we create temp folder for the QC

  QC_source_temp = "/content/QC_source"

  if os.path.exists(QC_source_temp):
    shutil.rmtree(QC_source_temp)
  os.makedirs(QC_source_temp)

  QC_target_temp = "/content/QC_target"
  if os.path.exists(QC_target_temp):
    shutil.rmtree(QC_target_temp)
  os.makedirs(QC_target_temp)

# Create a quality control/Prediction Folder
  if os.path.exists(QC_model_path+"/"+QC_model_name+"/Quality Control/Prediction"):
    shutil.rmtree(QC_model_path+"/"+QC_model_name+"/Quality Control/Prediction")

  os.makedirs(QC_model_path+"/"+QC_model_name+"/Quality Control/Prediction")

#Here we move the QC files to the temp

  for f in os.listdir(os.path.join(Source_QC_folder)):
    shutil.copy(Source_QC_folder+"/"+f, QC_source_temp+"/"+f)

  for p in os.listdir(os.path.join(Target_QC_folder)):
    shutil.copy(Target_QC_folder+"/"+p, QC_target_temp+"/"+p)

#Here we convert the XML files into JSON
#Save the list of files

  list_source_QC_temp = os.listdir(os.path.join(QC_source_temp))

  name_no_extension_QC = []
  for n in list_source_QC_temp:
    name_no_extension_QC.append(os.path.splitext(n)[0])

  with open('/content/QC_files.txt', 'w') as f:
      for item in name_no_extension_QC:
          print(item, end='\n', file=f)

#Convert XML into JSON
  file_output_QC = QC_target_temp+"/output.json"

  os.chdir("/content")
  !python voc2coco.py --ann_dir "$QC_target_temp" --output "$file_output_QC" --ann_ids "/content/QC_files.txt"  --labels "/content/labels.txt" --ext xml

  os.chdir("/")


#Here we register the QC dataset
  register_coco_instances("my_dataset_QC", {}, QC_target_temp+"/output.json", QC_source_temp)
  cell_ran_QC_QC_dataset = 1


#Load the model to use
cfg = get_cfg()
cfg.merge_from_file(full_QC_model_path+"config.yaml")
cfg.MODEL.WEIGHTS = os.path.join(full_QC_model_path, "model_final.pth")
cfg.DATASETS.TEST = ("my_dataset_QC", )
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5

#Metadata
test_metadata = MetadataCatalog.get("my_dataset_QC")
test_metadata.set(thing_color = color_list)

# For the evaluation we need to load the trainer
trainer = CocoTrainer(cfg)
trainer.resume_or_load(resume=True)

# Here we need to load the predictor

predictor = DefaultPredictor(cfg)
evaluator = COCOEvaluator("my_dataset_QC", cfg, False, output_dir=QC_model_path+"/"+QC_model_name+"/Quality Control/Prediction")
val_loader = build_detection_test_loader(cfg, "my_dataset_QC")
inference_on_dataset(trainer.model, val_loader, evaluator)


print("A prediction is displayed")

dataset_QC_dicts = DatasetCatalog.get("my_dataset_QC")

for d in random.sample(dataset_QC_dicts, 1):
    print("Ground Truth")
    img = cv2.imread(d["file_name"])
    visualizer = Visualizer(img[:, :, ::-1], metadata=test_metadata, instance_mode=ColorMode.SEGMENTATION, scale=0.5)
    vis = visualizer.draw_dataset_dict(d)
    cv2_imshow(vis.get_image()[:, :, ::-1])

    print("A prediction is displayed")
    im = cv2.imread(d["file_name"])
    outputs = predictor(im)
    v = Visualizer(im[:, :, ::-1],
              metadata=test_metadata,
              instance_mode=ColorMode.SEGMENTATION, 
              scale=0.5
                )
    out = v.draw_instance_predictions(outputs["instances"].to("cpu"))
    cv2_imshow(out.get_image()[:, :, ::-1])

cell_ran_QC_QC_dataset = 1<jupyter_output><empty_output><jupyter_text>**6. Using the trained model**---In this section the unseen data is processed using the trained model (in section 4). First, your unseen images are uploaded and prepared for prediction. After that your trained model from section 4 is activated and finally saved into your Google Drive.  **6.1. Generate prediction(s) from unseen dataset**---The current trained model (from section 4.2) can now be used to process images. If an older model needs to be used, please untick the **Use_the_current_trained_model** box and enter the name and path of the model to use. Predicted output images are saved in your **Result_folder** folder as restored image stacks (ImageJ-compatible TIFF images).**`Data_folder`:** This folder should contains the images that you want to predict using the network that you will train.**`Result_folder`:** This folder will contain the predicted output images.<jupyter_code>#@markdown ### Provide the path to your dataset and to the folder where the prediction will be saved, then play the cell to predict output on your unseen images.

#@markdown ###Path to data to analyse and where predicted output should be saved:
Data_folder = "" #@param {type:"string"}
Result_folder = "" #@param {type:"string"}

# model name and path
#@markdown ###Do you want to use the current trained model?
Use_the_current_trained_model = True #@param {type:"boolean"}

#@markdown ###If not, please provide the path to the model folder as well as the location of your training dataset:

#@markdown ####Path to trained model to be assessed: 

Prediction_model_folder = "" #@param {type:"string"}


#Here we find the loaded model name and parent path
Prediction_model_name = os.path.basename(Prediction_model_folder)
Prediction_model_path = os.path.dirname(Prediction_model_folder)

if (Use_the_current_trained_model): 
  print("Using current trained network")
  Prediction_model_name = model_name
  Prediction_model_path = model_path

full_Prediction_model_path = Prediction_model_path+'/'+Prediction_model_name+'/'


if os.path.exists(full_Prediction_model_path):
  print("The "+Prediction_model_name+" network will be used.")
else:
  print(bcolors.WARNING +'!! WARNING: The chosen model does not exist !!')
  print('Please make sure you provide a valid model path and model name before proceeding further.')

#Here we will load the label file

list_of_labels_predictions =[]
with open(full_Prediction_model_path+'labels.txt', newline='') as csvfile:
    reader = csv.reader(csvfile)
    for row in csv.reader(csvfile):
        list_of_labels_predictions.append(row[0])

#Here we create a list of color
color_list = []
for i in range(len(list_of_labels_predictions)):
  color = list(np.random.choice(range(256), size=3))
  color_list.append(color)

#Activate the pretrained model. 
# Create config
cfg = get_cfg()
cfg.merge_from_file(full_Prediction_model_path+"config.yaml")
cfg.MODEL.WEIGHTS = os.path.join(full_Prediction_model_path, "model_final.pth")
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5  # set threshold for this model

# Create predictor
predictor = DefaultPredictor(cfg)

#Load the metadata from the prediction file
prediction_metadata = Metadata()
prediction_metadata.set(thing_classes = list_of_labels_predictions)
prediction_metadata.set(thing_color = color_list)

start = datetime.now()

validation_folder = Path(Data_folder)

for i, file in enumerate(validation_folder.glob("*.png")):
    # this loop opens the .png files from the val-folder, creates a dict with the file
    # information, plots visualizations and saves the result as .pkl files.
    file = str(file)
    file_name = file.split("/")[-1]
    im = cv2.imread(file)

    #Prediction are done here
    outputs = predictor(im)

    #here we extract the results into numpy arrays

    Classes_predictions = outputs["instances"].pred_classes.cpu().data.numpy()

    boxes_predictions = outputs["instances"].pred_boxes.tensor.cpu().numpy()
    Score_predictions = outputs["instances"].scores.cpu().data.numpy()
 
    #here we save the results into a csv file
    prediction_csv = Result_folder+"/"+file_name+"_predictions.csv"

    with open(prediction_csv, 'w') as f:
      writer = csv.writer(f)
      writer.writerow(['x1','y1','x2','y2','box width','box height', 'class', 'score' ])    

      for i in range(len(boxes_predictions)):

        x1 = boxes_predictions[i][0]
        y1 = boxes_predictions[i][1]
        x2 = boxes_predictions[i][2]
        y2 = boxes_predictions[i][3]
        box_width = x2 - x1
        box_height = y2 -y1

        writer.writerow([str(x1), str(y1), str(x2), str(y2), str(box_width), str(box_height), str(list_of_labels_predictions[Classes_predictions[i]]), Score_predictions[i]])


# The last example is displayed   
v = Visualizer(im, metadata=prediction_metadata, instance_mode=ColorMode.SEGMENTATION, scale=1)
v = v.draw_instance_predictions(outputs["instances"].to("cpu"))    
plt.figure(figsize=(20,20))
plt.imshow(v.get_image()[:, :, ::-1])
plt.axis('off');
plt.savefig(Result_folder+"/"+file_name)
    
print("Time needed for inferencing:", datetime.now() - start)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.0935181425565686, 'fraction_numerical': 0.007087224539514968, 'mean_word_length': 4.953521591033953, 'pattern_counts': {'":': 10, '<': 49, '<?xml version=': 0, '>': 52, 'https://': 15, 'lorem ipsum': 0, 'www.': 5, 'xml': 15}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '37257', 'license': 'MIT', 'n_tokens_mistral': 16255, 'n_tokens_neox': 15499, 'n_words': 5936, 'path': 'Colab_notebooks/Beta notebooks/Detectron2_2D_ZeroCostDL4Mic.ipynb', 'repo_name': 'junelsolis/ZeroCostDL4Mic', 'size': '54182'}