Capture Semantic-Segmentation-Style Image in DotNet

Looking for some pointers / advice on how to capture a bitmap in DotNet (I’m using a C# component in Grasshopper right now) that displays a “semantic-segmentation” style image of a given viewport. I’m looking to create something like the images used in ML that segment a scene by object type, but using objects in the Rhino model. For now, we could imagine each object is assigned a random color, as is shown below (which was made by manually fiddling with the displaymode, but I need this to be done programmatically).

I’ve tried futzing around with creating a displaymode in C#, but certain essential methods that are available in the display options dialog in Rhino are missing from Rhinocommon. I also tried creating my own Rhino.Display.DisplayConduit, but can’t seem to disable the default lighting there either.

Any ideas / pointers / precedents come to mind?

@jeff - is this something you can help with?

Well. I got something working, but in the dumbest way I can think of. In summary, I manually exported an INI file containing the configuration of the displaymode I wanted, and then copied the contents of this file into my script. The script then: 1) saves a new INI file with these contents on the user’s temp directory 2) imports this INI file as a new temporary displaymode in Rhino 3) changes the current view to use this displaymode 4) capture the view 5) put everything back the way it was by restoring the previous displaymode to the view, deleting the temporary displaymode, deleting the INI file.

Script below for anyone who wants to do this dumb thing too.

 private void RunScript(bool doIt, string savePath, ref object A)
  {

    if (doIt){

      var view = RhinoDoc.ActiveDoc.Views.ActiveView;
      if (view == null) { return; }

      Guid userDisplayModeId = view.ActiveViewport.DisplayMode.Id;

      Guid displayModeId = new Guid();
      if (createTempDisplayMode(ref displayModeId)){
        try {
          Print(String.Format("Capturing view with temporary displaymode {0}", displayModeId.ToString()));
          view.ActiveViewport.DisplayMode = Rhino.Display.DisplayModeDescription.GetDisplayMode(displayModeId);
          Rhino.Display.DisplayModeDescription dispModeDescription = Rhino.Display.DisplayModeDescription.GetDisplayMode(displayModeId);
          Bitmap bitmap = view.CaptureToBitmap(new Size(512, 512), dispModeDescription);
          if (bitmap != null) { bitmap.Save(Path.Combine(savePath, displayModeId.ToString() + ".png"));  }

        } catch (Exception ex) {
          Print("A main function exception occurred: " + ex.Message);
        } finally {
          view.ActiveViewport.DisplayMode = Rhino.Display.DisplayModeDescription.GetDisplayMode(userDisplayModeId);
          Rhino.Display.DisplayModeDescription.DeleteDisplayMode(displayModeId);
        }
      }


    }



  }



  public bool createTempDisplayMode(ref Guid displayModeId){
    string filePathINI = "";
    string guidStr = ""; // we don't really need this, since we get the GUID from the import operation below
    createTempINIFile(ref filePathINI, ref guidStr);
    //Print(filePathINI);

    try {
      displayModeId = Rhino.Display.DisplayModeDescription.ImportFromFile(filePathINI);
      removeTempINIFile(filePathINI);
      return true;
    } catch (Exception ex){
      Print("createTempDisplayMode exception occurred: " + ex.Message);
      removeTempINIFile(filePathINI);
      return false;
    }
  }


  public bool createTempINIFile(ref string fPath, ref string guidStr)
  {

    Guid newGuid = Guid.NewGuid(); // Generate a new GUID
    string guidString = newGuid.ToString();
    string str = dispmodeIniString(guidString);

    string tempPath = Path.GetTempPath(); // Define the path for the .ini file in the temp directory
    string filePath = Path.Combine(tempPath, guidString + ".ini");

    File.WriteAllText(filePath, str); // Write the text into the file

    fPath = filePath; // Output the filepath and the GUID
    guidStr = guidString;
    return true;
  }


  public bool removeTempINIFile(string fPath)
  {
    try
    {
      if (File.Exists(fPath))
      {
        File.Delete(fPath);
        return true;
      }
      else { Print(String.Format("removeTempINIFile: file does not exist {0}", fPath)); }
    }
    catch (Exception ex) { Print("removeTempINIFile error: " + ex.Message); }
    return false;
  }


  public string dispmodeIniString(string guidString)
  {
    string ret = @"CONTENTS OF INI FILE";

    return ret.Replace("[[GUID]]", guidString);
  }







Hi @ksteinfeld,

a DisplayConduit is the best way to do it. In order to get rid of the shading in your conduit you might use DrawBrepShaded or DrawMeshShaded using a custom DisplayMaterial which has the same color for diffuse, specular, ambient and emission for each object or set of objects using identical colors. You’ll need to draw everything yourself in the conduits PreDrawObjects event.

To prevent that Rhino too draws anything in the regular (shaded) display pipeline you’ll need to subscribe to the conduits ObjectCulling event and make sure to cull all Rhino objects you already draw yourself in your own conduit.

_
c.

1 Like