You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS中利用Segmentation数据绘制图像分割掩码的实现方法求助

How to Draw Segmentation Masks from JSON Data on Canvas in ReactJS

Got it, let's tackle drawing segmentation masks with your existing React Canvas setup. First, let's break down your segmentation data: it's a list of polygon coordinates (each pair of numbers is an [x, y] point) that form a closed shape. We can use Canvas's 2D context to draw and fill this polygon as a semi-transparent mask (or outline it, if you prefer).

Here's the modified version of your code with segmentation mask support, plus explanations of key changes:

import React, { useRef, useEffect, useState } from 'react';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';

function App() {
  const [data, setData] = useState([]);
  const canvas = useRef();
  let ctx = null;

  // Initialize canvas context and set dimensions
  useEffect(() => {
    const canvasEle = canvas.current;
    // Match canvas dimensions to your image size (assuming 512x512 here)
    canvasEle.width = 512;
    canvasEle.height = 512;
    ctx = canvasEle.getContext("2d");
  }, []);

  // Draw bounding box (your existing function, kept for reference)
  const drawRect = (info, style = {}) => {
    const { x, y, w, h } = info;
    const { borderColor = 'black', borderWidth = 1 } = style;
    ctx.beginPath();
    ctx.strokeStyle = borderColor;
    ctx.lineWidth = borderWidth;
    ctx.rect(x, y, w, h);
    ctx.stroke();
  };

  // New function to draw segmentation mask
  const drawSegmentationMask = (segmentation, style = {}) => {
    const { fillColor = 'rgba(255, 0, 0, 0.3)', strokeColor = 'red', strokeWidth = 2 } = style;
    // Your segmentation data uses a single polygon per annotation
    const points = segmentation[0];
    
    if (!points || points.length < 2) return;

    ctx.beginPath();
    // Move to the first coordinate point
    ctx.moveTo(points[0], points[1]);
    // Loop through remaining points to draw the polygon
    for (let i = 2; i < points.length; i += 2) {
      ctx.lineTo(points[i], points[i + 1]);
    }
    // Close the path to complete the shape
    ctx.closePath();

    // Fill the mask with semi-transparent color (so image shows through)
    ctx.fillStyle = fillColor;
    ctx.fill();
    // Optional: Add an outline around the mask for clarity
    ctx.strokeStyle = strokeColor;
    ctx.lineWidth = strokeWidth;
    ctx.stroke();
  };

  const getData = () => {
    fetch('/test.json', {
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      }
    })
    .then(response => response.json())
    .then(myJson => {
      setData(myJson.annotations);
      // Clear canvas first to prevent overlapping drawings
      ctx.clearRect(0, 0, canvas.current.width, canvas.current.height);
      
      // Loop through all annotations to draw both bbox and mask
      myJson.annotations.forEach(anno => {
        // Draw bounding box from bbox data
        const [x, y, w, h] = anno.bbox;
        drawRect({ x, y, w, h }, { borderColor: 'blue', borderWidth: 2 });
        
        // Draw segmentation mask from polygon data
        drawSegmentationMask(anno.segmentation, { 
          fillColor: 'rgba(0, 255, 0, 0.3)', 
          strokeColor: 'green',
          strokeWidth: 2
        });
      });
    });
  };

  useEffect(() => {
    getData();
  }, []);

  return (
    <div className="App">
      <canvas 
        style={{
          height: "512px", 
          width: "512px",
          backgroundImage: `url("https://karthiknbucket1.s3.ap-southeast-1.amazonaws.com/00000001.png")`, 
          backgroundPosition: "center",
          backgroundSize: "100% 100%" 
        }}
        ref={canvas}
      ></canvas>
    </div>
  );
}

export default App;

Key Changes Explained:

  1. Fixed Canvas Dimensions: We explicitly set the canvas to match your image size (512x512) to ensure your JSON coordinates align perfectly with the canvas pixel space.

  2. drawSegmentationMask Function:

    • Parses the flat list of coordinates into [x,y] pairs to build a polygon path
    • Uses semi-transparent fill color so you can still see the underlying image
    • Adds an optional outline to make the mask boundaries clearer
  3. Updated getData Function:

    • Clears the canvas before drawing to avoid overlapping if you re-fetch data
    • Loops through all annotations instead of just one, drawing both the bounding box and segmentation mask for each object
  4. Style Customization: Adjust fillColor (use RGBA for transparency) and strokeColor values to match your desired visual style.

Quick Notes:

  • If your image ever scales differently than the canvas, you'll need to add a scaling factor to the coordinates (e.g., multiply each x/y by canvas.width / originalImageWidth). For your current setup though, this isn't needed since the background is set to 100% 100%.
  • This code handles iscrowd: 0 annotations (polygon format). If you ever have iscrowd: 1 entries, they use RLE (run-length encoding) which requires a different parsing approach.

内容的提问来源于stack exchange,提问作者Karthikeyan M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 23:27:44