Add professional, light-themed dashboard
Browse files- .gitattributes +2 -0
- Dockerfile +4 -0
- app/.DS_Store +0 -0
- app/main.py +25 -6
- docs/.DS_Store +0 -0
- docs/dev/HF-MODELS.md +55 -0
- docs/dev/HF-QUICKSTART.md +117 -0
- docs/dev/SEAMO-GRADIO.md +0 -0
- docs/gradio/.DS_Store +0 -0
- docs/gradio/Dockerfile +10 -0
- docs/gradio/README.md +16 -0
- docs/gradio/app.py +31 -0
- docs/gradio/images/.DS_Store +0 -0
- docs/gradio/images/red_fish.png +3 -0
- docs/gradio/images/red_fish_2.png +3 -0
- docs/gradio/inference.py +69 -0
- docs/gradio/mbari-mb-benthic-33k.names +691 -0
- docs/gradio/mbari-mb-benthic-33k_stats.txt +691 -0
- docs/gradio/requirements.txt +2 -0
- docs/gradio/tator_inference.py +100 -0
- requirements.txt +3 -0
- static/css/dashboard.css +356 -0
- static/css/main.css +275 -0
- static/js/dashboard.js +250 -0
- static/js/main.js +90 -0
- templates/base.html +59 -0
- templates/dashboard.html +149 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
docs/gradio/images/red_fish_2.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
docs/gradio/images/red_fish.png filter=lfs diff=lfs merge=lfs -text
|
Dockerfile
CHANGED
|
@@ -67,6 +67,10 @@ COPY --chown=user --from=model-builder /models $HOME/app/models
|
|
| 67 |
# Copy the application code
|
| 68 |
COPY --chown=user ./app app
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
# Create necessary directories
|
| 71 |
RUN mkdir -p $HOME/.cache/huggingface $HOME/.cache/torch
|
| 72 |
|
|
|
|
| 67 |
# Copy the application code
|
| 68 |
COPY --chown=user ./app app
|
| 69 |
|
| 70 |
+
# Copy templates and static files for dashboard
|
| 71 |
+
COPY --chown=user ./templates templates
|
| 72 |
+
COPY --chown=user ./static static
|
| 73 |
+
|
| 74 |
# Create necessary directories
|
| 75 |
RUN mkdir -p $HOME/.cache/huggingface $HOME/.cache/torch
|
| 76 |
|
app/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
app/main.py
CHANGED
|
@@ -8,7 +8,9 @@ import asyncio
|
|
| 8 |
from contextlib import asynccontextmanager
|
| 9 |
from fastapi import FastAPI, HTTPException, Request
|
| 10 |
from fastapi.middleware.cors import CORSMiddleware
|
| 11 |
-
from fastapi.responses import JSONResponse
|
|
|
|
|
|
|
| 12 |
import uvicorn
|
| 13 |
|
| 14 |
from app.core.config import settings
|
|
@@ -57,6 +59,10 @@ app = FastAPI(
|
|
| 57 |
lifespan=lifespan
|
| 58 |
)
|
| 59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
# Add CORS middleware
|
| 61 |
app.add_middleware(
|
| 62 |
CORSMiddleware,
|
|
@@ -86,18 +92,31 @@ async def global_exception_handler(request: Request, exc: Exception):
|
|
| 86 |
app.include_router(api_router, prefix=settings.API_V1_STR)
|
| 87 |
|
| 88 |
|
| 89 |
-
#
|
| 90 |
-
@app.get("/", tags=["
|
| 91 |
-
async def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
"""
|
| 93 |
-
|
| 94 |
"""
|
| 95 |
return {
|
| 96 |
"message": "Marine Species Identification API",
|
| 97 |
"version": settings.VERSION,
|
| 98 |
"docs": "/docs",
|
| 99 |
"health": f"{settings.API_V1_STR}/health",
|
| 100 |
-
"api_info": f"{settings.API_V1_STR}/info"
|
|
|
|
| 101 |
}
|
| 102 |
|
| 103 |
|
|
|
|
| 8 |
from contextlib import asynccontextmanager
|
| 9 |
from fastapi import FastAPI, HTTPException, Request
|
| 10 |
from fastapi.middleware.cors import CORSMiddleware
|
| 11 |
+
from fastapi.responses import JSONResponse, HTMLResponse
|
| 12 |
+
from fastapi.staticfiles import StaticFiles
|
| 13 |
+
from fastapi.templating import Jinja2Templates
|
| 14 |
import uvicorn
|
| 15 |
|
| 16 |
from app.core.config import settings
|
|
|
|
| 59 |
lifespan=lifespan
|
| 60 |
)
|
| 61 |
|
| 62 |
+
# Mount static files and templates (for dashboard)
|
| 63 |
+
app.mount("/static", StaticFiles(directory="static"), name="static")
|
| 64 |
+
templates = Jinja2Templates(directory="templates")
|
| 65 |
+
|
| 66 |
# Add CORS middleware
|
| 67 |
app.add_middleware(
|
| 68 |
CORSMiddleware,
|
|
|
|
| 92 |
app.include_router(api_router, prefix=settings.API_V1_STR)
|
| 93 |
|
| 94 |
|
| 95 |
+
# Dashboard endpoint (new web interface)
|
| 96 |
+
@app.get("/", response_class=HTMLResponse, tags=["Dashboard"])
|
| 97 |
+
async def dashboard(request: Request):
|
| 98 |
+
"""
|
| 99 |
+
Main dashboard for marine species identification.
|
| 100 |
+
Provides a web interface for testing the API.
|
| 101 |
+
"""
|
| 102 |
+
return templates.TemplateResponse("dashboard.html", {
|
| 103 |
+
"request": request,
|
| 104 |
+
"active_tab": "dashboard"
|
| 105 |
+
})
|
| 106 |
+
|
| 107 |
+
# API root endpoint (moved to /api for clarity)
|
| 108 |
+
@app.get("/api", tags=["Root"])
|
| 109 |
+
async def api_root():
|
| 110 |
"""
|
| 111 |
+
API root endpoint providing basic API information.
|
| 112 |
"""
|
| 113 |
return {
|
| 114 |
"message": "Marine Species Identification API",
|
| 115 |
"version": settings.VERSION,
|
| 116 |
"docs": "/docs",
|
| 117 |
"health": f"{settings.API_V1_STR}/health",
|
| 118 |
+
"api_info": f"{settings.API_V1_STR}/info",
|
| 119 |
+
"dashboard": "/"
|
| 120 |
}
|
| 121 |
|
| 122 |
|
docs/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
docs/dev/HF-MODELS.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Here is an example of a dockerfile of a fastapi app that uses my self hosted model
|
| 2 |
+
|
| 3 |
+
# Dockerfile for Sema Translation API on HuggingFace Spaces
|
| 4 |
+
# Multi-stage build to handle model downloading with proper permissions
|
| 5 |
+
|
| 6 |
+
# Stage 1: Download models as root
|
| 7 |
+
FROM python:3.10-slim AS model-builder
|
| 8 |
+
|
| 9 |
+
# Install huggingface_hub for downloading models
|
| 10 |
+
RUN pip install huggingface_hub
|
| 11 |
+
|
| 12 |
+
# Download models from sematech/sema-utils
|
| 13 |
+
RUN python -c "\
|
| 14 |
+
from huggingface_hub import hf_hub_download; \
|
| 15 |
+
hf_hub_download('sematech/sema-utils', 'spm.model'); \
|
| 16 |
+
hf_hub_download('sematech/sema-utils', 'lid218e.bin'); \
|
| 17 |
+
hf_hub_download('sematech/sema-utils', 'translation_models/sematrans-3.3B/model.bin'); \
|
| 18 |
+
hf_hub_download('sematech/sema-utils', 'translation_models/sematrans-3.3B/config.json'); \
|
| 19 |
+
hf_hub_download('sematech/sema-utils', 'translation_models/sematrans-3.3B/shared_vocabulary.txt')"
|
| 20 |
+
|
| 21 |
+
# Stage 2: Build the application
|
| 22 |
+
FROM python:3.10-slim
|
| 23 |
+
|
| 24 |
+
# Set up a new user named "user" with user ID 1000
|
| 25 |
+
RUN useradd -m -u 1000 user
|
| 26 |
+
# Switch to the "user" user
|
| 27 |
+
USER user
|
| 28 |
+
# Set home to the user's home directory
|
| 29 |
+
ENV HOME=/home/user \
|
| 30 |
+
PATH=/home/user/.local/bin:$PATH
|
| 31 |
+
|
| 32 |
+
# Set the working directory to the user's home directory
|
| 33 |
+
WORKDIR $HOME/app
|
| 34 |
+
|
| 35 |
+
# Set environment variables for HuggingFace
|
| 36 |
+
ENV HF_HUB_OFFLINE=1
|
| 37 |
+
ENV TRANSFORMERS_NO_ADVISORY_WARNINGS=1
|
| 38 |
+
|
| 39 |
+
# Copy the requirements file and install dependencies
|
| 40 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
| 41 |
+
RUN pip install --no-cache-dir --upgrade pip
|
| 42 |
+
RUN pip install --no-cache-dir --user -r requirements.txt
|
| 43 |
+
|
| 44 |
+
# Copy the downloaded models from the builder stage
|
| 45 |
+
COPY --chown=user --from=model-builder /root/.cache/huggingface $HOME/.cache/huggingface
|
| 46 |
+
|
| 47 |
+
# Copy the application code
|
| 48 |
+
COPY --chown=user ./app app
|
| 49 |
+
|
| 50 |
+
# Expose port 7860 (HuggingFace Spaces standard)
|
| 51 |
+
EXPOSE 7860
|
| 52 |
+
|
| 53 |
+
# Tell uvicorn to run on port 7860, which is the standard for HF Spaces
|
| 54 |
+
# Use 0.0.0.0 to make it accessible from outside the container
|
| 55 |
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860"]
|
docs/dev/HF-QUICKSTART.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
π³ Get started with your Docker Space!
|
| 2 |
+
Your new Space has been created, follow these steps to get started (or read the full documentation)
|
| 3 |
+
|
| 4 |
+
Start by cloning this repo by using:
|
| 5 |
+
|
| 6 |
+
Use an access token as git password/credential
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
# When prompted for a password, use an access token with write permissions.
|
| 10 |
+
# Generate one from your settings: https://huggingface.co/settings/tokens
|
| 11 |
+
git clone https://huggingface.co/spaces/seamo-ai/fishapi
|
| 12 |
+
|
| 13 |
+
# Make sure hf CLI is installed: pip install -U "huggingface_hub[cli]"
|
| 14 |
+
hf download seamo-ai/fishapi --repo-type=space
|
| 15 |
+
Let's create a simple Python app using FastAPI:
|
| 16 |
+
|
| 17 |
+
requirements.txt
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
fastapi
|
| 21 |
+
uvicorn[standard]
|
| 22 |
+
Hint You can also create the requirements file file directly in your browser.
|
| 23 |
+
app.py
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
from fastapi import FastAPI
|
| 27 |
+
|
| 28 |
+
app = FastAPI()
|
| 29 |
+
|
| 30 |
+
@app.get("/")
|
| 31 |
+
def greet_json():
|
| 32 |
+
return {"Hello": "World!"}
|
| 33 |
+
Hint You can also create the app file file directly in your browser.
|
| 34 |
+
Create your Dockerfile:
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
# Read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
|
| 38 |
+
# you will also find guides on how best to write your Dockerfile
|
| 39 |
+
|
| 40 |
+
FROM python:3.9
|
| 41 |
+
|
| 42 |
+
RUN useradd -m -u 1000 user
|
| 43 |
+
USER user
|
| 44 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
| 45 |
+
|
| 46 |
+
WORKDIR /app
|
| 47 |
+
|
| 48 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
| 49 |
+
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
| 50 |
+
|
| 51 |
+
COPY --chown=user . /app
|
| 52 |
+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
| 53 |
+
Hint Alternatively, you can create the Dockerfile file directly in your browser.
|
| 54 |
+
Then commit and push:
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
git add requirements.txt app.py Dockerfile
|
| 58 |
+
git commit -m "Add application file"
|
| 59 |
+
git push
|
| 60 |
+
Finally, your Space should be running on this page after a few moments!
|
| 61 |
+
|
| 62 |
+
App port
|
| 63 |
+
|
| 64 |
+
Your Docker Space needs to listen on port 7860.
|
| 65 |
+
|
| 66 |
+
Personalize your Space
|
| 67 |
+
|
| 68 |
+
Make your Space stand out by customizing its emoji, colors, and description by editing metadata in its README.md file.
|
| 69 |
+
|
| 70 |
+
Documentation
|
| 71 |
+
|
| 72 |
+
Read the full documentation for Docker Spaces [here](https://huggingface.co/docs/hub/spaces-sdks-docker).
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
Seamo Model card
|
| 76 |
+
seamo-ai/marina-species-v1
|
| 77 |
+
|
| 78 |
+
License:
|
| 79 |
+
apache-2.0
|
| 80 |
+
Model card
|
| 81 |
+
Files and versions
|
| 82 |
+
Community
|
| 83 |
+
Settings
|
| 84 |
+
Getting started with your model
|
| 85 |
+
Complete model information
|
| 86 |
+
Add metadata and complete your model card to make your model more discoverable.
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
Push your model files
|
| 90 |
+
Upload your model weights to this repository.
|
| 91 |
+
|
| 92 |
+
CLI
|
| 93 |
+
Python
|
| 94 |
+
Git
|
| 95 |
+
HTTPS
|
| 96 |
+
SSH
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
brew install huggingface-cli
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
hf auth login
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
hf upload seamo-ai/marina-species-v1 .
|
| 106 |
+
You can also upload directly from the website using the File Uploader.
|
| 107 |
+
|
| 108 |
+
Preparing a significant release? Consult our guide to improve your model page and extend its impact and reach.
|
| 109 |
+
Downloads last month
|
| 110 |
+
-
|
| 111 |
+
|
| 112 |
+
Downloads are not tracked for this model.
|
| 113 |
+
How to track
|
| 114 |
+
Inference Providers
|
| 115 |
+
NEW
|
| 116 |
+
This model isn't deployed by any Inference Provider.
|
| 117 |
+
|
docs/dev/SEAMO-GRADIO.md
ADDED
|
File without changes
|
docs/gradio/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
docs/gradio/Dockerfile
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.7
|
| 2 |
+
|
| 3 |
+
RUN apt-get update \
|
| 4 |
+
&& apt-get install ffmpeg libsm6 libxext6 -y
|
| 5 |
+
|
| 6 |
+
RUN pip install yolov5 tator gradio
|
| 7 |
+
|
| 8 |
+
COPY . ./
|
| 9 |
+
|
| 10 |
+
CMD [ "python", "-u", "./tator_inference.py" ]
|
docs/gradio/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Seamore
|
| 3 |
+
emoji: π
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: indigo
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 3.47.1
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
This is a gradio app for the yolo 5 model that identifies fish species.
|
| 16 |
+
|
docs/gradio/app.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import glob
|
| 2 |
+
import gradio as gr
|
| 3 |
+
from inference import *
|
| 4 |
+
from PIL import Image
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def gradio_app(image_path):
|
| 8 |
+
"""A function that send the file to the inference pipeline, and filters
|
| 9 |
+
some predictions before outputting to gradio interface."""
|
| 10 |
+
|
| 11 |
+
predictions = run_inference(image_path)
|
| 12 |
+
|
| 13 |
+
out_img = Image.fromarray(predictions.render()[0])
|
| 14 |
+
|
| 15 |
+
return out_img
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
Title = "Marine Life Identification"
|
| 19 |
+
description = (
|
| 20 |
+
""
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
examples = glob.glob("images/*.png")
|
| 24 |
+
|
| 25 |
+
gr.Interface(gradio_app,
|
| 26 |
+
inputs=[gr.inputs.Image(type="filepath")],
|
| 27 |
+
outputs=gr.outputs.Image(type="pil"),
|
| 28 |
+
enable_queue=True,
|
| 29 |
+
title=Title,
|
| 30 |
+
description=description,
|
| 31 |
+
examples=examples).launch()
|
docs/gradio/images/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
docs/gradio/images/red_fish.png
ADDED
|
Git LFS Details
|
docs/gradio/images/red_fish_2.png
ADDED
|
Git LFS Details
|
docs/gradio/inference.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cv2
|
| 2 |
+
import glob
|
| 3 |
+
import numpy as np
|
| 4 |
+
import torch
|
| 5 |
+
import yolov5
|
| 6 |
+
from typing import Dict, Tuple, Union, List, Optional
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
# -----------------------------------------------------------------------------
|
| 10 |
+
# Configs
|
| 11 |
+
# -----------------------------------------------------------------------------
|
| 12 |
+
|
| 13 |
+
model_path = "models/mbari-mb-benthic-33k.pt"
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
# -----------------------------------------------------------------------------
|
| 17 |
+
# YOLOv5 class
|
| 18 |
+
# -----------------------------------------------------------------------------
|
| 19 |
+
|
| 20 |
+
class YOLO:
|
| 21 |
+
"""Wrapper class for loading and running YOLO model"""
|
| 22 |
+
|
| 23 |
+
def __init__(self, model_path: str, device: Optional[str] = None):
|
| 24 |
+
|
| 25 |
+
# load model
|
| 26 |
+
self.model = yolov5.load(model_path, device=device)
|
| 27 |
+
|
| 28 |
+
def __call__(
|
| 29 |
+
self,
|
| 30 |
+
img: Union[str, np.ndarray],
|
| 31 |
+
conf_threshold: float = 0.25,
|
| 32 |
+
iou_threshold: float = 0.45,
|
| 33 |
+
image_size: int = 720,
|
| 34 |
+
classes: Optional[List[int]] = None) -> torch.Tensor:
|
| 35 |
+
self.model.conf = conf_threshold
|
| 36 |
+
self.model.iou = iou_threshold
|
| 37 |
+
|
| 38 |
+
if classes is not None:
|
| 39 |
+
self.model.classes = classes
|
| 40 |
+
|
| 41 |
+
# pylint: disable=not-callable
|
| 42 |
+
detections = self.model(img, size=image_size)
|
| 43 |
+
|
| 44 |
+
return detections
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def run_inference(image_path):
|
| 48 |
+
"""Helper function to execute the inference."""
|
| 49 |
+
|
| 50 |
+
predictions = model(image_path)
|
| 51 |
+
|
| 52 |
+
return predictions
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
# -----------------------------------------------------------------------------
|
| 56 |
+
# Model Creation
|
| 57 |
+
# -----------------------------------------------------------------------------
|
| 58 |
+
model = YOLO(model_path, device='cpu')
|
| 59 |
+
|
| 60 |
+
if __name__ == "__main__":
|
| 61 |
+
|
| 62 |
+
# For demo purposes: run through a couple of test
|
| 63 |
+
# images and then output the predictions in a folder.
|
| 64 |
+
test_images = glob.glob("images/*.png")
|
| 65 |
+
|
| 66 |
+
for test_image in test_images:
|
| 67 |
+
predictions = run_inference(test_image)
|
| 68 |
+
|
| 69 |
+
print("Done.")
|
docs/gradio/mbari-mb-benthic-33k.names
ADDED
|
@@ -0,0 +1,691 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Anoplopoma fimbria
|
| 2 |
+
Crossaster
|
| 3 |
+
Myxoderma sacculatum
|
| 4 |
+
Sebastolobus
|
| 5 |
+
Neptunea-Buccinum Complex
|
| 6 |
+
Ceriantharia
|
| 7 |
+
Merluccius productus
|
| 8 |
+
Pannychia moseleyi
|
| 9 |
+
Octopus rubescens
|
| 10 |
+
Actiniaria
|
| 11 |
+
Solasteridae
|
| 12 |
+
Antimora microlepis
|
| 13 |
+
Macrouridae
|
| 14 |
+
Heteropolypus ritteri
|
| 15 |
+
Liponema brevicorne
|
| 16 |
+
Ophiuroidea
|
| 17 |
+
Octocorallia
|
| 18 |
+
Porifera
|
| 19 |
+
Brisingida
|
| 20 |
+
Chorilia longipes
|
| 21 |
+
Asteroidea
|
| 22 |
+
equipment
|
| 23 |
+
Metridium farcimen
|
| 24 |
+
Embassichthys bathybius
|
| 25 |
+
Funiculina
|
| 26 |
+
Strongylocentrotus fragilis
|
| 27 |
+
Chionoecetes tanneri
|
| 28 |
+
Actinostoloidea
|
| 29 |
+
Myxoderma platyacanthum
|
| 30 |
+
Gastropoda
|
| 31 |
+
Umbellula
|
| 32 |
+
Psolus squamatus
|
| 33 |
+
Hexactinellida
|
| 34 |
+
Swiftia simplex
|
| 35 |
+
Galatheidae
|
| 36 |
+
Coryphaenoides
|
| 37 |
+
Dosidicus gigas
|
| 38 |
+
Microstomus pacificus
|
| 39 |
+
Sebastolobus alascanus
|
| 40 |
+
Farrea
|
| 41 |
+
Poralia rufescens
|
| 42 |
+
Acanthoptilum
|
| 43 |
+
Isosicyonis
|
| 44 |
+
Paragorgia arborea
|
| 45 |
+
Pannychia sp. 2
|
| 46 |
+
Bothrocara brunneum
|
| 47 |
+
Hormathiidae
|
| 48 |
+
Lycenchelys
|
| 49 |
+
Pteraster
|
| 50 |
+
Paragorgia
|
| 51 |
+
Sebastes
|
| 52 |
+
Bathyraja abyssicola
|
| 53 |
+
Eptatretus
|
| 54 |
+
Lycenchelys crotalinus
|
| 55 |
+
Pennatulacea
|
| 56 |
+
Pandalidae
|
| 57 |
+
Tunicata
|
| 58 |
+
Actinernus
|
| 59 |
+
Asbestopluma rickettsi
|
| 60 |
+
Apostichopus leukothele
|
| 61 |
+
Stylasterias forreri
|
| 62 |
+
Sebastes elongatus
|
| 63 |
+
Sebastomus complex
|
| 64 |
+
Parastenella
|
| 65 |
+
Bathyraja trachura
|
| 66 |
+
Laqueus californicus
|
| 67 |
+
Eutonina indicans
|
| 68 |
+
Keratoisis
|
| 69 |
+
Apristurus
|
| 70 |
+
Mysida
|
| 71 |
+
Tritonia tetraquetra
|
| 72 |
+
Mediaster aequalis
|
| 73 |
+
Anthoptilum grandiflorum
|
| 74 |
+
Virgulariidae
|
| 75 |
+
Vesicomyidae
|
| 76 |
+
Sebastolobus altivelis
|
| 77 |
+
Neptunea
|
| 78 |
+
Rathbunaster californicus
|
| 79 |
+
Bathyraja kincaidii
|
| 80 |
+
Scyliorhinidae
|
| 81 |
+
Lycodapus
|
| 82 |
+
Paralomis
|
| 83 |
+
Isididae
|
| 84 |
+
Crinoidea
|
| 85 |
+
Acanthogorgia
|
| 86 |
+
Swiftia
|
| 87 |
+
Enteroctopus dofleini
|
| 88 |
+
Pagurus tanneri
|
| 89 |
+
Mediaster
|
| 90 |
+
Pyrosoma atlanticum
|
| 91 |
+
Nanomia bijuga
|
| 92 |
+
Lycodes diapterus
|
| 93 |
+
Pectinidae
|
| 94 |
+
Asbestopluma
|
| 95 |
+
Isidella
|
| 96 |
+
Hippasteria
|
| 97 |
+
Osedax
|
| 98 |
+
Corallimorphus
|
| 99 |
+
Florometra serratissima
|
| 100 |
+
Scotoplanes
|
| 101 |
+
Asteronyx
|
| 102 |
+
Swiftia kofoidi
|
| 103 |
+
Pandalus
|
| 104 |
+
Pennatula phosphorea
|
| 105 |
+
Ascidiacea
|
| 106 |
+
Laminariales
|
| 107 |
+
Doryteuthis opalescens
|
| 108 |
+
Sebastidae
|
| 109 |
+
Bathyraja
|
| 110 |
+
Paelopatides confundens
|
| 111 |
+
Suction Sampler
|
| 112 |
+
Lycodes cortezianus
|
| 113 |
+
Pandalus platyceros
|
| 114 |
+
Lumpenus sagitta
|
| 115 |
+
Pandalopsis ampla
|
| 116 |
+
Hydrolagus colliei
|
| 117 |
+
Bathyraja spinosissima
|
| 118 |
+
Solaster hypothrissus
|
| 119 |
+
Hyalonema (Corynonema) populiferum
|
| 120 |
+
Holothuroidea
|
| 121 |
+
Apostichopus
|
| 122 |
+
Synallactidae
|
| 123 |
+
Caridea
|
| 124 |
+
Lithodidae
|
| 125 |
+
Tonrometra
|
| 126 |
+
Stomphia didemon
|
| 127 |
+
Solmissus
|
| 128 |
+
Euphausia
|
| 129 |
+
Lycodapus fierasfer
|
| 130 |
+
Munidopsis depressa
|
| 131 |
+
Cataetyx
|
| 132 |
+
Sebastes diploproa
|
| 133 |
+
Pleurobranchaea californica
|
| 134 |
+
Paguroidea
|
| 135 |
+
Lycodes
|
| 136 |
+
Heterochone calyx
|
| 137 |
+
Isidella tentaculum
|
| 138 |
+
Psathyrometra fragilis
|
| 139 |
+
Sebastes melanostomus
|
| 140 |
+
trash
|
| 141 |
+
Xeneretmus latifrons
|
| 142 |
+
Bathyraja microtrachys
|
| 143 |
+
Bathybembix
|
| 144 |
+
Pyrosoma detritus
|
| 145 |
+
Luidia foliolata
|
| 146 |
+
Lycodes pacificus
|
| 147 |
+
Munida
|
| 148 |
+
Beringraja rhina
|
| 149 |
+
Lophaster
|
| 150 |
+
Gersemia juliepackardae
|
| 151 |
+
Paralomis multispina
|
| 152 |
+
Stomphia
|
| 153 |
+
Primnoidae
|
| 154 |
+
Funiculina-Halipteris complex
|
| 155 |
+
Pleuronectiformes
|
| 156 |
+
Sibogagorgia cauliflora
|
| 157 |
+
Sebastes chlorostictus
|
| 158 |
+
Sebastes zacentrus
|
| 159 |
+
Sebastes babcocki
|
| 160 |
+
Solaster
|
| 161 |
+
Akoya platinum
|
| 162 |
+
Opisthoteuthis sp. A
|
| 163 |
+
Lepidisis
|
| 164 |
+
Branchiocerianthus
|
| 165 |
+
Antedonidae
|
| 166 |
+
Gorgonocephalus eucnemis
|
| 167 |
+
Staurocalyptus
|
| 168 |
+
Glyptocephalus zachirus
|
| 169 |
+
Phyllospadix-Zostera detritus
|
| 170 |
+
Careproctus melanurus
|
| 171 |
+
Amphipoda
|
| 172 |
+
LRJ complex
|
| 173 |
+
Careproctus
|
| 174 |
+
Benthopecten
|
| 175 |
+
Squalus suckleyi
|
| 176 |
+
Eopsetta jordani
|
| 177 |
+
Eusergestes similis
|
| 178 |
+
Sabellida
|
| 179 |
+
Brachyura
|
| 180 |
+
Serpulidae
|
| 181 |
+
Lyopsetta exilis
|
| 182 |
+
Mycale
|
| 183 |
+
Poraniopsis inflata
|
| 184 |
+
Eualus macrophthalmus
|
| 185 |
+
Chonelasma
|
| 186 |
+
Acanthascinae
|
| 187 |
+
Rajiformes
|
| 188 |
+
Corallimorphus pilatus
|
| 189 |
+
Zoarcidae
|
| 190 |
+
Aegina
|
| 191 |
+
medusa carcass
|
| 192 |
+
Neogastropoda
|
| 193 |
+
Pleuronectidae
|
| 194 |
+
Calyptogena
|
| 195 |
+
Pleuronectinae
|
| 196 |
+
Hymenaster
|
| 197 |
+
Munidopsis
|
| 198 |
+
Swiftia sim
|
| 199 |
+
Munnopsidae
|
| 200 |
+
Lobata
|
| 201 |
+
Pannychia
|
| 202 |
+
Lithodes couesi
|
| 203 |
+
Myctophidae
|
| 204 |
+
Thrissacanthias penicillatus
|
| 205 |
+
geology
|
| 206 |
+
Dofleinia
|
| 207 |
+
Asthenactis fisheri
|
| 208 |
+
Cydippida
|
| 209 |
+
Harriotta raleighana
|
| 210 |
+
Metacarcinus magister
|
| 211 |
+
Gobiidae
|
| 212 |
+
Albatrossia pectoralis
|
| 213 |
+
Lampocteis cruentiventer
|
| 214 |
+
Buccinidae
|
| 215 |
+
Alcyonacea
|
| 216 |
+
Ophiacanthidae
|
| 217 |
+
Careproctus kamikawai
|
| 218 |
+
Stylatula
|
| 219 |
+
Paragorgiidae
|
| 220 |
+
Majidae
|
| 221 |
+
Megalodicopia hians
|
| 222 |
+
Moridae
|
| 223 |
+
Ptilosarcus gurneyi
|
| 224 |
+
Isopoda
|
| 225 |
+
Asbestopluma monticola
|
| 226 |
+
Octopoda
|
| 227 |
+
Bivalvia
|
| 228 |
+
Desmophyllum dianthus
|
| 229 |
+
Fungiacyathus (Bathyactis) marenzelleri
|
| 230 |
+
Peniagone
|
| 231 |
+
Elpidia
|
| 232 |
+
Scotoplanes globosa
|
| 233 |
+
Teuthoidea
|
| 234 |
+
Peniagone gracilis
|
| 235 |
+
Oneirophanta mutabilis complex
|
| 236 |
+
Nanomia bijuga nectosome
|
| 237 |
+
fishing-debris
|
| 238 |
+
Peniagone papillata
|
| 239 |
+
Synallactidae gen. et sp. indet.
|
| 240 |
+
Sebastes rufus
|
| 241 |
+
Hydrolagus cf. trolli
|
| 242 |
+
Psychropotes sp. 2
|
| 243 |
+
Tjalfiella
|
| 244 |
+
Poeobius meseres
|
| 245 |
+
Bathochordaeus stygius inner filter
|
| 246 |
+
Bathochordaeus stygius outer filter
|
| 247 |
+
Hydrozoa
|
| 248 |
+
Cnemidocarpa
|
| 249 |
+
Hyalonema
|
| 250 |
+
Malacostraca
|
| 251 |
+
Iosactis vagabunda
|
| 252 |
+
Abyssocucumis abyssorum
|
| 253 |
+
Peniagone vitrea
|
| 254 |
+
Ophiodon elongatus
|
| 255 |
+
Parastichopus leukothele
|
| 256 |
+
Cystechinus loveni
|
| 257 |
+
Ceramaster
|
| 258 |
+
Hexacorallia
|
| 259 |
+
Octopus californicus
|
| 260 |
+
Neolithodes diomedeae
|
| 261 |
+
Benthocodon pedunculata
|
| 262 |
+
Styelidae
|
| 263 |
+
Physiculus rastrelliger
|
| 264 |
+
Laetmogone
|
| 265 |
+
Sebastes saxicola
|
| 266 |
+
Bathochordaeus
|
| 267 |
+
Cladorhizidae
|
| 268 |
+
Peribolaster biserialis
|
| 269 |
+
Muusoctopus robustus
|
| 270 |
+
Hydrolagus melanophasma
|
| 271 |
+
Beroe forskalii
|
| 272 |
+
Sebastes flavidus
|
| 273 |
+
Nemichthyidae
|
| 274 |
+
Poraniopsis
|
| 275 |
+
Sebastes brevispinis
|
| 276 |
+
Sebastes rubrivinctus
|
| 277 |
+
Octopodidae
|
| 278 |
+
Paraliparis sp. 2
|
| 279 |
+
Pythonaster
|
| 280 |
+
Synallactes
|
| 281 |
+
Sebastes ensifer
|
| 282 |
+
Sebastes miniatus
|
| 283 |
+
Hyalonema (Oonema) bianchoratum
|
| 284 |
+
Anomura
|
| 285 |
+
Echinocrepis rostrata
|
| 286 |
+
Prayidae
|
| 287 |
+
Physonectae nectosome
|
| 288 |
+
Physonectae
|
| 289 |
+
Sebastes paucispinis
|
| 290 |
+
Sebastes head
|
| 291 |
+
Hirudinea
|
| 292 |
+
Urticina
|
| 293 |
+
Astropecten
|
| 294 |
+
Leptogorgia
|
| 295 |
+
Galatheoidea
|
| 296 |
+
Beroe cucumis
|
| 297 |
+
Bolocera
|
| 298 |
+
Fariometra parvula
|
| 299 |
+
Neptunea-Buccinum Complex eggcase
|
| 300 |
+
Graneledone boreopacifica
|
| 301 |
+
Polynoidae
|
| 302 |
+
Psamminidae
|
| 303 |
+
Psychrolutes phrictus
|
| 304 |
+
Sergestes similis
|
| 305 |
+
Calycophorae nectosome
|
| 306 |
+
Beroe
|
| 307 |
+
Thenea muricata
|
| 308 |
+
Gonatus
|
| 309 |
+
Henricia
|
| 310 |
+
Nudibranchia
|
| 311 |
+
Sebastes aurora
|
| 312 |
+
Zoantharia
|
| 313 |
+
Clavularia
|
| 314 |
+
Terebratulina complex
|
| 315 |
+
Macrourinae
|
| 316 |
+
Ptychogastria
|
| 317 |
+
Delectopecten
|
| 318 |
+
Phacellophora camtschatica
|
| 319 |
+
Siboglinidae
|
| 320 |
+
Gorgoniidae
|
| 321 |
+
eggcase
|
| 322 |
+
Sibogagorgia
|
| 323 |
+
Comatulida
|
| 324 |
+
Diogenidae
|
| 325 |
+
eggs
|
| 326 |
+
Apolemia
|
| 327 |
+
Midwater Respirometry System
|
| 328 |
+
Pycnogonida
|
| 329 |
+
Calliostoma
|
| 330 |
+
Sebastes aleutianus-melanostictus complex
|
| 331 |
+
Brachiopoda
|
| 332 |
+
Medusae
|
| 333 |
+
Lamellibrachia
|
| 334 |
+
Bathyphellia australis
|
| 335 |
+
Ophiuridae
|
| 336 |
+
Lycodes brevipes
|
| 337 |
+
Atolla
|
| 338 |
+
Plectobranchus evides
|
| 339 |
+
Asteriidae
|
| 340 |
+
Farrea occa
|
| 341 |
+
Agonidae
|
| 342 |
+
Bathymetrinae
|
| 343 |
+
Decapoda
|
| 344 |
+
Corallium
|
| 345 |
+
Halipteris californica
|
| 346 |
+
Dipsacaster
|
| 347 |
+
Chonelasmatinae sp. 2
|
| 348 |
+
shell
|
| 349 |
+
Phyllospadix detritus
|
| 350 |
+
Spectrunculus grandis
|
| 351 |
+
shell fragment
|
| 352 |
+
Paralomis verrilli
|
| 353 |
+
Hydrolagus
|
| 354 |
+
Actinopterygii
|
| 355 |
+
Parmaturus xaniurus
|
| 356 |
+
whale carcass
|
| 357 |
+
Pterasteridae arm
|
| 358 |
+
Annelida
|
| 359 |
+
Lyrocteis
|
| 360 |
+
Echiura
|
| 361 |
+
Vanhoeffenura pulchra
|
| 362 |
+
Bolinopsis infundibulum
|
| 363 |
+
Colossendeidae
|
| 364 |
+
Bathochordaeus stygius
|
| 365 |
+
Sebastes jordani
|
| 366 |
+
Platyctenida
|
| 367 |
+
Saxipendium implicatum
|
| 368 |
+
TorquaratoridaeB sp. 2
|
| 369 |
+
Pachycara bulbiceps
|
| 370 |
+
Hydractiniidae
|
| 371 |
+
Psamminidae sp. 2
|
| 372 |
+
Tjalfiellidae
|
| 373 |
+
Myxoderma
|
| 374 |
+
Hyocrinidae
|
| 375 |
+
Chondrocladia
|
| 376 |
+
Cystocrepis setigera
|
| 377 |
+
Munidopsis kensmithi
|
| 378 |
+
Radiozoa
|
| 379 |
+
Chaetognatha
|
| 380 |
+
Siphonophorae
|
| 381 |
+
Chrysogorgia
|
| 382 |
+
Pseudostichopus mollis
|
| 383 |
+
Benthothuria
|
| 384 |
+
Bolocera kensmithi
|
| 385 |
+
Sebastes semicinctus
|
| 386 |
+
Galiteuthis phyllura
|
| 387 |
+
Octopodinae
|
| 388 |
+
Serrivomer
|
| 389 |
+
Demospongiae
|
| 390 |
+
Latrunculia (Latrunculia) austini
|
| 391 |
+
Dromalia alexandri
|
| 392 |
+
Scleractinia
|
| 393 |
+
Plesionika
|
| 394 |
+
bacterial mat
|
| 395 |
+
Chondrocladia (Symmetrocladia) lyra
|
| 396 |
+
Neoloricata
|
| 397 |
+
asteroid feeding depression
|
| 398 |
+
Bathyalcyon robustum
|
| 399 |
+
Bathypterois
|
| 400 |
+
Distichoptilum
|
| 401 |
+
Paraliparis cephalus
|
| 402 |
+
Sebastes serranoides
|
| 403 |
+
Goniasteridae
|
| 404 |
+
ledge
|
| 405 |
+
Tromikosoma panamense
|
| 406 |
+
Ctenophora
|
| 407 |
+
Docosaccus maculatus
|
| 408 |
+
sinker
|
| 409 |
+
Lophaster furcilliger
|
| 410 |
+
Sebastes cortezi
|
| 411 |
+
Culeolus
|
| 412 |
+
Mysidacea
|
| 413 |
+
Bathydorus laevis pseudospinosus
|
| 414 |
+
Alepocephalus tenebrosus
|
| 415 |
+
Echinoidea
|
| 416 |
+
Heterozonias alternatus
|
| 417 |
+
Smithsonius dorothea
|
| 418 |
+
Heterocarpus sp. 2
|
| 419 |
+
Eucryphycus californicus
|
| 420 |
+
Polychaeta tube
|
| 421 |
+
Cirroteuthis
|
| 422 |
+
Tergivelum baldwinae
|
| 423 |
+
Tiburonia granrojo
|
| 424 |
+
Liparidae
|
| 425 |
+
Riftia pachyptila
|
| 426 |
+
Hydroidolina
|
| 427 |
+
Plexauridae
|
| 428 |
+
Bathylagidae
|
| 429 |
+
Lepidion
|
| 430 |
+
Sclerothamnopsis
|
| 431 |
+
Careproctus ovigerus
|
| 432 |
+
Psychropotes depressa
|
| 433 |
+
Icelinus filamentosus
|
| 434 |
+
Chrysogorgia monticola
|
| 435 |
+
wood
|
| 436 |
+
Bathochordaeus inner filter
|
| 437 |
+
Sebastes entomelas
|
| 438 |
+
Anthozoa
|
| 439 |
+
Bathypterois pectinatus
|
| 440 |
+
Cladorhiza kensmithi
|
| 441 |
+
Aporocidaris milleri
|
| 442 |
+
Ischnomesidae
|
| 443 |
+
Staurocalyptus solidus
|
| 444 |
+
Anthoptilum lithophilum
|
| 445 |
+
Atolla wyvillei
|
| 446 |
+
Erenna richardi
|
| 447 |
+
Hyalonematidae
|
| 448 |
+
Pleurobranchaea
|
| 449 |
+
Sergestidae
|
| 450 |
+
Thermarces cerberus
|
| 451 |
+
Pennatula
|
| 452 |
+
Moloha faxoni
|
| 453 |
+
Munida quadrispina
|
| 454 |
+
Lophiiformes
|
| 455 |
+
Benthoctopus
|
| 456 |
+
Strongylocentrotus
|
| 457 |
+
kelp
|
| 458 |
+
Nanomia nectosome
|
| 459 |
+
Sicyonis
|
| 460 |
+
Chrysogorgia pinnata
|
| 461 |
+
Forskalia formosa
|
| 462 |
+
Sebastes ruberrimus
|
| 463 |
+
Sebastes levis
|
| 464 |
+
Praya dubia nectosome
|
| 465 |
+
Praya dubia
|
| 466 |
+
Pleuronectiformes 3
|
| 467 |
+
Chuniphyes multidentata
|
| 468 |
+
Dictyocalyx
|
| 469 |
+
Zaniolepis frenata
|
| 470 |
+
Octopus
|
| 471 |
+
Forcipulatacea
|
| 472 |
+
Eretmichthys pinnatus
|
| 473 |
+
Dibranchus hystrix
|
| 474 |
+
Coelorinchus spilonotus
|
| 475 |
+
Pseudobathylagus
|
| 476 |
+
Benthodytes
|
| 477 |
+
Alternatipathes
|
| 478 |
+
Lillipathes
|
| 479 |
+
Protoptilum sp. 2
|
| 480 |
+
Hastigerinella digitata
|
| 481 |
+
Bargmannia elongata
|
| 482 |
+
Bargmannia elongata nectosome
|
| 483 |
+
Psychronaetes
|
| 484 |
+
Bathysaurus mollis
|
| 485 |
+
Lycodinae
|
| 486 |
+
Euplectellidae
|
| 487 |
+
Pasiphaea
|
| 488 |
+
Bathysiphon
|
| 489 |
+
Beroe abyssicola
|
| 490 |
+
Tomopteris
|
| 491 |
+
Polychaeta
|
| 492 |
+
Articulata
|
| 493 |
+
Apostichopus californicus
|
| 494 |
+
Kophobelemnon
|
| 495 |
+
Bolinopsis
|
| 496 |
+
Euryalida
|
| 497 |
+
Pennatulidae
|
| 498 |
+
Gastroptychus
|
| 499 |
+
molt
|
| 500 |
+
Corallimorphus denhartogi
|
| 501 |
+
Neptunea eggcase
|
| 502 |
+
Octacnemidae sp. 2
|
| 503 |
+
Xeneretmus
|
| 504 |
+
Dibranchus spinosus
|
| 505 |
+
Epizoanthus stellaris
|
| 506 |
+
Pennatulacea sp. 2
|
| 507 |
+
Sebastes borealis
|
| 508 |
+
Aeolidiidae
|
| 509 |
+
Mitrocoma cellularia
|
| 510 |
+
Tromikosoma
|
| 511 |
+
Icichthys lockingtoni
|
| 512 |
+
Solmissus incisa
|
| 513 |
+
Sebastes pinniger
|
| 514 |
+
Enteropneusta
|
| 515 |
+
Sebastes auriculatus
|
| 516 |
+
Megalodicopia
|
| 517 |
+
Asthenactis papyraceus
|
| 518 |
+
Sebastes miniatus-pinniger complex
|
| 519 |
+
Asthenactis
|
| 520 |
+
test
|
| 521 |
+
Icelinus
|
| 522 |
+
Parantipathes
|
| 523 |
+
Sebastes macdonaldi
|
| 524 |
+
Sebastes mystinus
|
| 525 |
+
Physiculus nematopus-rastrelliger complex
|
| 526 |
+
Sebastes rosenblatti
|
| 527 |
+
Bathochordaeus sinker
|
| 528 |
+
Distichoptilum gracile
|
| 529 |
+
kelp holdfast
|
| 530 |
+
Rhinochimaeridae
|
| 531 |
+
Echinocrepis setigera
|
| 532 |
+
Sebastes caurinus
|
| 533 |
+
Egregia menziesii
|
| 534 |
+
Myriothelidae
|
| 535 |
+
coiled fecal cast
|
| 536 |
+
Cystechinus giganteus
|
| 537 |
+
Bathochordaeus mcnutti inner filter
|
| 538 |
+
Bathochordaeus mcnutti
|
| 539 |
+
Cladorhiza
|
| 540 |
+
Cirripedia
|
| 541 |
+
Swiftia kol
|
| 542 |
+
Phyllochaetopterus gigas
|
| 543 |
+
Hymenaster koehleri
|
| 544 |
+
sinker outer filter
|
| 545 |
+
Allocentrotus fragilis
|
| 546 |
+
Luciobrotula sp. A
|
| 547 |
+
Opisthoteuthis
|
| 548 |
+
Haliscera bigelowi
|
| 549 |
+
Scotoplanes clarki
|
| 550 |
+
Lyssacinosida sp. 2
|
| 551 |
+
larvacean outer filter
|
| 552 |
+
Ophichthus frontalis
|
| 553 |
+
Calyptrophora
|
| 554 |
+
Provannidae
|
| 555 |
+
Marine organism
|
| 556 |
+
Farrea truncata complex
|
| 557 |
+
Actinoscyphia
|
| 558 |
+
Exocoelactis
|
| 559 |
+
Kophobelemnidae
|
| 560 |
+
Lychnagalma nectosome
|
| 561 |
+
Lychnagalma
|
| 562 |
+
Caenogastropoda
|
| 563 |
+
Zoroasteridae
|
| 564 |
+
Bathochordaeus outer filter
|
| 565 |
+
Vanhoeffenura
|
| 566 |
+
Stylasterias
|
| 567 |
+
Calycophorae
|
| 568 |
+
Vitreosalpa gemini
|
| 569 |
+
Anguilliformes
|
| 570 |
+
Calocarides quinqueseriatus
|
| 571 |
+
Fungiacyathus
|
| 572 |
+
Candelabridae sp. 2
|
| 573 |
+
Tergivelum sp. A
|
| 574 |
+
Mesochordaeus erythrocephalus
|
| 575 |
+
Monothalamea
|
| 576 |
+
Paradiopatra
|
| 577 |
+
Munida bapensis
|
| 578 |
+
Sebastes crameri-melanostomus complex
|
| 579 |
+
Asterozoa
|
| 580 |
+
Patiria miniata
|
| 581 |
+
Ophidiiformes
|
| 582 |
+
Salpida
|
| 583 |
+
Coelorinchus scaphopsis
|
| 584 |
+
Tomopteris nisseni
|
| 585 |
+
Camptoplites sp. A
|
| 586 |
+
Psychropotidae
|
| 587 |
+
Paxillosida
|
| 588 |
+
Dendronotus patricki
|
| 589 |
+
Oneirophanta
|
| 590 |
+
Lensia conoidea nectosome
|
| 591 |
+
Lensia conoidea
|
| 592 |
+
Glyphocrangon vicaria
|
| 593 |
+
Dipsacaster eximius
|
| 594 |
+
Bathydorus
|
| 595 |
+
Bathycrinidae
|
| 596 |
+
Sebastolobus head
|
| 597 |
+
Doryteuthis (Amerigo) opalescens eggs
|
| 598 |
+
Sebastes crameri
|
| 599 |
+
Thetys vagina
|
| 600 |
+
Sebastes ovalis
|
| 601 |
+
Lycodapus mandibularis
|
| 602 |
+
Sebastolobus tail
|
| 603 |
+
Sebastes goodei
|
| 604 |
+
Pseudobathylagus milleri
|
| 605 |
+
Narcomedusa
|
| 606 |
+
Chiroteuthis calyx
|
| 607 |
+
Heterobranchia
|
| 608 |
+
Octacnemidae
|
| 609 |
+
inner filter
|
| 610 |
+
Pentametrocrinus paucispinulus
|
| 611 |
+
Beroe gracilis
|
| 612 |
+
Schizopathidae
|
| 613 |
+
Dytaster gilberti
|
| 614 |
+
Physiculus sp. 2
|
| 615 |
+
Octopodidae tentacle
|
| 616 |
+
Mysidae
|
| 617 |
+
Antipatharia
|
| 618 |
+
Lychnagalma utricularia nectosome
|
| 619 |
+
Lychnagalma utricularia
|
| 620 |
+
Ridgeia
|
| 621 |
+
Actinauge verrillii
|
| 622 |
+
Oikopleuridae outer filter
|
| 623 |
+
Fecampiid eggcase
|
| 624 |
+
Chilara taylori
|
| 625 |
+
Acesta
|
| 626 |
+
Caulophacus
|
| 627 |
+
Parophrys vetulus
|
| 628 |
+
Dibranchus sp. A
|
| 629 |
+
Holothuria (Vaneyothuria) zacae
|
| 630 |
+
Prayidae nectosome
|
| 631 |
+
Acanthephyra
|
| 632 |
+
Bathycrinus complanatus
|
| 633 |
+
Munnopsis
|
| 634 |
+
Alcyoniidae
|
| 635 |
+
Microstomus bathybius
|
| 636 |
+
Theudoidea
|
| 637 |
+
Hydromedusae
|
| 638 |
+
Protoptilum
|
| 639 |
+
Bathyphellia
|
| 640 |
+
Euplokamidae
|
| 641 |
+
Microstomus pacificus sole
|
| 642 |
+
Hormiphora californensis
|
| 643 |
+
Leptocephalus-3
|
| 644 |
+
Verum proximum
|
| 645 |
+
Lepidopsetta bilineata
|
| 646 |
+
Corolla spectabilis
|
| 647 |
+
Haliscera conica
|
| 648 |
+
Brisaster
|
| 649 |
+
Oikopleura outer filter
|
| 650 |
+
Paulasterias mcclaini
|
| 651 |
+
Sicyonis careyi
|
| 652 |
+
Iosactis
|
| 653 |
+
Oikopleuridae inner filter
|
| 654 |
+
Chromista
|
| 655 |
+
Mola mola
|
| 656 |
+
Melanostigma pammelas
|
| 657 |
+
Scrippsia pacifica
|
| 658 |
+
larvacean house
|
| 659 |
+
Sebastes phillipsi
|
| 660 |
+
Peinaleopolynoe orphanae
|
| 661 |
+
Cnidaria
|
| 662 |
+
salp detritus
|
| 663 |
+
Atolla vanhoeffeni
|
| 664 |
+
Appendicularia outer filter
|
| 665 |
+
Appendicularia inner filter
|
| 666 |
+
Sebastes simulator
|
| 667 |
+
Acharax
|
| 668 |
+
Plesionika sp. A
|
| 669 |
+
Mediaster tenellus
|
| 670 |
+
Eutonina
|
| 671 |
+
Octopoteuthis deletron
|
| 672 |
+
Crustacea
|
| 673 |
+
Psathyrometra
|
| 674 |
+
Patellogastropoda
|
| 675 |
+
Sebastes cortezi tail
|
| 676 |
+
Yoda sp. A
|
| 677 |
+
Lophiodes caulinaris
|
| 678 |
+
Ptilosarcus
|
| 679 |
+
Gnathophis cinctus
|
| 680 |
+
Munidopsis sp. 2
|
| 681 |
+
salp chain
|
| 682 |
+
Oikopleuridae
|
| 683 |
+
Vogtia
|
| 684 |
+
Rossellidae
|
| 685 |
+
detrital aggregate
|
| 686 |
+
Sebastes maliger
|
| 687 |
+
Tuscaretta
|
| 688 |
+
Chaunacops coloratus
|
| 689 |
+
Pleurobrachiidae
|
| 690 |
+
Tenebrincola cukri
|
| 691 |
+
Amblyraja hyperborea
|
docs/gradio/mbari-mb-benthic-33k_stats.txt
ADDED
|
@@ -0,0 +1,691 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
339 Anoplopoma fimbria
|
| 2 |
+
320 Crossaster
|
| 3 |
+
27 Myxoderma sacculatum
|
| 4 |
+
5114 Sebastolobus
|
| 5 |
+
252 Neptunea-Buccinum Complex
|
| 6 |
+
264 Ceriantharia
|
| 7 |
+
6291 Merluccius productus
|
| 8 |
+
2554 Pannychia moseleyi
|
| 9 |
+
1751 Octopus rubescens
|
| 10 |
+
3316 Actiniaria
|
| 11 |
+
186 Solasteridae
|
| 12 |
+
479 Antimora microlepis
|
| 13 |
+
131 Macrouridae
|
| 14 |
+
1408 Heteropolypus ritteri
|
| 15 |
+
621 Liponema brevicorne
|
| 16 |
+
3706 Ophiuroidea
|
| 17 |
+
289 Octocorallia
|
| 18 |
+
2575 Porifera
|
| 19 |
+
413 Brisingida
|
| 20 |
+
209 Chorilia longipes
|
| 21 |
+
2803 Asteroidea
|
| 22 |
+
235 equipment
|
| 23 |
+
594 Metridium farcimen
|
| 24 |
+
744 Embassichthys bathybius
|
| 25 |
+
3848 Funiculina
|
| 26 |
+
8631 Strongylocentrotus fragilis
|
| 27 |
+
2790 Chionoecetes tanneri
|
| 28 |
+
151 Actinostoloidea
|
| 29 |
+
120 Myxoderma platyacanthum
|
| 30 |
+
811 Gastropoda
|
| 31 |
+
1723 Umbellula
|
| 32 |
+
3965 Psolus squamatus
|
| 33 |
+
786 Hexactinellida
|
| 34 |
+
743 Swiftia simplex
|
| 35 |
+
287 Galatheidae
|
| 36 |
+
411 Coryphaenoides
|
| 37 |
+
50 Dosidicus gigas
|
| 38 |
+
1214 Microstomus pacificus
|
| 39 |
+
65 Sebastolobus alascanus
|
| 40 |
+
907 Farrea
|
| 41 |
+
54 Poralia rufescens
|
| 42 |
+
757 Acanthoptilum
|
| 43 |
+
812 Isosicyonis
|
| 44 |
+
3546 Paragorgia arborea
|
| 45 |
+
25 Pannychia sp. 2
|
| 46 |
+
14 Bothrocara brunneum
|
| 47 |
+
409 Hormathiidae
|
| 48 |
+
621 Lycenchelys
|
| 49 |
+
488 Pteraster
|
| 50 |
+
484 Paragorgia
|
| 51 |
+
1368 Sebastes
|
| 52 |
+
199 Bathyraja abyssicola
|
| 53 |
+
403 Eptatretus
|
| 54 |
+
86 Lycenchelys crotalinus
|
| 55 |
+
788 Pennatulacea
|
| 56 |
+
92 Pandalidae
|
| 57 |
+
584 Tunicata
|
| 58 |
+
803 Actinernus
|
| 59 |
+
293 Asbestopluma rickettsi
|
| 60 |
+
525 Apostichopus leukothele
|
| 61 |
+
214 Stylasterias forreri
|
| 62 |
+
44 Sebastes elongatus
|
| 63 |
+
74 Sebastomus complex
|
| 64 |
+
215 Parastenella
|
| 65 |
+
504 Bathyraja trachura
|
| 66 |
+
300 Laqueus californicus
|
| 67 |
+
2 Eutonina indicans
|
| 68 |
+
3829 Keratoisis
|
| 69 |
+
8 Apristurus
|
| 70 |
+
66 Mysida
|
| 71 |
+
68 Tritonia tetraquetra
|
| 72 |
+
284 Mediaster aequalis
|
| 73 |
+
41 Anthoptilum grandiflorum
|
| 74 |
+
22 Virgulariidae
|
| 75 |
+
766 Vesicomyidae
|
| 76 |
+
136 Sebastolobus altivelis
|
| 77 |
+
246 Neptunea
|
| 78 |
+
3181 Rathbunaster californicus
|
| 79 |
+
424 Bathyraja kincaidii
|
| 80 |
+
6 Scyliorhinidae
|
| 81 |
+
15 Lycodapus
|
| 82 |
+
160 Paralomis
|
| 83 |
+
1426 Isididae
|
| 84 |
+
160 Crinoidea
|
| 85 |
+
31 Acanthogorgia
|
| 86 |
+
301 Swiftia
|
| 87 |
+
57 Enteroctopus dofleini
|
| 88 |
+
39 Pagurus tanneri
|
| 89 |
+
119 Mediaster
|
| 90 |
+
28 Pyrosoma atlanticum
|
| 91 |
+
1098 Nanomia bijuga
|
| 92 |
+
359 Lycodes diapterus
|
| 93 |
+
31 Pectinidae
|
| 94 |
+
340 Asbestopluma
|
| 95 |
+
263 Isidella
|
| 96 |
+
301 Hippasteria
|
| 97 |
+
34 Osedax
|
| 98 |
+
152 Corallimorphus
|
| 99 |
+
373 Florometra serratissima
|
| 100 |
+
602 Scotoplanes
|
| 101 |
+
415 Asteronyx
|
| 102 |
+
418 Swiftia kofoidi
|
| 103 |
+
29 Pandalus
|
| 104 |
+
46 Pennatula phosphorea
|
| 105 |
+
24 Ascidiacea
|
| 106 |
+
12 Laminariales
|
| 107 |
+
117 Doryteuthis opalescens
|
| 108 |
+
5 Sebastidae
|
| 109 |
+
43 Bathyraja
|
| 110 |
+
590 Paelopatides confundens
|
| 111 |
+
329 Suction Sampler
|
| 112 |
+
270 Lycodes cortezianus
|
| 113 |
+
337 Pandalus platyceros
|
| 114 |
+
6 Lumpenus sagitta
|
| 115 |
+
570 Pandalopsis ampla
|
| 116 |
+
167 Hydrolagus colliei
|
| 117 |
+
207 Bathyraja spinosissima
|
| 118 |
+
62 Solaster hypothrissus
|
| 119 |
+
36 Hyalonema (Corynonema) populiferum
|
| 120 |
+
465 Holothuroidea
|
| 121 |
+
56 Apostichopus
|
| 122 |
+
167 Synallactidae
|
| 123 |
+
209 Caridea
|
| 124 |
+
72 Lithodidae
|
| 125 |
+
1 Tonrometra
|
| 126 |
+
26 Stomphia didemon
|
| 127 |
+
50 Solmissus
|
| 128 |
+
54 Euphausia
|
| 129 |
+
59 Lycodapus fierasfer
|
| 130 |
+
8 Munidopsis depressa
|
| 131 |
+
3 Cataetyx
|
| 132 |
+
520 Sebastes diploproa
|
| 133 |
+
37 Pleurobranchaea californica
|
| 134 |
+
80 Paguroidea
|
| 135 |
+
49 Lycodes
|
| 136 |
+
418 Heterochone calyx
|
| 137 |
+
135 Isidella tentaculum
|
| 138 |
+
500 Psathyrometra fragilis
|
| 139 |
+
162 Sebastes melanostomus
|
| 140 |
+
118 trash
|
| 141 |
+
33 Xeneretmus latifrons
|
| 142 |
+
157 Bathyraja microtrachys
|
| 143 |
+
31 Bathybembix
|
| 144 |
+
253 Pyrosoma detritus
|
| 145 |
+
107 Luidia foliolata
|
| 146 |
+
34 Lycodes pacificus
|
| 147 |
+
55 Munida
|
| 148 |
+
86 Beringraja rhina
|
| 149 |
+
153 Lophaster
|
| 150 |
+
2373 Gersemia juliepackardae
|
| 151 |
+
128 Paralomis multispina
|
| 152 |
+
21 Stomphia
|
| 153 |
+
14 Primnoidae
|
| 154 |
+
267 Funiculina-Halipteris complex
|
| 155 |
+
684 Pleuronectiformes
|
| 156 |
+
63 Sibogagorgia cauliflora
|
| 157 |
+
17 Sebastes chlorostictus
|
| 158 |
+
18 Sebastes zacentrus
|
| 159 |
+
43 Sebastes babcocki
|
| 160 |
+
67 Solaster
|
| 161 |
+
50 Akoya platinum
|
| 162 |
+
11 Opisthoteuthis sp. A
|
| 163 |
+
50 Lepidisis
|
| 164 |
+
2 Branchiocerianthus
|
| 165 |
+
81 Antedonidae
|
| 166 |
+
31 Gorgonocephalus eucnemis
|
| 167 |
+
492 Staurocalyptus
|
| 168 |
+
56 Glyptocephalus zachirus
|
| 169 |
+
21 Phyllospadix-Zostera detritus
|
| 170 |
+
53 Careproctus melanurus
|
| 171 |
+
12 Amphipoda
|
| 172 |
+
625 LRJ complex
|
| 173 |
+
26 Careproctus
|
| 174 |
+
24 Benthopecten
|
| 175 |
+
7 Squalus suckleyi
|
| 176 |
+
31 Eopsetta jordani
|
| 177 |
+
81 Eusergestes similis
|
| 178 |
+
32 Sabellida
|
| 179 |
+
6 Brachyura
|
| 180 |
+
275 Serpulidae
|
| 181 |
+
22 Lyopsetta exilis
|
| 182 |
+
107 Mycale
|
| 183 |
+
33 Poraniopsis inflata
|
| 184 |
+
23 Eualus macrophthalmus
|
| 185 |
+
12 Chonelasma
|
| 186 |
+
163 Acanthascinae
|
| 187 |
+
21 Rajiformes
|
| 188 |
+
115 Corallimorphus pilatus
|
| 189 |
+
19 Zoarcidae
|
| 190 |
+
41 Aegina
|
| 191 |
+
1 medusa carcass
|
| 192 |
+
3 Neogastropoda
|
| 193 |
+
10 Pleuronectidae
|
| 194 |
+
7 Calyptogena
|
| 195 |
+
10 Pleuronectinae
|
| 196 |
+
296 Hymenaster
|
| 197 |
+
202 Munidopsis
|
| 198 |
+
14 Swiftia sim
|
| 199 |
+
54 Munnopsidae
|
| 200 |
+
7 Lobata
|
| 201 |
+
138 Pannychia
|
| 202 |
+
8 Lithodes couesi
|
| 203 |
+
4 Myctophidae
|
| 204 |
+
7 Thrissacanthias penicillatus
|
| 205 |
+
34 geology
|
| 206 |
+
8 Dofleinia
|
| 207 |
+
141 Asthenactis fisheri
|
| 208 |
+
15 Cydippida
|
| 209 |
+
4 Harriotta raleighana
|
| 210 |
+
11 Metacarcinus magister
|
| 211 |
+
2 Gobiidae
|
| 212 |
+
5 Albatrossia pectoralis
|
| 213 |
+
6 Lampocteis cruentiventer
|
| 214 |
+
21 Buccinidae
|
| 215 |
+
53 Alcyonacea
|
| 216 |
+
58 Ophiacanthidae
|
| 217 |
+
5 Careproctus kamikawai
|
| 218 |
+
4 Stylatula
|
| 219 |
+
72 Paragorgiidae
|
| 220 |
+
12 Majidae
|
| 221 |
+
21 Megalodicopia hians
|
| 222 |
+
2 Moridae
|
| 223 |
+
13 Ptilosarcus gurneyi
|
| 224 |
+
23 Isopoda
|
| 225 |
+
214 Asbestopluma monticola
|
| 226 |
+
9 Octopoda
|
| 227 |
+
54 Bivalvia
|
| 228 |
+
17 Desmophyllum dianthus
|
| 229 |
+
41 Fungiacyathus (Bathyactis) marenzelleri
|
| 230 |
+
3760 Peniagone
|
| 231 |
+
822 Elpidia
|
| 232 |
+
1706 Scotoplanes globosa
|
| 233 |
+
32 Teuthoidea
|
| 234 |
+
551 Peniagone gracilis
|
| 235 |
+
158 Oneirophanta mutabilis complex
|
| 236 |
+
337 Nanomia bijuga nectosome
|
| 237 |
+
6 fishing-debris
|
| 238 |
+
231 Peniagone papillata
|
| 239 |
+
184 Synallactidae gen. et sp. indet.
|
| 240 |
+
18 Sebastes rufus
|
| 241 |
+
109 Hydrolagus cf. trolli
|
| 242 |
+
96 Psychropotes sp. 2
|
| 243 |
+
255 Tjalfiella
|
| 244 |
+
24 Poeobius meseres
|
| 245 |
+
34 Bathochordaeus stygius inner filter
|
| 246 |
+
31 Bathochordaeus stygius outer filter
|
| 247 |
+
17 Hydrozoa
|
| 248 |
+
57 Cnemidocarpa
|
| 249 |
+
29 Hyalonema
|
| 250 |
+
21 Malacostraca
|
| 251 |
+
17 Iosactis vagabunda
|
| 252 |
+
499 Abyssocucumis abyssorum
|
| 253 |
+
811 Peniagone vitrea
|
| 254 |
+
18 Ophiodon elongatus
|
| 255 |
+
10 Parastichopus leukothele
|
| 256 |
+
124 Cystechinus loveni
|
| 257 |
+
13 Ceramaster
|
| 258 |
+
51 Hexacorallia
|
| 259 |
+
163 Octopus californicus
|
| 260 |
+
17 Neolithodes diomedeae
|
| 261 |
+
381 Benthocodon pedunculata
|
| 262 |
+
4 Styelidae
|
| 263 |
+
9 Physiculus rastrelliger
|
| 264 |
+
25 Laetmogone
|
| 265 |
+
40 Sebastes saxicola
|
| 266 |
+
11 Bathochordaeus
|
| 267 |
+
62 Cladorhizidae
|
| 268 |
+
8 Peribolaster biserialis
|
| 269 |
+
144 Muusoctopus robustus
|
| 270 |
+
43 Hydrolagus melanophasma
|
| 271 |
+
8 Beroe forskalii
|
| 272 |
+
15 Sebastes flavidus
|
| 273 |
+
3 Nemichthyidae
|
| 274 |
+
22 Poraniopsis
|
| 275 |
+
12 Sebastes brevispinis
|
| 276 |
+
16 Sebastes rubrivinctus
|
| 277 |
+
32 Octopodidae
|
| 278 |
+
1 Paraliparis sp. 2
|
| 279 |
+
33 Pythonaster
|
| 280 |
+
74 Synallactes
|
| 281 |
+
6 Sebastes ensifer
|
| 282 |
+
19 Sebastes miniatus
|
| 283 |
+
40 Hyalonema (Oonema) bianchoratum
|
| 284 |
+
2 Anomura
|
| 285 |
+
92 Echinocrepis rostrata
|
| 286 |
+
8 Prayidae
|
| 287 |
+
2 Physonectae nectosome
|
| 288 |
+
2 Physonectae
|
| 289 |
+
9 Sebastes paucispinis
|
| 290 |
+
1 Sebastes head
|
| 291 |
+
45 Hirudinea
|
| 292 |
+
2 Urticina
|
| 293 |
+
2 Astropecten
|
| 294 |
+
30 Leptogorgia
|
| 295 |
+
51 Galatheoidea
|
| 296 |
+
5 Beroe cucumis
|
| 297 |
+
28 Bolocera
|
| 298 |
+
14 Fariometra parvula
|
| 299 |
+
5 Neptunea-Buccinum Complex eggcase
|
| 300 |
+
51 Graneledone boreopacifica
|
| 301 |
+
7 Polynoidae
|
| 302 |
+
55 Psamminidae
|
| 303 |
+
29 Psychrolutes phrictus
|
| 304 |
+
2 Sergestes similis
|
| 305 |
+
2 Calycophorae nectosome
|
| 306 |
+
40 Beroe
|
| 307 |
+
37 Thenea muricata
|
| 308 |
+
17 Gonatus
|
| 309 |
+
18 Henricia
|
| 310 |
+
1 Nudibranchia
|
| 311 |
+
66 Sebastes aurora
|
| 312 |
+
681 Zoantharia
|
| 313 |
+
112 Clavularia
|
| 314 |
+
33 Terebratulina complex
|
| 315 |
+
4 Macrourinae
|
| 316 |
+
34 Ptychogastria
|
| 317 |
+
21 Delectopecten
|
| 318 |
+
20 Phacellophora camtschatica
|
| 319 |
+
10 Siboglinidae
|
| 320 |
+
6 Gorgoniidae
|
| 321 |
+
132 eggcase
|
| 322 |
+
60 Sibogagorgia
|
| 323 |
+
106 Comatulida
|
| 324 |
+
3 Diogenidae
|
| 325 |
+
2 eggs
|
| 326 |
+
12 Apolemia
|
| 327 |
+
7 Midwater Respirometry System
|
| 328 |
+
15 Pycnogonida
|
| 329 |
+
25 Calliostoma
|
| 330 |
+
14 Sebastes aleutianus-melanostictus complex
|
| 331 |
+
57 Brachiopoda
|
| 332 |
+
8 Medusae
|
| 333 |
+
31 Lamellibrachia
|
| 334 |
+
28 Bathyphellia australis
|
| 335 |
+
6 Ophiuridae
|
| 336 |
+
8 Lycodes brevipes
|
| 337 |
+
13 Atolla
|
| 338 |
+
4 Plectobranchus evides
|
| 339 |
+
3 Asteriidae
|
| 340 |
+
84 Farrea occa
|
| 341 |
+
7 Agonidae
|
| 342 |
+
9 Bathymetrinae
|
| 343 |
+
7 Decapoda
|
| 344 |
+
17 Corallium
|
| 345 |
+
87 Halipteris californica
|
| 346 |
+
8 Dipsacaster
|
| 347 |
+
2 Chonelasmatinae sp. 2
|
| 348 |
+
29 shell
|
| 349 |
+
3 Phyllospadix detritus
|
| 350 |
+
1 Spectrunculus grandis
|
| 351 |
+
18 shell fragment
|
| 352 |
+
9 Paralomis verrilli
|
| 353 |
+
5 Hydrolagus
|
| 354 |
+
21 Actinopterygii
|
| 355 |
+
26 Parmaturus xaniurus
|
| 356 |
+
3 whale carcass
|
| 357 |
+
1 Pterasteridae arm
|
| 358 |
+
5 Annelida
|
| 359 |
+
2 Lyrocteis
|
| 360 |
+
14 Echiura
|
| 361 |
+
11 Vanhoeffenura pulchra
|
| 362 |
+
14 Bolinopsis infundibulum
|
| 363 |
+
31 Colossendeidae
|
| 364 |
+
18 Bathochordaeus stygius
|
| 365 |
+
44 Sebastes jordani
|
| 366 |
+
3 Platyctenida
|
| 367 |
+
2 Saxipendium implicatum
|
| 368 |
+
2 TorquaratoridaeB sp. 2
|
| 369 |
+
28 Pachycara bulbiceps
|
| 370 |
+
10 Hydractiniidae
|
| 371 |
+
47 Psamminidae sp. 2
|
| 372 |
+
1 Tjalfiellidae
|
| 373 |
+
62 Myxoderma
|
| 374 |
+
5 Hyocrinidae
|
| 375 |
+
3 Chondrocladia
|
| 376 |
+
78 Cystocrepis setigera
|
| 377 |
+
19 Munidopsis kensmithi
|
| 378 |
+
2 Radiozoa
|
| 379 |
+
22 Chaetognatha
|
| 380 |
+
14 Siphonophorae
|
| 381 |
+
36 Chrysogorgia
|
| 382 |
+
13 Pseudostichopus mollis
|
| 383 |
+
10 Benthothuria
|
| 384 |
+
21 Bolocera kensmithi
|
| 385 |
+
11 Sebastes semicinctus
|
| 386 |
+
1 Galiteuthis phyllura
|
| 387 |
+
2 Octopodinae
|
| 388 |
+
2 Serrivomer
|
| 389 |
+
8 Demospongiae
|
| 390 |
+
6 Latrunculia (Latrunculia) austini
|
| 391 |
+
15 Dromalia alexandri
|
| 392 |
+
82 Scleractinia
|
| 393 |
+
16 Plesionika
|
| 394 |
+
27 bacterial mat
|
| 395 |
+
2 Chondrocladia (Symmetrocladia) lyra
|
| 396 |
+
13 Neoloricata
|
| 397 |
+
2 asteroid feeding depression
|
| 398 |
+
8 Bathyalcyon robustum
|
| 399 |
+
2 Bathypterois
|
| 400 |
+
2 Distichoptilum
|
| 401 |
+
2 Paraliparis cephalus
|
| 402 |
+
9 Sebastes serranoides
|
| 403 |
+
12 Goniasteridae
|
| 404 |
+
3 ledge
|
| 405 |
+
21 Tromikosoma panamense
|
| 406 |
+
10 Ctenophora
|
| 407 |
+
7 Docosaccus maculatus
|
| 408 |
+
2 sinker
|
| 409 |
+
20 Lophaster furcilliger
|
| 410 |
+
46 Sebastes cortezi
|
| 411 |
+
8 Culeolus
|
| 412 |
+
4 Mysidacea
|
| 413 |
+
64 Bathydorus laevis pseudospinosus
|
| 414 |
+
2 Alepocephalus tenebrosus
|
| 415 |
+
12 Echinoidea
|
| 416 |
+
13 Heterozonias alternatus
|
| 417 |
+
19 Smithsonius dorothea
|
| 418 |
+
2 Heterocarpus sp. 2
|
| 419 |
+
2 Eucryphycus californicus
|
| 420 |
+
104 Polychaeta tube
|
| 421 |
+
4 Cirroteuthis
|
| 422 |
+
20 Tergivelum baldwinae
|
| 423 |
+
2 Tiburonia granrojo
|
| 424 |
+
7 Liparidae
|
| 425 |
+
19 Riftia pachyptila
|
| 426 |
+
2 Hydroidolina
|
| 427 |
+
9 Plexauridae
|
| 428 |
+
5 Bathylagidae
|
| 429 |
+
4 Lepidion
|
| 430 |
+
7 Sclerothamnopsis
|
| 431 |
+
1 Careproctus ovigerus
|
| 432 |
+
3 Psychropotes depressa
|
| 433 |
+
11 Icelinus filamentosus
|
| 434 |
+
24 Chrysogorgia monticola
|
| 435 |
+
3 wood
|
| 436 |
+
13 Bathochordaeus inner filter
|
| 437 |
+
15 Sebastes entomelas
|
| 438 |
+
11 Anthozoa
|
| 439 |
+
6 Bathypterois pectinatus
|
| 440 |
+
20 Cladorhiza kensmithi
|
| 441 |
+
15 Aporocidaris milleri
|
| 442 |
+
6 Ischnomesidae
|
| 443 |
+
9 Staurocalyptus solidus
|
| 444 |
+
18 Anthoptilum lithophilum
|
| 445 |
+
5 Atolla wyvillei
|
| 446 |
+
6 Erenna richardi
|
| 447 |
+
4 Hyalonematidae
|
| 448 |
+
1 Pleurobranchaea
|
| 449 |
+
3 Sergestidae
|
| 450 |
+
6 Thermarces cerberus
|
| 451 |
+
43 Pennatula
|
| 452 |
+
3 Moloha faxoni
|
| 453 |
+
5 Munida quadrispina
|
| 454 |
+
2 Lophiiformes
|
| 455 |
+
11 Benthoctopus
|
| 456 |
+
60 Strongylocentrotus
|
| 457 |
+
2 kelp
|
| 458 |
+
5 Nanomia nectosome
|
| 459 |
+
10 Sicyonis
|
| 460 |
+
17 Chrysogorgia pinnata
|
| 461 |
+
4 Forskalia formosa
|
| 462 |
+
39 Sebastes ruberrimus
|
| 463 |
+
10 Sebastes levis
|
| 464 |
+
14 Praya dubia nectosome
|
| 465 |
+
17 Praya dubia
|
| 466 |
+
2 Pleuronectiformes 3
|
| 467 |
+
3 Chuniphyes multidentata
|
| 468 |
+
1 Dictyocalyx
|
| 469 |
+
1 Zaniolepis frenata
|
| 470 |
+
4 Octopus
|
| 471 |
+
6 Forcipulatacea
|
| 472 |
+
2 Eretmichthys pinnatus
|
| 473 |
+
2 Dibranchus hystrix
|
| 474 |
+
1 Coelorinchus spilonotus
|
| 475 |
+
2 Pseudobathylagus
|
| 476 |
+
6 Benthodytes
|
| 477 |
+
6 Alternatipathes
|
| 478 |
+
10 Lillipathes
|
| 479 |
+
46 Protoptilum sp. 2
|
| 480 |
+
5 Hastigerinella digitata
|
| 481 |
+
8 Bargmannia elongata
|
| 482 |
+
7 Bargmannia elongata nectosome
|
| 483 |
+
8 Psychronaetes
|
| 484 |
+
6 Bathysaurus mollis
|
| 485 |
+
12 Lycodinae
|
| 486 |
+
3 Euplectellidae
|
| 487 |
+
6 Pasiphaea
|
| 488 |
+
23 Bathysiphon
|
| 489 |
+
4 Beroe abyssicola
|
| 490 |
+
11 Tomopteris
|
| 491 |
+
8 Polychaeta
|
| 492 |
+
5 Articulata
|
| 493 |
+
3 Apostichopus californicus
|
| 494 |
+
23 Kophobelemnon
|
| 495 |
+
6 Bolinopsis
|
| 496 |
+
3 Euryalida
|
| 497 |
+
2 Pennatulidae
|
| 498 |
+
2 Gastroptychus
|
| 499 |
+
3 molt
|
| 500 |
+
2 Corallimorphus denhartogi
|
| 501 |
+
8 Neptunea eggcase
|
| 502 |
+
11 Octacnemidae sp. 2
|
| 503 |
+
5 Xeneretmus
|
| 504 |
+
3 Dibranchus spinosus
|
| 505 |
+
30 Epizoanthus stellaris
|
| 506 |
+
4 Pennatulacea sp. 2
|
| 507 |
+
2 Sebastes borealis
|
| 508 |
+
2 Aeolidiidae
|
| 509 |
+
43 Mitrocoma cellularia
|
| 510 |
+
3 Tromikosoma
|
| 511 |
+
1 Icichthys lockingtoni
|
| 512 |
+
6 Solmissus incisa
|
| 513 |
+
13 Sebastes pinniger
|
| 514 |
+
5 Enteropneusta
|
| 515 |
+
5 Sebastes auriculatus
|
| 516 |
+
6 Megalodicopia
|
| 517 |
+
10 Asthenactis papyraceus
|
| 518 |
+
4 Sebastes miniatus-pinniger complex
|
| 519 |
+
8 Asthenactis
|
| 520 |
+
3 test
|
| 521 |
+
3 Icelinus
|
| 522 |
+
1 Parantipathes
|
| 523 |
+
13 Sebastes macdonaldi
|
| 524 |
+
4 Sebastes mystinus
|
| 525 |
+
5 Physiculus nematopus-rastrelliger complex
|
| 526 |
+
1 Sebastes rosenblatti
|
| 527 |
+
16 Bathochordaeus sinker
|
| 528 |
+
3 Distichoptilum gracile
|
| 529 |
+
1 kelp holdfast
|
| 530 |
+
1 Rhinochimaeridae
|
| 531 |
+
3 Echinocrepis setigera
|
| 532 |
+
9 Sebastes caurinus
|
| 533 |
+
2 Egregia menziesii
|
| 534 |
+
1 Myriothelidae
|
| 535 |
+
5 coiled fecal cast
|
| 536 |
+
1 Cystechinus giganteus
|
| 537 |
+
8 Bathochordaeus mcnutti inner filter
|
| 538 |
+
8 Bathochordaeus mcnutti
|
| 539 |
+
1 Cladorhiza
|
| 540 |
+
6 Cirripedia
|
| 541 |
+
2 Swiftia kol
|
| 542 |
+
4 Phyllochaetopterus gigas
|
| 543 |
+
10 Hymenaster koehleri
|
| 544 |
+
3 sinker outer filter
|
| 545 |
+
11 Allocentrotus fragilis
|
| 546 |
+
2 Luciobrotula sp. A
|
| 547 |
+
1 Opisthoteuthis
|
| 548 |
+
1 Haliscera bigelowi
|
| 549 |
+
12 Scotoplanes clarki
|
| 550 |
+
2 Lyssacinosida sp. 2
|
| 551 |
+
2 larvacean outer filter
|
| 552 |
+
1 Ophichthus frontalis
|
| 553 |
+
3 Calyptrophora
|
| 554 |
+
6 Provannidae
|
| 555 |
+
3 Marine organism
|
| 556 |
+
3 Farrea truncata complex
|
| 557 |
+
3 Actinoscyphia
|
| 558 |
+
5 Exocoelactis
|
| 559 |
+
12 Kophobelemnidae
|
| 560 |
+
1 Lychnagalma nectosome
|
| 561 |
+
1 Lychnagalma
|
| 562 |
+
8 Caenogastropoda
|
| 563 |
+
5 Zoroasteridae
|
| 564 |
+
13 Bathochordaeus outer filter
|
| 565 |
+
3 Vanhoeffenura
|
| 566 |
+
2 Stylasterias
|
| 567 |
+
4 Calycophorae
|
| 568 |
+
4 Vitreosalpa gemini
|
| 569 |
+
2 Anguilliformes
|
| 570 |
+
1 Calocarides quinqueseriatus
|
| 571 |
+
1 Fungiacyathus
|
| 572 |
+
3 Candelabridae sp. 2
|
| 573 |
+
2 Tergivelum sp. A
|
| 574 |
+
1 Mesochordaeus erythrocephalus
|
| 575 |
+
1 Monothalamea
|
| 576 |
+
4 Paradiopatra
|
| 577 |
+
2 Munida bapensis
|
| 578 |
+
8 Sebastes crameri-melanostomus complex
|
| 579 |
+
1 Asterozoa
|
| 580 |
+
6 Patiria miniata
|
| 581 |
+
1 Ophidiiformes
|
| 582 |
+
3 Salpida
|
| 583 |
+
2 Coelorinchus scaphopsis
|
| 584 |
+
2 Tomopteris nisseni
|
| 585 |
+
2 Camptoplites sp. A
|
| 586 |
+
2 Psychropotidae
|
| 587 |
+
1 Paxillosida
|
| 588 |
+
2 Dendronotus patricki
|
| 589 |
+
4 Oneirophanta
|
| 590 |
+
1 Lensia conoidea nectosome
|
| 591 |
+
2 Lensia conoidea
|
| 592 |
+
4 Glyphocrangon vicaria
|
| 593 |
+
3 Dipsacaster eximius
|
| 594 |
+
3 Bathydorus
|
| 595 |
+
4 Bathycrinidae
|
| 596 |
+
4 Sebastolobus head
|
| 597 |
+
1 Doryteuthis (Amerigo) opalescens eggs
|
| 598 |
+
5 Sebastes crameri
|
| 599 |
+
1 Thetys vagina
|
| 600 |
+
5 Sebastes ovalis
|
| 601 |
+
1 Lycodapus mandibularis
|
| 602 |
+
1 Sebastolobus tail
|
| 603 |
+
7 Sebastes goodei
|
| 604 |
+
1 Pseudobathylagus milleri
|
| 605 |
+
1 Narcomedusa
|
| 606 |
+
2 Chiroteuthis calyx
|
| 607 |
+
1 Heterobranchia
|
| 608 |
+
1 Octacnemidae
|
| 609 |
+
1 inner filter
|
| 610 |
+
1 Pentametrocrinus paucispinulus
|
| 611 |
+
2 Beroe gracilis
|
| 612 |
+
1 Schizopathidae
|
| 613 |
+
2 Dytaster gilberti
|
| 614 |
+
3 Physiculus sp. 2
|
| 615 |
+
1 Octopodidae tentacle
|
| 616 |
+
5 Mysidae
|
| 617 |
+
1 Antipatharia
|
| 618 |
+
2 Lychnagalma utricularia nectosome
|
| 619 |
+
2 Lychnagalma utricularia
|
| 620 |
+
1 Ridgeia
|
| 621 |
+
1 Actinauge verrillii
|
| 622 |
+
1 Oikopleuridae outer filter
|
| 623 |
+
1 Fecampiid eggcase
|
| 624 |
+
2 Chilara taylori
|
| 625 |
+
1 Acesta
|
| 626 |
+
3 Caulophacus
|
| 627 |
+
2 Parophrys vetulus
|
| 628 |
+
1 Dibranchus sp. A
|
| 629 |
+
1 Holothuria (Vaneyothuria) zacae
|
| 630 |
+
2 Prayidae nectosome
|
| 631 |
+
1 Acanthephyra
|
| 632 |
+
1 Bathycrinus complanatus
|
| 633 |
+
1 Munnopsis
|
| 634 |
+
1 Alcyoniidae
|
| 635 |
+
1 Microstomus bathybius
|
| 636 |
+
1 Theudoidea
|
| 637 |
+
4 Hydromedusae
|
| 638 |
+
1 Protoptilum
|
| 639 |
+
2 Bathyphellia
|
| 640 |
+
1 Euplokamidae
|
| 641 |
+
1 Microstomus pacificus sole
|
| 642 |
+
3 Hormiphora californensis
|
| 643 |
+
1 Leptocephalus-3
|
| 644 |
+
2 Verum proximum
|
| 645 |
+
1 Lepidopsetta bilineata
|
| 646 |
+
1 Corolla spectabilis
|
| 647 |
+
1 Haliscera conica
|
| 648 |
+
18 Brisaster
|
| 649 |
+
2 Oikopleura outer filter
|
| 650 |
+
1 Paulasterias mcclaini
|
| 651 |
+
1 Sicyonis careyi
|
| 652 |
+
2 Iosactis
|
| 653 |
+
1 Oikopleuridae inner filter
|
| 654 |
+
1 Chromista
|
| 655 |
+
1 Mola mola
|
| 656 |
+
1 Melanostigma pammelas
|
| 657 |
+
1 Scrippsia pacifica
|
| 658 |
+
1 larvacean house
|
| 659 |
+
4 Sebastes phillipsi
|
| 660 |
+
1 Peinaleopolynoe orphanae
|
| 661 |
+
3 Cnidaria
|
| 662 |
+
1 salp detritus
|
| 663 |
+
5 Atolla vanhoeffeni
|
| 664 |
+
1 Appendicularia outer filter
|
| 665 |
+
1 Appendicularia inner filter
|
| 666 |
+
2 Sebastes simulator
|
| 667 |
+
1 Acharax
|
| 668 |
+
2 Plesionika sp. A
|
| 669 |
+
1 Mediaster tenellus
|
| 670 |
+
1 Eutonina
|
| 671 |
+
2 Octopoteuthis deletron
|
| 672 |
+
1 Crustacea
|
| 673 |
+
2 Psathyrometra
|
| 674 |
+
2 Patellogastropoda
|
| 675 |
+
1 Sebastes cortezi tail
|
| 676 |
+
2 Yoda sp. A
|
| 677 |
+
1 Lophiodes caulinaris
|
| 678 |
+
1 Ptilosarcus
|
| 679 |
+
1 Gnathophis cinctus
|
| 680 |
+
4 Munidopsis sp. 2
|
| 681 |
+
2 salp chain
|
| 682 |
+
1 Oikopleuridae
|
| 683 |
+
1 Vogtia
|
| 684 |
+
2 Rossellidae
|
| 685 |
+
3 detrital aggregate
|
| 686 |
+
1 Sebastes maliger
|
| 687 |
+
1 Tuscaretta
|
| 688 |
+
1 Chaunacops coloratus
|
| 689 |
+
1 Pleurobrachiidae
|
| 690 |
+
1 Tenebrincola cukri
|
| 691 |
+
1 Amblyraja hyperborea
|
docs/gradio/requirements.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
tator
|
| 2 |
+
yolov5==6.2.3
|
docs/gradio/tator_inference.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import logging
|
| 3 |
+
from tempfile import TemporaryFile
|
| 4 |
+
|
| 5 |
+
import cv2
|
| 6 |
+
import numpy as np
|
| 7 |
+
from PIL import Image
|
| 8 |
+
|
| 9 |
+
import tator
|
| 10 |
+
import inference
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
logger = logging.getLogger(__name__)
|
| 14 |
+
logger.setLevel(logging.INFO)
|
| 15 |
+
|
| 16 |
+
# Read environment variables that are provided from TATOR
|
| 17 |
+
host = os.getenv('HOST')
|
| 18 |
+
token = os.getenv('TOKEN')
|
| 19 |
+
project_id = int(os.getenv('PROJECT_ID'))
|
| 20 |
+
media_ids = [int(id_) for id_ in os.getenv('MEDIA_IDS').split(',')]
|
| 21 |
+
frames_per_inference = int(os.getenv('FRAMES_PER_INFERENCE', 30))
|
| 22 |
+
|
| 23 |
+
# Set up the TATOR API.
|
| 24 |
+
api = tator.get_api(host, token)
|
| 25 |
+
|
| 26 |
+
# Iterate through each video.
|
| 27 |
+
for media_id in media_ids:
|
| 28 |
+
|
| 29 |
+
# Download video.
|
| 30 |
+
media = api.get_media(media_id)
|
| 31 |
+
logger.info(f"Downloading {media.name}...")
|
| 32 |
+
out_path = f"/tmp/{media.name}"
|
| 33 |
+
for progress in tator.util.download_media(api, media, out_path):
|
| 34 |
+
logger.info(f"Download progress: {progress}%")
|
| 35 |
+
|
| 36 |
+
# Do inference on each video.
|
| 37 |
+
logger.info(f"Doing inference on {media.name}...")
|
| 38 |
+
localizations = []
|
| 39 |
+
vid = cv2.VideoCapture(out_path)
|
| 40 |
+
frame_number = 0
|
| 41 |
+
|
| 42 |
+
# Read *every* frame from the video, break when at the end.
|
| 43 |
+
while True:
|
| 44 |
+
ret, frame = vid.read()
|
| 45 |
+
if not ret:
|
| 46 |
+
break
|
| 47 |
+
|
| 48 |
+
# Create a temporary file, access the image data, save data to file.
|
| 49 |
+
framefile = TemporaryFile(suffix='.jpg')
|
| 50 |
+
im = Image.fromarray(frame)
|
| 51 |
+
im.save(framefile)
|
| 52 |
+
|
| 53 |
+
# For every N frames, make a prediction; append prediction results
|
| 54 |
+
# to a list, increase the frame count.
|
| 55 |
+
if frame_number % frames_per_inference == 0:
|
| 56 |
+
|
| 57 |
+
spec = {}
|
| 58 |
+
|
| 59 |
+
# Predictions contains all information inside pandas dataframe
|
| 60 |
+
predictions = inference.run_inference(framefile)
|
| 61 |
+
|
| 62 |
+
for i, r in predictions.pandas().xyxy[0].iterrows:
|
| 63 |
+
|
| 64 |
+
spec['media_id'] = media_id
|
| 65 |
+
spec['type'] = None # Unsure, docs not specific
|
| 66 |
+
spec['frame'] = frame_number
|
| 67 |
+
|
| 68 |
+
x, y, x2, y2 = r['xmin'], r['ymin'], r['xmax'], r['ymax']
|
| 69 |
+
w, h = x2 - x, y2 - y
|
| 70 |
+
|
| 71 |
+
spec['x'] = x
|
| 72 |
+
spec['y'] = y
|
| 73 |
+
spec['width'] = w
|
| 74 |
+
spec['height'] = h
|
| 75 |
+
spec['class_category'] = r['name']
|
| 76 |
+
spec['confidence'] = r['confidence']
|
| 77 |
+
|
| 78 |
+
localizations.append(spec)
|
| 79 |
+
|
| 80 |
+
frame_number += 1
|
| 81 |
+
|
| 82 |
+
# End interaction with video properly.
|
| 83 |
+
vid.release()
|
| 84 |
+
|
| 85 |
+
logger.info(f"Uploading object detections on {media.name}...")
|
| 86 |
+
|
| 87 |
+
# Create the localizations in the video.
|
| 88 |
+
num_created = 0
|
| 89 |
+
for response in tator.util.chunked_create(api.create_localization_list,
|
| 90 |
+
project_id,
|
| 91 |
+
localization_spec=localizations):
|
| 92 |
+
num_created += len(response.id)
|
| 93 |
+
|
| 94 |
+
# Output pretty logging information.
|
| 95 |
+
logger.info(f"Successfully created {num_created} localizations on "
|
| 96 |
+
f"{media.name}!")
|
| 97 |
+
|
| 98 |
+
logger.info("-------------------------------------------------")
|
| 99 |
+
|
| 100 |
+
logger.info(f"Completed inference on {len(media_ids)} files.")
|
requirements.txt
CHANGED
|
@@ -21,6 +21,9 @@ huggingface-hub==0.19.4
|
|
| 21 |
python-multipart==0.0.6
|
| 22 |
aiofiles==23.2.1
|
| 23 |
|
|
|
|
|
|
|
|
|
|
| 24 |
# Performance monitoring and optimization
|
| 25 |
psutil==5.9.6
|
| 26 |
|
|
|
|
| 21 |
python-multipart==0.0.6
|
| 22 |
aiofiles==23.2.1
|
| 23 |
|
| 24 |
+
# Templates and Static Files (for dashboard)
|
| 25 |
+
jinja2==3.1.2
|
| 26 |
+
|
| 27 |
# Performance monitoring and optimization
|
| 28 |
psutil==5.9.6
|
| 29 |
|
static/css/dashboard.css
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Dashboard-specific styles */
|
| 2 |
+
|
| 3 |
+
.dashboard {
|
| 4 |
+
max-width: 1400px;
|
| 5 |
+
margin: 0 auto;
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
/* Page Header */
|
| 9 |
+
.page-header {
|
| 10 |
+
text-align: center;
|
| 11 |
+
margin-bottom: var(--spacing-xl);
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
.page-description {
|
| 15 |
+
font-size: 1.125rem;
|
| 16 |
+
color: var(--gray-600);
|
| 17 |
+
max-width: 600px;
|
| 18 |
+
margin: 0 auto;
|
| 19 |
+
line-height: 1.6;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
/* Status Banner */
|
| 23 |
+
.status-banner {
|
| 24 |
+
background: white;
|
| 25 |
+
border: 1px solid var(--gray-200);
|
| 26 |
+
border-radius: var(--radius-lg);
|
| 27 |
+
padding: var(--spacing-md);
|
| 28 |
+
margin-bottom: var(--spacing-xl);
|
| 29 |
+
display: flex;
|
| 30 |
+
align-items: center;
|
| 31 |
+
justify-content: space-between;
|
| 32 |
+
box-shadow: var(--shadow-sm);
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
.status-indicator {
|
| 36 |
+
display: flex;
|
| 37 |
+
align-items: center;
|
| 38 |
+
gap: var(--spacing-sm);
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
.status-dot {
|
| 42 |
+
width: 12px;
|
| 43 |
+
height: 12px;
|
| 44 |
+
border-radius: 50%;
|
| 45 |
+
background: var(--gray-400);
|
| 46 |
+
animation: pulse 2s infinite;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
.status-dot.healthy {
|
| 50 |
+
background: var(--success-green);
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
.status-dot.error {
|
| 54 |
+
background: var(--error-red);
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
.status-text {
|
| 58 |
+
font-weight: 500;
|
| 59 |
+
color: var(--gray-700);
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
.model-info {
|
| 63 |
+
font-size: 0.875rem;
|
| 64 |
+
color: var(--gray-500);
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
@keyframes pulse {
|
| 68 |
+
0%, 100% { opacity: 1; }
|
| 69 |
+
50% { opacity: 0.5; }
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
/* Dashboard Grid */
|
| 73 |
+
.dashboard-grid {
|
| 74 |
+
display: grid;
|
| 75 |
+
grid-template-columns: 1fr 1fr 1fr;
|
| 76 |
+
gap: var(--spacing-xl);
|
| 77 |
+
margin-bottom: var(--spacing-2xl);
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
.panel {
|
| 81 |
+
min-height: 600px;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
/* Upload Area */
|
| 85 |
+
.upload-area {
|
| 86 |
+
border: 2px dashed var(--gray-300);
|
| 87 |
+
border-radius: var(--radius-lg);
|
| 88 |
+
padding: var(--spacing-2xl);
|
| 89 |
+
text-align: center;
|
| 90 |
+
cursor: pointer;
|
| 91 |
+
transition: all 0.2s ease;
|
| 92 |
+
margin-bottom: var(--spacing-lg);
|
| 93 |
+
min-height: 200px;
|
| 94 |
+
display: flex;
|
| 95 |
+
align-items: center;
|
| 96 |
+
justify-content: center;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
.upload-area:hover {
|
| 100 |
+
border-color: var(--primary-blue);
|
| 101 |
+
background-color: var(--gray-50);
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
.upload-area.dragover {
|
| 105 |
+
border-color: var(--primary-blue);
|
| 106 |
+
background-color: #eff6ff;
|
| 107 |
+
transform: scale(1.02);
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
.upload-area.has-image {
|
| 111 |
+
border-style: solid;
|
| 112 |
+
border-color: var(--success-green);
|
| 113 |
+
background-color: var(--gray-50);
|
| 114 |
+
padding: var(--spacing-md);
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
.upload-content {
|
| 118 |
+
display: flex;
|
| 119 |
+
flex-direction: column;
|
| 120 |
+
align-items: center;
|
| 121 |
+
gap: var(--spacing-md);
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
.upload-icon {
|
| 125 |
+
font-size: 3rem;
|
| 126 |
+
color: var(--gray-400);
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
.upload-primary {
|
| 130 |
+
font-size: 1.125rem;
|
| 131 |
+
font-weight: 500;
|
| 132 |
+
color: var(--gray-700);
|
| 133 |
+
margin: 0;
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
.upload-secondary {
|
| 137 |
+
font-size: 0.875rem;
|
| 138 |
+
color: var(--gray-500);
|
| 139 |
+
margin: 0;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
/* Settings Section */
|
| 143 |
+
.settings-section {
|
| 144 |
+
margin-bottom: var(--spacing-lg);
|
| 145 |
+
padding-top: var(--spacing-lg);
|
| 146 |
+
border-top: 1px solid var(--gray-200);
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
.settings-section h4 {
|
| 150 |
+
margin-bottom: var(--spacing-md);
|
| 151 |
+
color: var(--gray-700);
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
.settings-grid {
|
| 155 |
+
display: grid;
|
| 156 |
+
gap: var(--spacing-md);
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
.setting-item label {
|
| 160 |
+
display: block;
|
| 161 |
+
font-size: 0.875rem;
|
| 162 |
+
font-weight: 500;
|
| 163 |
+
color: var(--gray-700);
|
| 164 |
+
margin-bottom: var(--spacing-xs);
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
.slider-container {
|
| 168 |
+
display: flex;
|
| 169 |
+
align-items: center;
|
| 170 |
+
gap: var(--spacing-md);
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
.slider-container input[type="range"] {
|
| 174 |
+
flex: 1;
|
| 175 |
+
height: 6px;
|
| 176 |
+
border-radius: 3px;
|
| 177 |
+
background: var(--gray-200);
|
| 178 |
+
outline: none;
|
| 179 |
+
-webkit-appearance: none;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
.slider-container input[type="range"]::-webkit-slider-thumb {
|
| 183 |
+
-webkit-appearance: none;
|
| 184 |
+
width: 20px;
|
| 185 |
+
height: 20px;
|
| 186 |
+
border-radius: 50%;
|
| 187 |
+
background: var(--primary-blue);
|
| 188 |
+
cursor: pointer;
|
| 189 |
+
box-shadow: var(--shadow-sm);
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
.slider-container input[type="range"]::-moz-range-thumb {
|
| 193 |
+
width: 20px;
|
| 194 |
+
height: 20px;
|
| 195 |
+
border-radius: 50%;
|
| 196 |
+
background: var(--primary-blue);
|
| 197 |
+
cursor: pointer;
|
| 198 |
+
border: none;
|
| 199 |
+
box-shadow: var(--shadow-sm);
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
.slider-value {
|
| 203 |
+
font-size: 0.875rem;
|
| 204 |
+
font-weight: 500;
|
| 205 |
+
color: var(--primary-blue);
|
| 206 |
+
min-width: 40px;
|
| 207 |
+
text-align: right;
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
/* Button Styles */
|
| 211 |
+
.btn-full {
|
| 212 |
+
width: 100%;
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
/* Image Containers */
|
| 216 |
+
.image-container {
|
| 217 |
+
border: 1px solid var(--gray-200);
|
| 218 |
+
border-radius: var(--radius-md);
|
| 219 |
+
overflow: hidden;
|
| 220 |
+
min-height: 250px;
|
| 221 |
+
display: flex;
|
| 222 |
+
align-items: center;
|
| 223 |
+
justify-content: center;
|
| 224 |
+
background: var(--gray-50);
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
.image-container img {
|
| 228 |
+
max-width: 100%;
|
| 229 |
+
max-height: 100%;
|
| 230 |
+
object-fit: contain;
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
.image-placeholder {
|
| 234 |
+
text-align: center;
|
| 235 |
+
color: var(--gray-400);
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
.placeholder-icon {
|
| 239 |
+
font-size: 2rem;
|
| 240 |
+
margin-bottom: var(--spacing-sm);
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
/* Results Sections */
|
| 244 |
+
.annotated-section,
|
| 245 |
+
.metadata-section,
|
| 246 |
+
.species-section {
|
| 247 |
+
margin-bottom: var(--spacing-lg);
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
.annotated-section h4,
|
| 251 |
+
.metadata-section h4,
|
| 252 |
+
.species-section h4 {
|
| 253 |
+
margin-bottom: var(--spacing-md);
|
| 254 |
+
color: var(--gray-700);
|
| 255 |
+
font-size: 1rem;
|
| 256 |
+
font-weight: 600;
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
/* Metadata Grid */
|
| 260 |
+
.metadata-grid {
|
| 261 |
+
display: grid;
|
| 262 |
+
gap: var(--spacing-sm);
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
.metadata-item {
|
| 266 |
+
display: flex;
|
| 267 |
+
justify-content: space-between;
|
| 268 |
+
align-items: center;
|
| 269 |
+
padding: var(--spacing-sm);
|
| 270 |
+
background: var(--gray-50);
|
| 271 |
+
border-radius: var(--radius-sm);
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
.metadata-label {
|
| 275 |
+
font-size: 0.875rem;
|
| 276 |
+
color: var(--gray-600);
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
.metadata-value {
|
| 280 |
+
font-size: 0.875rem;
|
| 281 |
+
font-weight: 500;
|
| 282 |
+
color: var(--gray-900);
|
| 283 |
+
}
|
| 284 |
+
|
| 285 |
+
/* Species List */
|
| 286 |
+
.species-list {
|
| 287 |
+
display: grid;
|
| 288 |
+
gap: var(--spacing-sm);
|
| 289 |
+
max-height: 300px;
|
| 290 |
+
overflow-y: auto;
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
.species-item {
|
| 294 |
+
display: flex;
|
| 295 |
+
justify-content: space-between;
|
| 296 |
+
align-items: center;
|
| 297 |
+
padding: var(--spacing-sm);
|
| 298 |
+
background: white;
|
| 299 |
+
border: 1px solid var(--gray-200);
|
| 300 |
+
border-radius: var(--radius-sm);
|
| 301 |
+
transition: all 0.2s ease;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
.species-item:hover {
|
| 305 |
+
border-color: var(--primary-blue);
|
| 306 |
+
box-shadow: var(--shadow-sm);
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
.species-name {
|
| 310 |
+
font-size: 0.875rem;
|
| 311 |
+
font-weight: 500;
|
| 312 |
+
color: var(--gray-900);
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
.species-confidence {
|
| 316 |
+
font-size: 0.875rem;
|
| 317 |
+
font-weight: 600;
|
| 318 |
+
color: var(--primary-blue);
|
| 319 |
+
}
|
| 320 |
+
|
| 321 |
+
/* Responsive Design */
|
| 322 |
+
@media (max-width: 1024px) {
|
| 323 |
+
.dashboard-grid {
|
| 324 |
+
grid-template-columns: 1fr;
|
| 325 |
+
gap: var(--spacing-lg);
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
.status-banner {
|
| 329 |
+
flex-direction: column;
|
| 330 |
+
gap: var(--spacing-sm);
|
| 331 |
+
text-align: center;
|
| 332 |
+
}
|
| 333 |
+
}
|
| 334 |
+
|
| 335 |
+
@media (max-width: 768px) {
|
| 336 |
+
.upload-area {
|
| 337 |
+
padding: var(--spacing-lg);
|
| 338 |
+
min-height: 150px;
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
.upload-icon {
|
| 342 |
+
font-size: 2rem;
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
.upload-primary {
|
| 346 |
+
font-size: 1rem;
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
.settings-grid {
|
| 350 |
+
gap: var(--spacing-sm);
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
.image-container {
|
| 354 |
+
min-height: 200px;
|
| 355 |
+
}
|
| 356 |
+
}
|
static/css/main.css
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Marine Species API - Main Stylesheet */
|
| 2 |
+
|
| 3 |
+
:root {
|
| 4 |
+
/* Color Palette */
|
| 5 |
+
--primary-blue: #2563eb;
|
| 6 |
+
--success-green: #059669;
|
| 7 |
+
--error-red: #dc2626;
|
| 8 |
+
--warning-yellow: #d97706;
|
| 9 |
+
|
| 10 |
+
/* Grays */
|
| 11 |
+
--gray-50: #f9fafb;
|
| 12 |
+
--gray-100: #f3f4f6;
|
| 13 |
+
--gray-200: #e5e7eb;
|
| 14 |
+
--gray-300: #d1d5db;
|
| 15 |
+
--gray-400: #9ca3af;
|
| 16 |
+
--gray-500: #6b7280;
|
| 17 |
+
--gray-600: #4b5563;
|
| 18 |
+
--gray-700: #374151;
|
| 19 |
+
--gray-800: #1f2937;
|
| 20 |
+
--gray-900: #111827;
|
| 21 |
+
|
| 22 |
+
/* Spacing */
|
| 23 |
+
--spacing-xs: 0.25rem;
|
| 24 |
+
--spacing-sm: 0.5rem;
|
| 25 |
+
--spacing-md: 1rem;
|
| 26 |
+
--spacing-lg: 1.5rem;
|
| 27 |
+
--spacing-xl: 2rem;
|
| 28 |
+
--spacing-2xl: 3rem;
|
| 29 |
+
|
| 30 |
+
/* Border Radius */
|
| 31 |
+
--radius-sm: 6px;
|
| 32 |
+
--radius-md: 8px;
|
| 33 |
+
--radius-lg: 12px;
|
| 34 |
+
--radius-xl: 16px;
|
| 35 |
+
|
| 36 |
+
/* Shadows */
|
| 37 |
+
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
| 38 |
+
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
| 39 |
+
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
/* Reset and Base Styles */
|
| 43 |
+
* {
|
| 44 |
+
margin: 0;
|
| 45 |
+
padding: 0;
|
| 46 |
+
box-sizing: border-box;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
body {
|
| 50 |
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
| 51 |
+
font-size: 1rem;
|
| 52 |
+
line-height: 1.5;
|
| 53 |
+
color: var(--gray-900);
|
| 54 |
+
background-color: var(--gray-50);
|
| 55 |
+
min-height: 100vh;
|
| 56 |
+
display: flex;
|
| 57 |
+
flex-direction: column;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
/* Container */
|
| 61 |
+
.container {
|
| 62 |
+
max-width: 1200px;
|
| 63 |
+
margin: 0 auto;
|
| 64 |
+
padding: 0 var(--spacing-md);
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
/* Header */
|
| 68 |
+
.header {
|
| 69 |
+
background: white;
|
| 70 |
+
border-bottom: 1px solid var(--gray-200);
|
| 71 |
+
position: sticky;
|
| 72 |
+
top: 0;
|
| 73 |
+
z-index: 100;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
.header .container {
|
| 77 |
+
display: flex;
|
| 78 |
+
align-items: center;
|
| 79 |
+
justify-content: space-between;
|
| 80 |
+
padding: var(--spacing-md);
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
.nav-brand {
|
| 84 |
+
display: flex;
|
| 85 |
+
align-items: center;
|
| 86 |
+
gap: var(--spacing-sm);
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
.nav-icon {
|
| 90 |
+
font-size: 1.5rem;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
.nav-title {
|
| 94 |
+
font-size: 1.25rem;
|
| 95 |
+
font-weight: 600;
|
| 96 |
+
color: var(--gray-900);
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
.nav-tabs {
|
| 100 |
+
display: flex;
|
| 101 |
+
gap: var(--spacing-lg);
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
.nav-tab {
|
| 105 |
+
padding: var(--spacing-sm) var(--spacing-md);
|
| 106 |
+
text-decoration: none;
|
| 107 |
+
color: var(--gray-600);
|
| 108 |
+
font-weight: 500;
|
| 109 |
+
border-radius: var(--radius-md);
|
| 110 |
+
transition: all 0.2s ease;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
.nav-tab:hover {
|
| 114 |
+
color: var(--primary-blue);
|
| 115 |
+
background-color: var(--gray-100);
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
.nav-tab.active {
|
| 119 |
+
color: var(--primary-blue);
|
| 120 |
+
background-color: var(--gray-100);
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
/* Main Content */
|
| 124 |
+
.main {
|
| 125 |
+
flex: 1;
|
| 126 |
+
padding: var(--spacing-xl) 0;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
/* Footer */
|
| 130 |
+
.footer {
|
| 131 |
+
background: white;
|
| 132 |
+
border-top: 1px solid var(--gray-200);
|
| 133 |
+
padding: var(--spacing-lg) 0;
|
| 134 |
+
margin-top: auto;
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
.footer p {
|
| 138 |
+
text-align: center;
|
| 139 |
+
color: var(--gray-500);
|
| 140 |
+
font-size: 0.875rem;
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
/* Typography */
|
| 144 |
+
h1 {
|
| 145 |
+
font-size: 2rem;
|
| 146 |
+
font-weight: 600;
|
| 147 |
+
color: var(--gray-900);
|
| 148 |
+
margin-bottom: var(--spacing-lg);
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
h2 {
|
| 152 |
+
font-size: 1.5rem;
|
| 153 |
+
font-weight: 500;
|
| 154 |
+
color: var(--gray-900);
|
| 155 |
+
margin-bottom: var(--spacing-md);
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
h3 {
|
| 159 |
+
font-size: 1.25rem;
|
| 160 |
+
font-weight: 500;
|
| 161 |
+
color: var(--gray-900);
|
| 162 |
+
margin-bottom: var(--spacing-sm);
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
/* Cards */
|
| 166 |
+
.card {
|
| 167 |
+
background: white;
|
| 168 |
+
border: 1px solid var(--gray-200);
|
| 169 |
+
border-radius: var(--radius-lg);
|
| 170 |
+
box-shadow: var(--shadow-sm);
|
| 171 |
+
overflow: hidden;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
.card-header {
|
| 175 |
+
padding: var(--spacing-lg);
|
| 176 |
+
border-bottom: 1px solid var(--gray-200);
|
| 177 |
+
background: var(--gray-50);
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
.card-body {
|
| 181 |
+
padding: var(--spacing-lg);
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
.card-title {
|
| 185 |
+
font-size: 1.125rem;
|
| 186 |
+
font-weight: 600;
|
| 187 |
+
color: var(--gray-900);
|
| 188 |
+
margin: 0;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
/* Buttons */
|
| 192 |
+
.btn {
|
| 193 |
+
display: inline-flex;
|
| 194 |
+
align-items: center;
|
| 195 |
+
justify-content: center;
|
| 196 |
+
gap: var(--spacing-sm);
|
| 197 |
+
padding: 12px 24px;
|
| 198 |
+
font-size: 1rem;
|
| 199 |
+
font-weight: 500;
|
| 200 |
+
text-decoration: none;
|
| 201 |
+
border: none;
|
| 202 |
+
border-radius: var(--radius-md);
|
| 203 |
+
cursor: pointer;
|
| 204 |
+
transition: all 0.2s ease;
|
| 205 |
+
min-height: 44px;
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
.btn-primary {
|
| 209 |
+
background: var(--primary-blue);
|
| 210 |
+
color: white;
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
.btn-primary:hover {
|
| 214 |
+
background: #1d4ed8;
|
| 215 |
+
transform: translateY(-1px);
|
| 216 |
+
box-shadow: var(--shadow-md);
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
.btn-primary:disabled {
|
| 220 |
+
background: var(--gray-300);
|
| 221 |
+
cursor: not-allowed;
|
| 222 |
+
transform: none;
|
| 223 |
+
box-shadow: none;
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
.btn-secondary {
|
| 227 |
+
background: white;
|
| 228 |
+
color: var(--gray-700);
|
| 229 |
+
border: 1px solid var(--gray-300);
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
.btn-secondary:hover {
|
| 233 |
+
background: var(--gray-50);
|
| 234 |
+
border-color: var(--gray-400);
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
/* Loading Spinner */
|
| 238 |
+
.spinner {
|
| 239 |
+
width: 20px;
|
| 240 |
+
height: 20px;
|
| 241 |
+
border: 2px solid transparent;
|
| 242 |
+
border-top: 2px solid currentColor;
|
| 243 |
+
border-radius: 50%;
|
| 244 |
+
animation: spin 1s linear infinite;
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
@keyframes spin {
|
| 248 |
+
to {
|
| 249 |
+
transform: rotate(360deg);
|
| 250 |
+
}
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
/* Responsive Design */
|
| 254 |
+
@media (max-width: 768px) {
|
| 255 |
+
.container {
|
| 256 |
+
padding: 0 var(--spacing-sm);
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
.header .container {
|
| 260 |
+
flex-direction: column;
|
| 261 |
+
gap: var(--spacing-md);
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
.nav-tabs {
|
| 265 |
+
gap: var(--spacing-md);
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
h1 {
|
| 269 |
+
font-size: 1.75rem;
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
.main {
|
| 273 |
+
padding: var(--spacing-lg) 0;
|
| 274 |
+
}
|
| 275 |
+
}
|
static/js/dashboard.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Dashboard functionality for Marine Species API
|
| 2 |
+
|
| 3 |
+
class MarineDashboard {
|
| 4 |
+
constructor() {
|
| 5 |
+
this.currentImage = null;
|
| 6 |
+
this.currentImageFile = null;
|
| 7 |
+
this.isProcessing = false;
|
| 8 |
+
|
| 9 |
+
this.initializeElements();
|
| 10 |
+
this.bindEvents();
|
| 11 |
+
this.checkAPIStatus();
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
initializeElements() {
|
| 15 |
+
// Upload elements
|
| 16 |
+
this.uploadArea = document.getElementById('uploadArea');
|
| 17 |
+
this.fileInput = document.getElementById('fileInput');
|
| 18 |
+
this.identifyBtn = document.getElementById('identifyBtn');
|
| 19 |
+
|
| 20 |
+
// Settings elements
|
| 21 |
+
this.confidenceSlider = document.getElementById('confidenceSlider');
|
| 22 |
+
this.confidenceValue = document.getElementById('confidenceValue');
|
| 23 |
+
this.iouSlider = document.getElementById('iouSlider');
|
| 24 |
+
this.iouValue = document.getElementById('iouValue');
|
| 25 |
+
|
| 26 |
+
// Display elements
|
| 27 |
+
this.originalImageContainer = document.getElementById('originalImageContainer');
|
| 28 |
+
this.annotatedImageContainer = document.getElementById('annotatedImageContainer');
|
| 29 |
+
|
| 30 |
+
// Results elements
|
| 31 |
+
this.metadataSection = document.getElementById('metadataSection');
|
| 32 |
+
this.speciesSection = document.getElementById('speciesSection');
|
| 33 |
+
this.processingTime = document.getElementById('processingTime');
|
| 34 |
+
this.speciesCount = document.getElementById('speciesCount');
|
| 35 |
+
this.imageSize = document.getElementById('imageSize');
|
| 36 |
+
this.speciesList = document.getElementById('speciesList');
|
| 37 |
+
|
| 38 |
+
// Status elements
|
| 39 |
+
this.statusDot = document.getElementById('statusDot');
|
| 40 |
+
this.statusText = document.getElementById('statusText');
|
| 41 |
+
this.modelInfo = document.getElementById('modelInfo');
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
bindEvents() {
|
| 45 |
+
// Upload area events
|
| 46 |
+
this.uploadArea.addEventListener('click', () => this.fileInput.click());
|
| 47 |
+
this.uploadArea.addEventListener('dragover', this.handleDragOver.bind(this));
|
| 48 |
+
this.uploadArea.addEventListener('dragleave', this.handleDragLeave.bind(this));
|
| 49 |
+
this.uploadArea.addEventListener('drop', this.handleDrop.bind(this));
|
| 50 |
+
|
| 51 |
+
// File input change
|
| 52 |
+
this.fileInput.addEventListener('change', this.handleFileSelect.bind(this));
|
| 53 |
+
|
| 54 |
+
// Settings sliders
|
| 55 |
+
this.confidenceSlider.addEventListener('input', this.updateConfidenceValue.bind(this));
|
| 56 |
+
this.iouSlider.addEventListener('input', this.updateIouValue.bind(this));
|
| 57 |
+
|
| 58 |
+
// Identify button
|
| 59 |
+
this.identifyBtn.addEventListener('click', this.identifySpecies.bind(this));
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
// API Status Check
|
| 63 |
+
async checkAPIStatus() {
|
| 64 |
+
try {
|
| 65 |
+
const response = await fetch('/api/v1/health');
|
| 66 |
+
const data = await response.json();
|
| 67 |
+
|
| 68 |
+
if (data.model_loaded) {
|
| 69 |
+
this.statusDot.className = 'status-dot healthy';
|
| 70 |
+
this.statusText.textContent = 'API Ready';
|
| 71 |
+
|
| 72 |
+
if (data.model_info) {
|
| 73 |
+
this.modelInfo.textContent = `Model: ${data.model_info.model_name} (${data.model_info.total_classes} species)`;
|
| 74 |
+
}
|
| 75 |
+
} else {
|
| 76 |
+
this.statusDot.className = 'status-dot error';
|
| 77 |
+
this.statusText.textContent = 'Model Loading...';
|
| 78 |
+
this.modelInfo.textContent = 'Please wait while the model loads';
|
| 79 |
+
}
|
| 80 |
+
} catch (error) {
|
| 81 |
+
this.statusDot.className = 'status-dot error';
|
| 82 |
+
this.statusText.textContent = 'API Unavailable';
|
| 83 |
+
this.modelInfo.textContent = 'Unable to connect to API';
|
| 84 |
+
console.error('API status check failed:', error);
|
| 85 |
+
}
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
// Drag and Drop Handlers
|
| 89 |
+
handleDragOver(e) {
|
| 90 |
+
e.preventDefault();
|
| 91 |
+
this.uploadArea.classList.add('dragover');
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
handleDragLeave(e) {
|
| 95 |
+
e.preventDefault();
|
| 96 |
+
this.uploadArea.classList.remove('dragover');
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
handleDrop(e) {
|
| 100 |
+
e.preventDefault();
|
| 101 |
+
this.uploadArea.classList.remove('dragover');
|
| 102 |
+
|
| 103 |
+
const files = e.dataTransfer.files;
|
| 104 |
+
if (files.length > 0) {
|
| 105 |
+
this.processFile(files[0]);
|
| 106 |
+
}
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
// File Selection Handler
|
| 110 |
+
handleFileSelect(e) {
|
| 111 |
+
const file = e.target.files[0];
|
| 112 |
+
if (file) {
|
| 113 |
+
this.processFile(file);
|
| 114 |
+
}
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
// Process Selected File
|
| 118 |
+
processFile(file) {
|
| 119 |
+
// Validate file type
|
| 120 |
+
if (!file.type.startsWith('image/')) {
|
| 121 |
+
window.MarineAPI.utils.showNotification('Please select an image file', 'error');
|
| 122 |
+
return;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
// Validate file size (10MB limit)
|
| 126 |
+
if (file.size > 10 * 1024 * 1024) {
|
| 127 |
+
window.MarineAPI.utils.showNotification('File size must be less than 10MB', 'error');
|
| 128 |
+
return;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
this.currentImageFile = file;
|
| 132 |
+
this.displayOriginalImage(file);
|
| 133 |
+
this.identifyBtn.disabled = false;
|
| 134 |
+
|
| 135 |
+
// Update upload area
|
| 136 |
+
this.uploadArea.classList.add('has-image');
|
| 137 |
+
this.uploadArea.innerHTML = `
|
| 138 |
+
<div class="upload-content">
|
| 139 |
+
<div class="upload-icon">β
</div>
|
| 140 |
+
<div class="upload-text">
|
| 141 |
+
<p class="upload-primary">${file.name}</p>
|
| 142 |
+
<p class="upload-secondary">${window.MarineAPI.utils.formatFileSize(file.size)}</p>
|
| 143 |
+
</div>
|
| 144 |
+
</div>
|
| 145 |
+
`;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
// Display Original Image
|
| 149 |
+
displayOriginalImage(file) {
|
| 150 |
+
const reader = new FileReader();
|
| 151 |
+
reader.onload = (e) => {
|
| 152 |
+
this.currentImage = e.target.result;
|
| 153 |
+
this.originalImageContainer.innerHTML = `
|
| 154 |
+
<img src="${e.target.result}" alt="Original image" />
|
| 155 |
+
`;
|
| 156 |
+
};
|
| 157 |
+
reader.readAsDataURL(file);
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
// Settings Handlers
|
| 161 |
+
updateConfidenceValue() {
|
| 162 |
+
this.confidenceValue.textContent = `${this.confidenceSlider.value}%`;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
updateIouValue() {
|
| 166 |
+
this.iouValue.textContent = `${this.iouSlider.value}%`;
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
// Main Identification Function
|
| 170 |
+
async identifySpecies() {
|
| 171 |
+
if (!this.currentImage || this.isProcessing) return;
|
| 172 |
+
|
| 173 |
+
this.isProcessing = true;
|
| 174 |
+
window.MarineAPI.utils.setLoading(this.identifyBtn, true);
|
| 175 |
+
|
| 176 |
+
try {
|
| 177 |
+
// Prepare request data
|
| 178 |
+
const requestData = {
|
| 179 |
+
image: this.currentImage.split(',')[1], // Remove data:image/jpeg;base64, prefix
|
| 180 |
+
confidence_threshold: this.confidenceSlider.value / 100,
|
| 181 |
+
iou_threshold: this.iouSlider.value / 100,
|
| 182 |
+
image_size: 640,
|
| 183 |
+
return_annotated_image: true
|
| 184 |
+
};
|
| 185 |
+
|
| 186 |
+
// Make API request
|
| 187 |
+
const response = await fetch('/api/v1/detect', {
|
| 188 |
+
method: 'POST',
|
| 189 |
+
headers: {
|
| 190 |
+
'Content-Type': 'application/json',
|
| 191 |
+
},
|
| 192 |
+
body: JSON.stringify(requestData)
|
| 193 |
+
});
|
| 194 |
+
|
| 195 |
+
if (!response.ok) {
|
| 196 |
+
throw new Error(`API request failed: ${response.status}`);
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
const result = await response.json();
|
| 200 |
+
this.displayResults(result);
|
| 201 |
+
window.MarineAPI.utils.showNotification('Species identification completed!', 'success');
|
| 202 |
+
|
| 203 |
+
} catch (error) {
|
| 204 |
+
console.error('Identification failed:', error);
|
| 205 |
+
window.MarineAPI.utils.showNotification('Identification failed. Please try again.', 'error');
|
| 206 |
+
} finally {
|
| 207 |
+
this.isProcessing = false;
|
| 208 |
+
window.MarineAPI.utils.setLoading(this.identifyBtn, false);
|
| 209 |
+
}
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
// Display Results
|
| 213 |
+
displayResults(result) {
|
| 214 |
+
const { detections, annotated_image, processing_time, image_dimensions } = result;
|
| 215 |
+
|
| 216 |
+
// Display annotated image
|
| 217 |
+
if (annotated_image) {
|
| 218 |
+
this.annotatedImageContainer.innerHTML = `
|
| 219 |
+
<img src="data:image/jpeg;base64,${annotated_image}" alt="Annotated results" />
|
| 220 |
+
`;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
// Update metadata
|
| 224 |
+
this.processingTime.textContent = `${processing_time.toFixed(3)}s`;
|
| 225 |
+
this.speciesCount.textContent = detections.length;
|
| 226 |
+
this.imageSize.textContent = `${image_dimensions.width}Γ${image_dimensions.height}`;
|
| 227 |
+
|
| 228 |
+
// Show metadata section
|
| 229 |
+
this.metadataSection.style.display = 'block';
|
| 230 |
+
|
| 231 |
+
// Display species list
|
| 232 |
+
if (detections.length > 0) {
|
| 233 |
+
this.speciesList.innerHTML = detections.map(detection => `
|
| 234 |
+
<div class="species-item">
|
| 235 |
+
<span class="species-name">${detection.class_name}</span>
|
| 236 |
+
<span class="species-confidence">${(detection.confidence * 100).toFixed(1)}%</span>
|
| 237 |
+
</div>
|
| 238 |
+
`).join('');
|
| 239 |
+
this.speciesSection.style.display = 'block';
|
| 240 |
+
} else {
|
| 241 |
+
this.speciesList.innerHTML = '<p class="no-detections">No marine species detected. Try adjusting the confidence threshold.</p>';
|
| 242 |
+
this.speciesSection.style.display = 'block';
|
| 243 |
+
}
|
| 244 |
+
}
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
// Initialize dashboard when DOM is loaded
|
| 248 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 249 |
+
new MarineDashboard();
|
| 250 |
+
});
|
static/js/main.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Marine Species API - Main JavaScript
|
| 2 |
+
|
| 3 |
+
// Global state
|
| 4 |
+
window.MarineAPI = {
|
| 5 |
+
baseURL: window.location.origin,
|
| 6 |
+
currentImage: null,
|
| 7 |
+
isProcessing: false
|
| 8 |
+
};
|
| 9 |
+
|
| 10 |
+
// Utility functions
|
| 11 |
+
const utils = {
|
| 12 |
+
// Show/hide loading state
|
| 13 |
+
setLoading: (element, isLoading) => {
|
| 14 |
+
if (isLoading) {
|
| 15 |
+
element.disabled = true;
|
| 16 |
+
element.innerHTML = '<span class="spinner"></span> Processing...';
|
| 17 |
+
} else {
|
| 18 |
+
element.disabled = false;
|
| 19 |
+
element.innerHTML = element.dataset.originalText || 'Identify Marine Life';
|
| 20 |
+
}
|
| 21 |
+
},
|
| 22 |
+
|
| 23 |
+
// Format file size
|
| 24 |
+
formatFileSize: (bytes) => {
|
| 25 |
+
if (bytes === 0) return '0 Bytes';
|
| 26 |
+
const k = 1024;
|
| 27 |
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
| 28 |
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
| 29 |
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
| 30 |
+
},
|
| 31 |
+
|
| 32 |
+
// Show notification
|
| 33 |
+
showNotification: (message, type = 'info') => {
|
| 34 |
+
// Simple notification system
|
| 35 |
+
const notification = document.createElement('div');
|
| 36 |
+
notification.className = `notification notification-${type}`;
|
| 37 |
+
notification.textContent = message;
|
| 38 |
+
|
| 39 |
+
// Style the notification
|
| 40 |
+
Object.assign(notification.style, {
|
| 41 |
+
position: 'fixed',
|
| 42 |
+
top: '20px',
|
| 43 |
+
right: '20px',
|
| 44 |
+
padding: '12px 20px',
|
| 45 |
+
borderRadius: '8px',
|
| 46 |
+
color: 'white',
|
| 47 |
+
fontWeight: '500',
|
| 48 |
+
zIndex: '1000',
|
| 49 |
+
transform: 'translateX(100%)',
|
| 50 |
+
transition: 'transform 0.3s ease'
|
| 51 |
+
});
|
| 52 |
+
|
| 53 |
+
// Set background color based on type
|
| 54 |
+
const colors = {
|
| 55 |
+
success: '#059669',
|
| 56 |
+
error: '#dc2626',
|
| 57 |
+
warning: '#d97706',
|
| 58 |
+
info: '#2563eb'
|
| 59 |
+
};
|
| 60 |
+
notification.style.backgroundColor = colors[type] || colors.info;
|
| 61 |
+
|
| 62 |
+
document.body.appendChild(notification);
|
| 63 |
+
|
| 64 |
+
// Animate in
|
| 65 |
+
setTimeout(() => {
|
| 66 |
+
notification.style.transform = 'translateX(0)';
|
| 67 |
+
}, 100);
|
| 68 |
+
|
| 69 |
+
// Remove after 5 seconds
|
| 70 |
+
setTimeout(() => {
|
| 71 |
+
notification.style.transform = 'translateX(100%)';
|
| 72 |
+
setTimeout(() => {
|
| 73 |
+
document.body.removeChild(notification);
|
| 74 |
+
}, 300);
|
| 75 |
+
}, 5000);
|
| 76 |
+
}
|
| 77 |
+
};
|
| 78 |
+
|
| 79 |
+
// Initialize when DOM is loaded
|
| 80 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 81 |
+
console.log('π Marine Species API Dashboard Loaded');
|
| 82 |
+
|
| 83 |
+
// Store original button text for loading states
|
| 84 |
+
document.querySelectorAll('.btn').forEach(btn => {
|
| 85 |
+
btn.dataset.originalText = btn.textContent;
|
| 86 |
+
});
|
| 87 |
+
});
|
| 88 |
+
|
| 89 |
+
// Export utils for use in other scripts
|
| 90 |
+
window.MarineAPI.utils = utils;
|
templates/base.html
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>{% block title %}Marine Species Identification API{% endblock %}</title>
|
| 7 |
+
|
| 8 |
+
<!-- Inter Font -->
|
| 9 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 10 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 11 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
| 12 |
+
|
| 13 |
+
<!-- Custom CSS -->
|
| 14 |
+
<link rel="stylesheet" href="{{ url_for('static', path='/css/main.css') }}">
|
| 15 |
+
|
| 16 |
+
{% block extra_css %}{% endblock %}
|
| 17 |
+
</head>
|
| 18 |
+
<body>
|
| 19 |
+
<!-- Navigation Header -->
|
| 20 |
+
<header class="header">
|
| 21 |
+
<div class="container">
|
| 22 |
+
<div class="nav-brand">
|
| 23 |
+
<span class="nav-icon">π</span>
|
| 24 |
+
<span class="nav-title">Marine Species API</span>
|
| 25 |
+
</div>
|
| 26 |
+
|
| 27 |
+
<nav class="nav-tabs">
|
| 28 |
+
<a href="/" class="nav-tab {% if active_tab == 'dashboard' %}active{% endif %}">
|
| 29 |
+
Dashboard
|
| 30 |
+
</a>
|
| 31 |
+
<a href="/docs" class="nav-tab {% if active_tab == 'docs' %}active{% endif %}">
|
| 32 |
+
API Docs
|
| 33 |
+
</a>
|
| 34 |
+
<a href="/api/v1/info" class="nav-tab" target="_blank">
|
| 35 |
+
API Info
|
| 36 |
+
</a>
|
| 37 |
+
</nav>
|
| 38 |
+
</div>
|
| 39 |
+
</header>
|
| 40 |
+
|
| 41 |
+
<!-- Main Content -->
|
| 42 |
+
<main class="main">
|
| 43 |
+
<div class="container">
|
| 44 |
+
{% block content %}{% endblock %}
|
| 45 |
+
</div>
|
| 46 |
+
</main>
|
| 47 |
+
|
| 48 |
+
<!-- Footer -->
|
| 49 |
+
<footer class="footer">
|
| 50 |
+
<div class="container">
|
| 51 |
+
<p>© 2025 Marine Species Identification API. Powered by YOLOv5.</p>
|
| 52 |
+
</div>
|
| 53 |
+
</footer>
|
| 54 |
+
|
| 55 |
+
<!-- JavaScript -->
|
| 56 |
+
<script src="{{ url_for('static', path='/js/main.js') }}"></script>
|
| 57 |
+
{% block extra_js %}{% endblock %}
|
| 58 |
+
</body>
|
| 59 |
+
</html>
|
templates/dashboard.html
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{% extends "base.html" %}
|
| 2 |
+
|
| 3 |
+
{% block title %}Dashboard - Marine Species Identification API{% endblock %}
|
| 4 |
+
|
| 5 |
+
{% block extra_css %}
|
| 6 |
+
<link rel="stylesheet" href="{{ url_for('static', path='/css/dashboard.css') }}">
|
| 7 |
+
{% endblock %}
|
| 8 |
+
|
| 9 |
+
{% block content %}
|
| 10 |
+
<div class="dashboard">
|
| 11 |
+
<!-- Page Header -->
|
| 12 |
+
<div class="page-header">
|
| 13 |
+
<h1>π Marine Species Identification</h1>
|
| 14 |
+
<p class="page-description">
|
| 15 |
+
Upload an image to identify marine species using our advanced YOLOv5 model.
|
| 16 |
+
Supports 691+ species including fish, corals, sea stars, and more.
|
| 17 |
+
</p>
|
| 18 |
+
</div>
|
| 19 |
+
|
| 20 |
+
<!-- API Status Banner -->
|
| 21 |
+
<div class="status-banner" id="statusBanner">
|
| 22 |
+
<div class="status-indicator">
|
| 23 |
+
<span class="status-dot" id="statusDot"></span>
|
| 24 |
+
<span class="status-text" id="statusText">Checking API status...</span>
|
| 25 |
+
</div>
|
| 26 |
+
<div class="model-info" id="modelInfo"></div>
|
| 27 |
+
</div>
|
| 28 |
+
|
| 29 |
+
<!-- Main Dashboard Grid -->
|
| 30 |
+
<div class="dashboard-grid">
|
| 31 |
+
<!-- Input Panel -->
|
| 32 |
+
<div class="panel input-panel">
|
| 33 |
+
<div class="card">
|
| 34 |
+
<div class="card-header">
|
| 35 |
+
<h3 class="card-title">π€ Upload Image</h3>
|
| 36 |
+
</div>
|
| 37 |
+
<div class="card-body">
|
| 38 |
+
<!-- Upload Area -->
|
| 39 |
+
<div class="upload-area" id="uploadArea">
|
| 40 |
+
<div class="upload-content">
|
| 41 |
+
<div class="upload-icon">π·</div>
|
| 42 |
+
<div class="upload-text">
|
| 43 |
+
<p class="upload-primary">Drag image here or click to browse</p>
|
| 44 |
+
<p class="upload-secondary">PNG, JPG, JPEG up to 10MB</p>
|
| 45 |
+
</div>
|
| 46 |
+
</div>
|
| 47 |
+
<input type="file" id="fileInput" accept="image/*" hidden>
|
| 48 |
+
</div>
|
| 49 |
+
|
| 50 |
+
<!-- Settings -->
|
| 51 |
+
<div class="settings-section">
|
| 52 |
+
<h4>βοΈ Detection Settings</h4>
|
| 53 |
+
<div class="settings-grid">
|
| 54 |
+
<div class="setting-item">
|
| 55 |
+
<label for="confidenceSlider">Confidence Threshold</label>
|
| 56 |
+
<div class="slider-container">
|
| 57 |
+
<input type="range" id="confidenceSlider" min="0" max="100" value="25">
|
| 58 |
+
<span class="slider-value" id="confidenceValue">25%</span>
|
| 59 |
+
</div>
|
| 60 |
+
</div>
|
| 61 |
+
<div class="setting-item">
|
| 62 |
+
<label for="iouSlider">IoU Threshold</label>
|
| 63 |
+
<div class="slider-container">
|
| 64 |
+
<input type="range" id="iouSlider" min="0" max="100" value="45">
|
| 65 |
+
<span class="slider-value" id="iouValue">45%</span>
|
| 66 |
+
</div>
|
| 67 |
+
</div>
|
| 68 |
+
</div>
|
| 69 |
+
</div>
|
| 70 |
+
|
| 71 |
+
<!-- Action Button -->
|
| 72 |
+
<button class="btn btn-primary btn-full" id="identifyBtn" disabled>
|
| 73 |
+
π Identify Marine Life
|
| 74 |
+
</button>
|
| 75 |
+
</div>
|
| 76 |
+
</div>
|
| 77 |
+
</div>
|
| 78 |
+
|
| 79 |
+
<!-- Original Image Panel -->
|
| 80 |
+
<div class="panel image-panel">
|
| 81 |
+
<div class="card">
|
| 82 |
+
<div class="card-header">
|
| 83 |
+
<h3 class="card-title">πΌοΈ Original Image</h3>
|
| 84 |
+
</div>
|
| 85 |
+
<div class="card-body">
|
| 86 |
+
<div class="image-container" id="originalImageContainer">
|
| 87 |
+
<div class="image-placeholder">
|
| 88 |
+
<div class="placeholder-icon">πΌοΈ</div>
|
| 89 |
+
<p>Upload an image to see it here</p>
|
| 90 |
+
</div>
|
| 91 |
+
</div>
|
| 92 |
+
</div>
|
| 93 |
+
</div>
|
| 94 |
+
</div>
|
| 95 |
+
|
| 96 |
+
<!-- Results Panel -->
|
| 97 |
+
<div class="panel results-panel">
|
| 98 |
+
<div class="card">
|
| 99 |
+
<div class="card-header">
|
| 100 |
+
<h3 class="card-title">π― Detection Results</h3>
|
| 101 |
+
</div>
|
| 102 |
+
<div class="card-body">
|
| 103 |
+
<!-- Annotated Image -->
|
| 104 |
+
<div class="annotated-section">
|
| 105 |
+
<h4>Annotated Image</h4>
|
| 106 |
+
<div class="image-container" id="annotatedImageContainer">
|
| 107 |
+
<div class="image-placeholder">
|
| 108 |
+
<div class="placeholder-icon">π</div>
|
| 109 |
+
<p>Annotated results will appear here</p>
|
| 110 |
+
</div>
|
| 111 |
+
</div>
|
| 112 |
+
</div>
|
| 113 |
+
|
| 114 |
+
<!-- Detection Metadata -->
|
| 115 |
+
<div class="metadata-section" id="metadataSection" style="display: none;">
|
| 116 |
+
<h4>Detection Summary</h4>
|
| 117 |
+
<div class="metadata-grid">
|
| 118 |
+
<div class="metadata-item">
|
| 119 |
+
<span class="metadata-label">Processing Time</span>
|
| 120 |
+
<span class="metadata-value" id="processingTime">-</span>
|
| 121 |
+
</div>
|
| 122 |
+
<div class="metadata-item">
|
| 123 |
+
<span class="metadata-label">Species Found</span>
|
| 124 |
+
<span class="metadata-value" id="speciesCount">-</span>
|
| 125 |
+
</div>
|
| 126 |
+
<div class="metadata-item">
|
| 127 |
+
<span class="metadata-label">Image Size</span>
|
| 128 |
+
<span class="metadata-value" id="imageSize">-</span>
|
| 129 |
+
</div>
|
| 130 |
+
</div>
|
| 131 |
+
</div>
|
| 132 |
+
|
| 133 |
+
<!-- Species List -->
|
| 134 |
+
<div class="species-section" id="speciesSection" style="display: none;">
|
| 135 |
+
<h4>Detected Species</h4>
|
| 136 |
+
<div class="species-list" id="speciesList">
|
| 137 |
+
<!-- Species items will be populated here -->
|
| 138 |
+
</div>
|
| 139 |
+
</div>
|
| 140 |
+
</div>
|
| 141 |
+
</div>
|
| 142 |
+
</div>
|
| 143 |
+
</div>
|
| 144 |
+
</div>
|
| 145 |
+
{% endblock %}
|
| 146 |
+
|
| 147 |
+
{% block extra_js %}
|
| 148 |
+
<script src="{{ url_for('static', path='/js/dashboard.js') }}"></script>
|
| 149 |
+
{% endblock %}
|