| {% extends "base.html" %} |
|
|
| {% block title %}Dashboard - Seamo Species API{% endblock %} |
|
|
| {% block extra_css %} |
| <link rel="stylesheet" href="/static/css/dashboard.css"> |
| <link rel="stylesheet" href="/static/css/dashboard-simple.css"> |
| {% endblock %} |
|
|
| {% block content %} |
| <div class="dashboard"> |
|
|
|
|
| |
| <div class="status-banner" id="statusBanner"> |
| <div class="status-indicator"> |
| <span class="status-dot" id="statusDot"></span> |
| <span class="status-text" id="statusText">Checking API status...</span> |
| </div> |
| <div class="model-info" id="modelInfo"></div> |
| </div> |
|
|
| |
| <div class="dashboard-grid"> |
| |
| <div class="panel model-panel"> |
| <div class="card"> |
| <div class="card-header"> |
| <h3 class="card-title">Model Information</h3> |
| </div> |
| <div class="card-body"> |
| |
| <div class="settings-section"> |
| <h4>Detection Settings</h4> |
| <div class="settings-grid"> |
| <div class="setting-item"> |
| <label for="confidenceSlider">Confidence Threshold</label> |
| <div class="slider-container"> |
| <input type="range" id="confidenceSlider" min="0" max="100" value="25"> |
| <span class="slider-value" id="confidenceValue">25%</span> |
| </div> |
| </div> |
| <div class="setting-item"> |
| <label for="iouSlider">IoU Threshold</label> |
| <div class="slider-container"> |
| <input type="range" id="iouSlider" min="0" max="100" value="45"> |
| <span class="slider-value" id="iouValue">45%</span> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="model-details-section"> |
| <h4>Model Details</h4> |
| <div class="model-details-grid"> |
| <div class="detail-item"> |
| <span class="detail-label">Model Type</span> |
| <span class="detail-value" id="modelType">YOLOv5</span> |
| </div> |
| <div class="detail-item"> |
| <span class="detail-label">Total Species</span> |
| <span class="detail-value" id="totalSpecies">-</span> |
| </div> |
| <div class="detail-item"> |
| <span class="detail-label">Device</span> |
| <span class="detail-value" id="deviceInfo">-</span> |
| </div> |
| <div class="detail-item"> |
| <span class="detail-label">Model Size</span> |
| <span class="detail-value" id="modelSize">33k Images</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="panel upload-panel"> |
| <div class="card"> |
| <div class="card-header"> |
| <h3 class="card-title">Upload & Test</h3> |
| </div> |
| <div class="card-body"> |
| |
| <div class="upload-area" id="uploadArea"> |
| <div class="upload-content"> |
| <div class="upload-icon">+</div> |
| <div class="upload-text"> |
| <p class="upload-primary">Drag image here or click to browse</p> |
| <p class="upload-secondary">PNG, JPG, JPEG up to 10MB</p> |
| </div> |
| </div> |
| <input type="file" id="fileInput" accept="image/*" hidden> |
| </div> |
|
|
| |
| <button class="btn btn-primary btn-full" id="identifyBtn" disabled> |
| Identify Species |
| </button> |
|
|
| |
| <div class="sample-images-section"> |
| <div class="sample-images-header"> |
| <h4>Try Sample Images</h4> |
| <div class="slider-controls"> |
| <button class="slider-btn slider-btn-prev" id="sliderPrev" aria-label="Previous images">‹</button> |
| <button class="slider-btn slider-btn-next" id="sliderNext" aria-label="Next images">›</button> |
| </div> |
| </div> |
| <div class="sample-images-slider" id="sampleImagesSlider"> |
| |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="panel results-panel"> |
| <div class="card"> |
| <div class="card-header"> |
| <h3 class="card-title">Detection Results</h3> |
| </div> |
| <div class="card-body"> |
| |
| <div class="annotated-section"> |
| <h4>Annotated Image</h4> |
| <div class="image-container" id="annotatedImageContainer"> |
| <div class="image-placeholder"> |
| <div class="placeholder-icon">□</div> |
| <p>Annotated results will appear here</p> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="metadata-section" id="metadataSection" style="display: none;"> |
| <h4>Detection Summary</h4> |
| <div class="metadata-grid"> |
| <div class="metadata-item"> |
| <span class="metadata-label">Processing Time</span> |
| <span class="metadata-value" id="processingTime">-</span> |
| </div> |
| <div class="metadata-item"> |
| <span class="metadata-label">Species Found</span> |
| <span class="metadata-value" id="speciesCount">-</span> |
| </div> |
| <div class="metadata-item"> |
| <span class="metadata-label">Image Size</span> |
| <span class="metadata-value" id="imageSize">-</span> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="species-section" id="speciesSection" style="display: none;"> |
| <h4>Detected Species</h4> |
| <div class="species-list" id="speciesList"> |
| |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="api-documentation-section"> |
| <div class="api-docs-header"> |
| <h2>API Documentation</h2> |
| </div> |
|
|
| <div class="api-overview"> |
| <div class="endpoint-card"> |
| <div class="endpoint-header"> |
| <span class="method-badge">POST</span> |
| <code class="endpoint-url">https://seamo-ai-fishapi.hf.space/api/v1/detect</code> |
| <span class="status-badge">Live</span> |
| </div> |
|
|
| <div class="features-grid"> |
| <div class="feature-item"> |
| <div class="feature-title">691 Species</div> |
| <div class="feature-description">Comprehensive marine life detection</div> |
| </div> |
| <div class="feature-item"> |
| <div class="feature-title">~2 seconds</div> |
| <div class="feature-description">Fast AI-powered processing</div> |
| </div> |
| <div class="feature-item"> |
| <div class="feature-title">Precise Locations</div> |
| <div class="feature-description">Bounding boxes with confidence scores</div> |
| </div> |
| <div class="feature-item"> |
| <div class="feature-title">Annotated Images</div> |
| <div class="feature-description">Visual results with species labels</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="tabs-container"> |
| <div class="tabs-nav"> |
| <button class="tab-button active" data-tab="curl">cURL</button> |
| <button class="tab-button" data-tab="python">Python</button> |
| <button class="tab-button" data-tab="javascript">JavaScript</button> |
| <button class="tab-button" data-tab="csharp">C#</button> |
| <button class="tab-button" data-tab="response">Response</button> |
| </div> |
|
|
| |
| <div class="tab-content active" id="curl-tab"> |
| <div class="code-section"> |
| <div class="code-header"> |
| <span class="code-title">cURL Request</span> |
| <button class="copy-button" onclick="copyCode('curl-code')">Copy</button> |
| </div> |
| <pre class="code-block" id="curl-code"><span class="comment"># Easy one-liner with automatic base64 conversion</span> |
| <span class="cmd">curl</span> <span class="flag">-X</span> <span class="method">POST</span> <span class="string">"https://seamo-ai-fishapi.hf.space/api/v1/detect"</span> <span class="operator">\</span> |
| <span class="flag">-H</span> <span class="string">"Content-Type: application/json"</span> <span class="operator">\</span> |
| <span class="flag">-d</span> <span class="string">"{ |
| \"image\": \"$(base64 -i your_image.jpg | tr -d '\n')\", |
| \"confidence_threshold\": 0.25, |
| \"iou_threshold\": 0.45, |
| \"return_annotated_image\": true |
| }"</span></pre> |
| </div> |
| </div> |
|
|
| |
| <div class="tab-content" id="python-tab"> |
| <div class="code-section"> |
| <div class="code-header"> |
| <span class="code-title">Python Request</span> |
| <button class="copy-button" onclick="copyCode('python-code')">Copy</button> |
| </div> |
| <pre class="code-block" id="python-code"><span class="keyword">import</span> <span class="module">requests</span> |
| <span class="keyword">import</span> <span class="module">base64</span> |
|
|
| <span class="variable">url</span> <span class="operator">=</span> <span class="string">"https://seamo-ai-fishapi.hf.space/api/v1/detect"</span> |
|
|
| <span class="comment"># Read and encode image</span> |
| <span class="keyword">with</span> <span class="function">open</span>(<span class="string">"your_image.jpg"</span>, <span class="string">"rb"</span>) <span class="keyword">as</span> <span class="variable">f</span>: |
| <span class="variable">image_data</span> <span class="operator">=</span> <span class="variable">base64</span>.<span class="function">b64encode</span>(<span class="variable">f</span>.<span class="function">read</span>()).<span class="function">decode</span>() |
|
|
| <span class="variable">payload</span> <span class="operator">=</span> { |
| <span class="string">"image"</span>: <span class="variable">image_data</span>, |
| <span class="string">"confidence_threshold"</span>: <span class="number">0.25</span>, |
| <span class="string">"iou_threshold"</span>: <span class="number">0.45</span>, |
| <span class="string">"return_annotated_image"</span>: <span class="keyword">True</span> |
| } |
|
|
| <span class="variable">response</span> <span class="operator">=</span> <span class="variable">requests</span>.<span class="function">post</span>(<span class="variable">url</span>, <span class="variable">json</span>=<span class="variable">payload</span>) |
| <span class="variable">result</span> <span class="operator">=</span> <span class="variable">response</span>.<span class="function">json</span>() |
|
|
| <span class="function">print</span>(<span class="string">f"Found </span>{<span class="function">len</span>(<span class="variable">result</span>[<span class="string">'detections'</span>])}<span class="string"> species"</span>) |
| <span class="keyword">for</span> <span class="variable">detection</span> <span class="keyword">in</span> <span class="variable">result</span>[<span class="string">'detections'</span>]: |
| <span class="function">print</span>(<span class="string">f"- </span>{<span class="variable">detection</span>[<span class="string">'class_name'</span>]}<span class="string">: </span>{<span class="variable">detection</span>[<span class="string">'confidence'</span>]:<span class="string">.2%</span>}<span class="string">"</span>)</pre> |
| </div> |
| </div> |
|
|
| |
| <div class="tab-content" id="javascript-tab"> |
| <div class="code-section"> |
| <div class="code-header"> |
| <span class="code-title">JavaScript Request</span> |
| <button class="copy-button" onclick="copyCode('js-code')">Copy</button> |
| </div> |
| <pre class="code-block" id="js-code"><span class="comment">// Convert file to base64</span> |
| <span class="keyword">function</span> <span class="function">fileToBase64</span>(<span class="variable">file</span>) { |
| <span class="keyword">return</span> <span class="keyword">new</span> <span class="function">Promise</span>((<span class="variable">resolve</span>, <span class="variable">reject</span>) <span class="operator">=></span> { |
| <span class="keyword">const</span> <span class="variable">reader</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="function">FileReader</span>(); |
| <span class="variable">reader</span>.<span class="property">onload</span> <span class="operator">=</span> () <span class="operator">=></span> <span class="function">resolve</span>(<span class="variable">reader</span>.<span class="property">result</span>.<span class="function">split</span>(<span class="string">','</span>)[<span class="number">1</span>]); |
| <span class="variable">reader</span>.<span class="property">onerror</span> <span class="operator">=</span> <span class="variable">reject</span>; |
| <span class="variable">reader</span>.<span class="function">readAsDataURL</span>(<span class="variable">file</span>); |
| }); |
| } |
|
|
| <span class="keyword">const</span> <span class="variable">imageBase64</span> <span class="operator">=</span> <span class="keyword">await</span> <span class="function">fileToBase64</span>(<span class="variable">fileInput</span>.<span class="property">files</span>[<span class="number">0</span>]); |
|
|
| <span class="keyword">const</span> <span class="variable">payload</span> <span class="operator">=</span> { |
| <span class="property">image</span>: <span class="variable">imageBase64</span>, |
| <span class="property">confidence_threshold</span>: <span class="number">0.25</span>, |
| <span class="property">iou_threshold</span>: <span class="number">0.45</span>, |
| <span class="property">return_annotated_image</span>: <span class="keyword">true</span> |
| }; |
|
|
| <span class="function">fetch</span>(<span class="string">'https://seamo-ai-fishapi.hf.space/api/v1/detect'</span>, { |
| <span class="property">method</span>: <span class="string">'POST'</span>, |
| <span class="property">headers</span>: { <span class="string">'Content-Type'</span>: <span class="string">'application/json'</span> }, |
| <span class="property">body</span>: <span class="function">JSON</span>.<span class="function">stringify</span>(<span class="variable">payload</span>) |
| }) |
| .<span class="function">then</span>(<span class="variable">response</span> <span class="operator">=></span> <span class="variable">response</span>.<span class="function">json</span>()) |
| .<span class="function">then</span>(<span class="variable">data</span> <span class="operator">=></span> { |
| <span class="variable">console</span>.<span class="function">log</span>(<span class="string">`Found </span>${<span class="variable">data</span>.<span class="property">detections</span>.<span class="property">length</span>}<span class="string"> species`</span>); |
| <span class="variable">data</span>.<span class="property">detections</span>.<span class="function">forEach</span>(<span class="variable">detection</span> <span class="operator">=></span> { |
| <span class="variable">console</span>.<span class="function">log</span>(<span class="string">`</span>${<span class="variable">detection</span>.<span class="property">class_name</span>}<span class="string">: </span>${(<span class="variable">detection</span>.<span class="property">confidence</span> <span class="operator">*</span> <span class="number">100</span>).<span class="function">toFixed</span>(<span class="number">1</span>)}<span class="string">%`</span>); |
| }); |
| }) |
| .<span class="function">catch</span>(<span class="variable">error</span> <span class="operator">=></span> <span class="variable">console</span>.<span class="function">error</span>(<span class="string">'Error:'</span>, <span class="variable">error</span>));</pre> |
| </div> |
| </div> |
|
|
| |
| <div class="tab-content" id="csharp-tab"> |
| <div class="code-section"> |
| <div class="code-header"> |
| <span class="code-title">C# Request</span> |
| <button class="copy-button" onclick="copyCode('csharp-code')">Copy</button> |
| </div> |
| <pre class="code-block" id="csharp-code"><span class="keyword">using</span> <span class="namespace">System</span>; |
| <span class="keyword">using</span> <span class="namespace">System.IO</span>; |
| <span class="keyword">using</span> <span class="namespace">System.Net.Http</span>; |
| <span class="keyword">using</span> <span class="namespace">System.Text</span>; |
| <span class="keyword">using</span> <span class="namespace">System.Threading.Tasks</span>; |
| <span class="keyword">using</span> <span class="namespace">Newtonsoft.Json</span>; |
|
|
| <span class="keyword">var</span> <span class="variable">client</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="function">HttpClient</span>(); |
|
|
| <span class="comment">// Read and encode image</span> |
| <span class="keyword">var</span> <span class="variable">imageBytes</span> <span class="operator">=</span> <span class="class">File</span>.<span class="function">ReadAllBytes</span>(<span class="string">"your_image.jpg"</span>); |
| <span class="keyword">var</span> <span class="variable">imageBase64</span> <span class="operator">=</span> <span class="class">Convert</span>.<span class="function">ToBase64String</span>(<span class="variable">imageBytes</span>); |
|
|
| <span class="keyword">var</span> <span class="variable">payload</span> <span class="operator">=</span> <span class="keyword">new</span> { |
| <span class="property">image</span> = <span class="variable">imageBase64</span>, |
| <span class="property">confidence_threshold</span> = <span class="number">0.25</span>, |
| <span class="property">iou_threshold</span> = <span class="number">0.45</span>, |
| <span class="property">return_annotated_image</span> = <span class="keyword">true</span> |
| }; |
|
|
| <span class="keyword">var</span> <span class="variable">json</span> <span class="operator">=</span> <span class="class">JsonConvert</span>.<span class="function">SerializeObject</span>(<span class="variable">payload</span>); |
| <span class="keyword">var</span> <span class="variable">content</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="function">StringContent</span>(<span class="variable">json</span>, <span class="class">Encoding</span>.<span class="property">UTF8</span>, <span class="string">"application/json"</span>); |
|
|
| <span class="keyword">var</span> <span class="variable">response</span> <span class="operator">=</span> <span class="keyword">await</span> <span class="variable">client</span>.<span class="function">PostAsync</span>( |
| <span class="string">"https://seamo-ai-fishapi.hf.space/api/v1/detect"</span>, |
| <span class="variable">content</span> |
| ); |
|
|
| <span class="keyword">var</span> <span class="variable">result</span> <span class="operator">=</span> <span class="keyword">await</span> <span class="variable">response</span>.<span class="property">Content</span>.<span class="function">ReadAsStringAsync</span>(); |
| <span class="class">Console</span>.<span class="function">WriteLine</span>(<span class="variable">result</span>);</pre> |
| </div> |
| </div> |
|
|
| |
| <div class="tab-content" id="response-tab"> |
| <div class="response-demo"> |
| <div class="response-title">Example API Response</div> |
| <div class="response-description"> |
| Actual response from testing with a marine image - detected <strong>8 marine species</strong> in 1.79 seconds: |
| </div> |
|
|
| <div class="detection-summary"> |
| <div class="detection-item"> |
| <span class="species-name">Sebastolobus (Rockfish)</span> |
| <span class="confidence-badge confidence-high">86.7%</span> |
| </div> |
| <div class="detection-item"> |
| <span class="species-name">Octocorallia (Soft Coral)</span> |
| <span class="confidence-badge confidence-medium">69.7%</span> |
| </div> |
| <div class="detection-item"> |
| <span class="species-name">Psolus squamatus (Sea Cucumber)</span> |
| <span class="confidence-badge confidence-medium">66.3%</span> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="code-section"> |
| <div class="code-header"> |
| <span class="code-title">JSON Response</span> |
| <button class="copy-button" onclick="copyCode('response-code')">Copy</button> |
| </div> |
| <pre class="code-block" id="response-code">{ |
| <span class="json-key">"detections"</span>: [ |
| { |
| <span class="json-key">"class_id"</span>: <span class="json-number">3</span>, |
| <span class="json-key">"class_name"</span>: <span class="json-string">"Sebastolobus"</span>, |
| <span class="json-key">"confidence"</span>: <span class="json-number">0.8674</span>, |
| <span class="json-key">"bbox"</span>: { |
| <span class="json-key">"x"</span>: <span class="json-number">179.4</span>, <span class="json-key">"y"</span>: <span class="json-number">282.2</span>, |
| <span class="json-key">"width"</span>: <span class="json-number">129.7</span>, <span class="json-key">"height"</span>: <span class="json-number">71.0</span> |
| } |
| }, |
| { |
| <span class="json-key">"class_id"</span>: <span class="json-number">16</span>, |
| <span class="json-key">"class_name"</span>: <span class="json-string">"Octocorallia"</span>, |
| <span class="json-key">"confidence"</span>: <span class="json-number">0.6969</span>, |
| <span class="json-key">"bbox"</span>: { <span class="comment">/* coordinates */</span> } |
| } |
| <span class="comment">// ... 6 more detections</span> |
| ], |
| <span class="json-key">"annotated_image"</span>: <span class="json-string">"base64_encoded_image_with_boxes"</span>, |
| <span class="json-key">"processing_time"</span>: <span class="json-number">1.79</span>, |
| <span class="json-key">"model_info"</span>: { |
| <span class="json-key">"model_name"</span>: <span class="json-string">"marina-benthic-33k"</span>, |
| <span class="json-key">"total_classes"</span>: <span class="json-number">691</span>, |
| <span class="json-key">"device"</span>: <span class="json-string">"cpu"</span> |
| }, |
| <span class="json-key">"image_dimensions"</span>: { |
| <span class="json-key">"width"</span>: <span class="json-number">714</span>, <span class="json-key">"height"</span>: <span class="json-number">486</span> |
| } |
| }</pre> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="docs-footer"> |
| <div class="info-grid"> |
| <div class="info-card"> |
| <h4>Request Parameters</h4> |
| <ul class="info-list"> |
| <li><strong>image</strong> (required): Base64 encoded image data</li> |
| <li><strong>confidence_threshold</strong>: Minimum confidence (0.0-1.0, default: 0.25)</li> |
| <li><strong>iou_threshold</strong>: IoU threshold (0.0-1.0, default: 0.45)</li> |
| <li><strong>return_annotated_image</strong>: Return annotated image (boolean, default: true)</li> |
| </ul> |
| </div> |
| <div class="info-card"> |
| <h4>Response Format</h4> |
| <ul class="info-list"> |
| <li><strong>detections</strong>: Array of detected species with bounding boxes</li> |
| <li><strong>processing_time</strong>: Time taken for inference in seconds</li> |
| <li><strong>model_info</strong>: Information about the AI model used</li> |
| <li><strong>image_dimensions</strong>: Original image width and height</li> |
| </ul> |
| </div> |
| <div class="info-card"> |
| <h4>Model Information</h4> |
| <ul class="info-list"> |
| <li><strong>Model</strong>: marina-benthic-33k</li> |
| <li><strong>Species</strong>: 691 marine species supported</li> |
| <li><strong>Performance</strong>: ~2 seconds average processing</li> |
| <li><strong>Accuracy</strong>: High precision bounding boxes</li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| {% endblock %} |
|
|
| {% block extra_js %} |
| <script src="/static/js/dashboard.js"></script> |
| {% endblock %} |
|
|