4
$\begingroup$

Let's say I have some composite 3D graphics of various shapes. For simplicity, let's say these are just two capsules, like below:

myShapes = {CapsuleShape[{{-0.002997, 0., 0.}, {0.002997, 0., 0.}}, 2.997], 
 CapsuleShape[{{5.22693, 0.954974, 0.945536}, {5.23274, 0.956034, 
    0.946586}}, 2.997]}

Graphics3D[myShapes, ViewPoint -> Front, 
 ViewProjection -> "Orthographic"]

enter image description here

Now, from that orthographic projection, I'd like to get a binary image of the "foreground" pixels visible from the projection, so that I can get 2D ComponentMeasurements[] (like area, circularity, etc.)

We can use Jen's function from this answer to get a black "shadow", which seems promising, but such shadow is still a Graphics3D[] object, so it does not seem very useful (but it's cool!):

enter image description here

How could I go about this?

Thanks!

Note: Ideally, the projection should respect the dimensions of the original graphics (say, the diameter/shape of the capsules), but I'm assuming the orthographic projection would take care of that(?)

$\endgroup$

1 Answer 1

8
$\begingroup$

Edit

If we only need image,we can use

Clear[plot, img]; 
myShapes = {CapsuleShape[{{-0.002997, 0., 
     0.}, {0.002997, 0., 0.}}, 2.997], 
  CapsuleShape[{{5.22693, 0.954974, 0.945536}, {5.23274, 0.956034, 
     0.946586}}, 2.997]}; 
plot = 
 Graphics3D[{Black, myShapes}, ViewProjection -> "Orthographic", 
  ViewPoint -> {0, -1, 0}, Boxed -> False, PlotRangePadding -> 0, 
  PlotRange -> Full];
 img = ImportString[ExportString[plot, "PNG"]]

Rasterize[plot]

enter image description here

Original

  • CapsuleShape is the BSplineSurface. It it not easy to handle.
Needs["OpenCascadeLink`"];
Needs["NDSolve`FEM`"];
myShapes = {CapsuleShape[{{-0.002997, 0., 0.}, {0.002997, 0., 0.}}, 
    2.997], CapsuleShape[{{5.22693, 0.954974, 0.945536}, {5.23274, 
      0.956034, 0.946586}}, 2.997]};
union = RegionUnion @@ myShapes;
shape = OpenCascadeShape[union];
mesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape, 
   "ShapeSurfaceMeshOptions" -> {"AngularDeflection" -> 0.05}];
mg = TransformedRegion[MeshRegion[mesh], 
   ScalingTransform[0, {0, 1, 0}]] // Quiet
mg // Area
dist = RegionDistance[mg];
projection = 
 ImplicitRegion[dist@{x, 0, z} <= .02, {x, z}] // DiscretizeRegion
projection // Area

55.6183

enter image description here

  • Compare with the 3D graphics.
myShapes = {CapsuleShape[{{-0.002997, 0., 0.}, {0.002997, 0., 0.}}, 
    2.997], CapsuleShape[{{5.22693, 0.954974, 0.945536}, {5.23274, 
      0.956034, 0.946586}}, 2.997]};
g = Graphics3D[
  GeometricTransformation[myShapes, ScalingTransform[0, {0, 1, 0}]], 
  ViewPoint -> Front, ViewProjection -> "Orthographic"]

Rasterize[g]

enter image description here

$\endgroup$
6
  • $\begingroup$ Wow, that's pretty cool. I wonder if there's a simple way to convert the "flat" 3D shapes into a binary image. In my case, I'd be using other shapes in addition to capsules (often combined in the same graphics object). But this approach is a great start, thanks! $\endgroup$ Commented Jul 17, 2022 at 3:04
  • 1
    $\begingroup$ @TumbiSapichu image is relatively easy. For example Clear[plot, img]; myShapes = {CapsuleShape[{{-0.002997, 0., 0.}, {0.002997, 0., 0.}}, 2.997], CapsuleShape[{{5.22693, 0.954974, 0.945536}, {5.23274, 0.956034, 0.946586}}, 2.997]}; plot = Graphics3D[{Black, myShapes}, ViewProjection -> "Orthographic", ViewPoint -> {0, 1, 0}, Boxed -> False, PlotRangePadding -> 1.2, PlotRange -> Full]; img = ImportString[ExportString[plot, "PNG"]] $\endgroup$
    – cvgmt
    Commented Jul 17, 2022 at 3:10
  • $\begingroup$ Oh, cool, that's exactly what I was trying to get at. If you write it as a response I'll accept it. $\endgroup$ Commented Jul 17, 2022 at 3:17
  • 1
    $\begingroup$ @TumbiSapichu updated. $\endgroup$
    – cvgmt
    Commented Jul 17, 2022 at 3:44
  • $\begingroup$ ImportString[ExportString[plot, "PNG"]] could be replaced by Rasterize $\endgroup$
    – SHuisman
    Commented Jan 25 at 16:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.