Model Card for aquaculture_oysters

Model Details

A fine-tuned YOLO11 model for sizing aquaculture oyster sample populations

Model Description

This model detects two object classes: triploid Crassostrea virginica oysters from various stages of aquaculture production and round sizing standards. Size standards should be flat disk-like objects. It was fine-tuned from the Ultralytics YOLO11n pretrained object detection model by using custom images of various sampled oyster populations and various different size standards.

  • Developed by: Craig S. Echt
  • Model type: Object Detection
  • Language(s) (NLP): American English
  • License: gpl-3.0
  • Finetuned from model: yolo11n

Model Sources

Uses

Its intended use is calculation of oyster population size metrics from filtered bounding box coordinates in images of dozens to hundreds of oysters that include one or a few disks of known diameter. It may be helpful to oyster farmers and researchers as an alternative to rough size estimates from tumblers or manual sizing of individual oysters.

Direct Use

A full GUI application is available at https://github.com/csecht/oyster-sizer.

An abbreviated demo Python script is below.

Bias, Risks, and Limitations

The model is not trained to distinguish between oysters and other bivalve species, e.g. scallops. Its intended use is with samples of aquaculture oyster populations at a particular stage of growth. That is, populations that are not mixed with other shell types. It may be possible, however, to use to size sample populations of bivalves.

How to Get Started with the Model

Download these files into a local folder: aquaculture_oysters.pt, oyster_sample.jpg, oysters.py. The python script in oysters.py is printed below.

From within the local folder, create a new venv virtual environment (using whatever venv folder name you like; here oyster_venv is used):

python3 -m venv oyster_venv

Activate this new virtual environment:

source oyster_venv/bin/activate (Linux and macOS) oyster_venv\Scripts\activate (Windows)

Update the PIP installer and install the most recent Ultralytics package in the active virtual environment.

python3 -m pip install --upgrade pip python3 -m pip install ultralytics

Run oysters.py: python3 -m oysters

oysters.py code:

    """
    Python3 script for YOLO prediction and sizing of oyster objects.
    
    """
    
    from ultralytics import YOLO
    
    # Locally written directories
    results_dir = 'oyster_yolo_results'
    predict_name = 'example_oyster_results'
    
    # Files from this aquaculture_oysters HF repository
    model = YOLO('aquaculture_oysters.pt')
    oyster_img =  'oyster_sample.jpg'
    
    # The size standard disk diameter. In this case, as millimeters, 
    #  using a cutout from a 3 inch hockey puck.
    std_mm = 76.2
    
    # Run inference with these arguments
    prediction_kwargs = dict(
        save=True,  # saves image to project/name
        save_txt=True,  # saves relative bounding box coordinates
        save_conf=True,  # includes conf scores
        augment=False,
        show_labels=True,
        line_width=2,
        project=results_dir,
        name=predict_name,
        exist_ok=False,
    )
    
    results = model.predict(
        source=oyster_img,
        half=False,
        imgsz=960,
        conf=0.7,
        device='cpu',
        iou=0.7,
        max_det=400,
        classes=[0,1],  #  0 is 'disk', 1 is 'oyster'.
        **prediction_kwargs
    )
    
    # Display detection bounding boxes with class names and confidence values.
    results[0].show(line_width=2)
    
    # Calculate and print size metrics, Are based on longest bounding box dimension.
    # Sizes do not account for longer lengths of oysters oriented on the diagonal.
    #  An empirically determined correction factor is recommended for better accuracy.
    #  A good correction function is used in the companion GitHub repository.
    boxes_tensor = results[0].boxes.xywh
    boxes_numpy = boxes_tensor.cpu().numpy().astype(int)
    w_h = boxes_numpy[:, 2:4]
    px_lengths = w_h.max(axis=1)
    
    classes = results[0].boxes.cls
    class_distribution = classes.cpu().numpy().astype(int)
    
    num_disks = len(class_distribution[class_distribution == 0])
    num_oysters = len(class_distribution[class_distribution == 1])
    oyster_px_sizes = px_lengths[class_distribution == 1]
    disk_px_sizes = px_lengths[class_distribution == 0]
    px2mm_factor = std_mm / disk_px_sizes.mean()
    oyster_mean_mm = round(oyster_px_sizes.mean() * px2mm_factor, 2)
    smallest = round(oyster_px_sizes.min() * px2mm_factor, 2)
    largest = round(oyster_px_sizes.max() * px2mm_factor, 2)
    
    print(f'Mean oyster size, mm: {oyster_mean_mm}')
    print(f'Oyster size range, mm: [{smallest} -- {largest}]')

Training Details

Training Data

The images and yolo-formatted labels used for training and validation (testing) are in those respective folders under Files and versions of this repository. Images are also in the aquaculture-oysters Dataset. These data have just two classes, disk and oyster.

Training Procedure

Versions and resources: Ultralytics 8.3.38 Python-3.12.3 torch-2.5.1+cu124 CUDA:0 (NVIDIA GeForce RTX 4070, 12002MiB)

Initial PyTorch training with yolo11n.pt weights was for 125 epochs, an image size of 960, batch size of 20, and the AdamW optimizer.

The resulting best.pt model was then tuned for 50 epochs over 300 iterations.

Hyperparameters from that best tune iteration, #233, were used to fine-tune the initial oyster model:

hyperparam_args233 = {
    'lr0': 0.00242,
    'lrf': 0.01009,
    'momentum': 0.92746,
    'weight_decay': 0.00038,
    'warmup_epochs': 1.94011,
    'warmup_momentum': 0.47865,
    'box': 5.89996,
    'cls': 0.27165,
    'dfl': 1.23119,
    'hsv_h': 0.01303,
    'hsv_s': 0.32101,
    'hsv_v': 0.40969,
    'degrees': 0.0,
    'translate': 0.15574,
    'scale': 0.75304,
    'shear': 0.0,
    'perspective': 0.0,
    'flipud': 0.0,
    'fliplr': 0.58715,
    'bgr': 0.0,
    'mosaic': 1.0,
    'mixup': 0.0,
    'copy_paste': 0.0,
}

Weights of the resulting best.pt (renamed here as aquaculture_oysters.pt) gave a mAP50-95(B) of 0.93349.

Results

Using the oyster_sample.jpg image with the oyster.py script, expected Terminal output and sizing results:

image 1/1 /home/craig/Desktop/oyster_sample.jpg: 960x768 3 disks, 105 oysters, 2903.9ms
Speed: 13.3ms preprocess, 2903.9ms inference, 28.1ms postprocess per image at shape (1, 3, 960, 768)
Results saved to oyster_yolo_results/example_oyster_results
1 label saved to oyster_yolo_results/example_oyster_results/labels
Mean oyster size, mm: 58.71
Oyster size range, mm: [47.22 -- 69.1]

Resulting image (2928 x 3761), saved to the oyster_yolo_results folder:

oysters with size annotations{width=488 height=626}

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model is not currently available via any of the supported Inference Providers.
The model cannot be deployed to the HF Inference API: The model has no library tag.