Skip to content

Commit

Permalink
FIX : DeepSlice
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldresser-ie committed Dec 15, 2023
1 parent 679d173 commit bdc2b9a
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 185 deletions.
5 changes: 5 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
1.x.x.x (relative to 1.3.x.x)
=======

Features
--------

- GafferImage : Added DeepSlice node for clipping out part of an image based on depth.

Improvements
------------

Expand Down
16 changes: 5 additions & 11 deletions include/GafferImage/DeepSlice.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

#include "GafferImage/ImageProcessor.h"

#include "Gaffer/CompoundNumericPlug.h"
#include "Gaffer/OptionalValuePlug.h"
#include "Gaffer/NumericPlug.h"

namespace Gaffer
Expand All @@ -65,17 +65,11 @@ class GAFFERIMAGE_API DeepSlice : public ImageProcessor

GAFFER_NODE_DECLARE_TYPE( GafferImage::DeepSlice, DeepSliceTypeId, ImageProcessor );

Gaffer::BoolPlug *nearClipPlug();
const Gaffer::BoolPlug *nearClipPlug() const;
Gaffer::OptionalValuePlug *nearClipPlug();
const Gaffer::OptionalValuePlug *nearClipPlug() const;

Gaffer::FloatPlug *nearClipDepthPlug();
const Gaffer::FloatPlug *nearClipDepthPlug() const;

Gaffer::BoolPlug *farClipPlug();
const Gaffer::BoolPlug *farClipPlug() const;

Gaffer::FloatPlug *farClipDepthPlug();
const Gaffer::FloatPlug *farClipDepthPlug() const;
Gaffer::OptionalValuePlug *farClipPlug();
const Gaffer::OptionalValuePlug *farClipPlug() const;

Gaffer::BoolPlug *flattenPlug();
const Gaffer::BoolPlug *flattenPlug() const;
Expand Down
67 changes: 32 additions & 35 deletions python/GafferImageTest/DeepSliceTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,14 @@ def testBasics( self ) :
# We could compute expectedWeights based some simple computations, but I think it makes it more
# obivous what we're testing to hardcode the expectedWeights for each test.
def sliceTest( nearClip, nearClipDepth, farClip, farClipDepth, expectedWeights ):
deepSlice["nearClip"].setValue( nearClip )
deepSlice["nearClipDepth"].setValue( nearClipDepth )
deepSlice["farClip"].setValue( farClip )
deepSlice["farClipDepth"].setValue( farClipDepth )
deepSliceFlatten["nearClip"].setValue( nearClip )
deepSliceFlatten["nearClipDepth"].setValue( nearClipDepth )
deepSliceFlatten["farClip"].setValue( farClip )
deepSliceFlatten["farClipDepth"].setValue( farClipDepth )
deepSlice["nearClip"]["enabled"].setValue( nearClip )
deepSlice["nearClip"]["value"].setValue( nearClipDepth )
deepSlice["farClip"]["enabled"].setValue( farClip )
deepSlice["farClip"]["value"].setValue( farClipDepth )
deepSliceFlatten["nearClip"]["enabled"].setValue( nearClip )
deepSliceFlatten["nearClip"]["value"].setValue( nearClipDepth )
deepSliceFlatten["farClip"]["enabled"].setValue( farClip )
deepSliceFlatten["farClip"]["value"].setValue( farClipDepth )

self.assertImagesEqual( deepSliceFlatten["out"], flatten["out"], maxDifference = 1e-7 )

Expand Down Expand Up @@ -270,8 +270,8 @@ def testBruteForce( self ) :

sliceNear = GafferImage.DeepSlice()
sliceNear["in"].setInput( testImage )
sliceNear["nearClip"].setValue( False )
sliceNear["farClip"].setValue( True )
sliceNear["nearClip"]["enabled"].setValue( False )
sliceNear["farClip"]["enabled"].setValue( True )
sliceNear["flatten"].setValue( False )

flattenedNear = GafferImage.DeepToFlat()
Expand All @@ -280,15 +280,15 @@ def testBruteForce( self ) :

flatSliceNear = GafferImage.DeepSlice()
flatSliceNear["in"].setInput( testImage )
flatSliceNear["nearClip"].setValue( False )
flatSliceNear["farClip"].setValue( True )
flatSliceNear["farClipDepth"].setInput( sliceNear["farClipDepth"] )
flatSliceNear["nearClip"]["enabled"].setValue( False )
flatSliceNear["farClip"]["enabled"].setValue( True )
flatSliceNear["farClip"]["value"].setInput( sliceNear["farClip"]["value"] )
flatSliceNear["flatten"].setValue( True )

sliceFar = GafferImage.DeepSlice()
sliceFar["in"].setInput( testImage )
sliceFar["nearClip"].setValue( True )
sliceFar["farClip"].setValue( False )
sliceFar["nearClip"]["enabled"].setValue( True )
sliceFar["farClip"]["enabled"].setValue( False )
sliceFar["flatten"].setValue( False )

flattenedFar = GafferImage.DeepToFlat()
Expand All @@ -297,15 +297,15 @@ def testBruteForce( self ) :

flatSliceFar = GafferImage.DeepSlice()
flatSliceFar["in"].setInput( testImage )
flatSliceFar["nearClip"].setValue( True )
flatSliceFar["nearClipDepth"].setInput( sliceFar["nearClipDepth"] )
flatSliceFar["farClip"].setValue( False )
flatSliceFar["nearClip"]["enabled"].setValue( True )
flatSliceFar["nearClip"]["value"].setInput( sliceFar["nearClip"]["value"] )
flatSliceFar["farClip"]["enabled"].setValue( False )
flatSliceFar["flatten"].setValue( True )

sliceMiddle = GafferImage.DeepSlice()
sliceMiddle["in"].setInput( testImage )
sliceMiddle["nearClip"].setValue( True )
sliceMiddle["farClip"].setValue( True )
sliceMiddle["nearClip"]["enabled"].setValue( True )
sliceMiddle["farClip"]["enabled"].setValue( True )
sliceMiddle["flatten"].setValue( False )

flattenedMiddle = GafferImage.DeepToFlat()
Expand All @@ -314,10 +314,10 @@ def testBruteForce( self ) :

flatSliceMiddle = GafferImage.DeepSlice()
flatSliceMiddle["in"].setInput( testImage )
flatSliceMiddle["nearClip"].setValue( True )
flatSliceMiddle["nearClipDepth"].setInput( sliceMiddle["nearClipDepth"] )
flatSliceMiddle["farClip"].setValue( True )
flatSliceMiddle["farClipDepth"].setInput( sliceMiddle["farClipDepth"] )
flatSliceMiddle["nearClip"]["enabled"].setValue( True )
flatSliceMiddle["nearClip"]["value"].setInput( sliceMiddle["nearClip"]["value"] )
flatSliceMiddle["farClip"]["enabled"].setValue( True )
flatSliceMiddle["farClip"]["value"].setInput( sliceMiddle["farClip"]["value"] )
flatSliceMiddle["flatten"].setValue( True )

flattenedInput = GafferImage.DeepToFlat()
Expand Down Expand Up @@ -413,8 +413,8 @@ def testBruteForce( self ) :
[ random.uniform( zStart, zEnd ) for i in range( 20 ) ]
):
with self.subTest( mode = "Near/Far", name = image.node().getName(), depth = depth ) :
sliceNear["farClipDepth"].setValue( depth )
sliceFar["nearClipDepth"].setValue( depth )
sliceNear["farClip"]["value"].setValue( depth )
sliceFar["nearClip"]["value"].setValue( depth )

# The output from DeepSlice should always be tidy, which we can validate by making
# sure tidying has no effect
Expand Down Expand Up @@ -458,19 +458,18 @@ def testBruteForce( self ) :
# the original sample counts, and no more than 1 greater ( since if a sample is split by
# the depth, it will appear in both )
self.assertImagesEqual(
sampleCountsNearFar["out"], sampleCountsInput["out"],
maxDifferenceGreater = 1, maxDifferenceLess = 0
sampleCountsInput["out"], sampleCountsNearFar["out"], maxDifference = (0,1)
)

# Run a few more tests when we're taking a middle slice by clipping both near and far
for a, b in ( ( random.uniform( zStart, zEnd ), random.uniform( zStart, zEnd ) ) for i in range( 20 ) ):
with self.subTest( mode = "Middle", name = image.node().getName(), depth = depth ) :
nearDepth = min( a, b )
farDepth = max( a, b )
sliceNear["farClipDepth"].setValue( nearDepth )
sliceMiddle["nearClipDepth"].setValue( nearDepth )
sliceMiddle["farClipDepth"].setValue( farDepth )
sliceFar["nearClipDepth"].setValue( farDepth )
sliceNear["farClip"]["value"].setValue( nearDepth )
sliceMiddle["nearClip"]["value"].setValue( nearDepth )
sliceMiddle["farClip"]["value"].setValue( farDepth )
sliceFar["nearClip"]["value"].setValue( farDepth )

# Check that the flat output from DeepSlice matches with what we get by flattening
# the deep output
Expand All @@ -488,10 +487,8 @@ def testBruteForce( self ) :
# the original sample counts, and no more than 2 greater ( since both clipping depths
# could split a sample )
self.assertImagesEqual(
sampleCountsNearMiddleFar["out"], sampleCountsInput["out"],
maxDifferenceGreater = 2, maxDifferenceLess = 0
sampleCountsInput["out"], sampleCountsNearMiddleFar["out"], maxDifference = (0,2)
)

if __name__ == "__main__":
unittest.main()

43 changes: 11 additions & 32 deletions python/GafferImageUI/DeepSliceUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,60 +43,39 @@

"description",
"""
Takes a slice out of a deep image by discarding everything outside of a clipping range.
Optionally also flattens the image. The range is half open, including point samples exactly
at the near clip, but excluding point samples exactly at the far clip. This means that if you split
an image into a front and back with two DeepSlices, they will composite back together to match the
original.
Takes a slice out of an image with depth defined by Z ( and optionally ZBack ) channels by
discarding everything outside of a clipping range. The range is half open, including point samples
exactly at the near clip, but excluding point samples exactly at the far clip. This means that if
you split an image into a front and back with two DeepSlices, they will composite back together to
match the original. Optionally also flattens the image.
""",

"layout:activator:nearClip", lambda node : node["nearClip"].getValue(),
"layout:activator:farClip", lambda node : node["farClip"].getValue(),

plugs = {

"nearClip" : [

"description",
"""
Remove everything with Z less than the near clip depth.
""",

],
"nearClipDepth" : [

"description",
"""
The depth for the near clip.
Removes everything with Z less than the near clip depth.
""",
"label", "",
"layout:accessory", True,
"layout:activator", "nearClip",

],
"farClip" : [

"description",
"""
Remove everything with Z greater than or equal to the far clip depth.
Removes everything with Z greater than or equal to the far clip depth.
""",

],
"farClipDepth" : [

"description",
"""
The depth for the far clip.
""",
"label", "",
"layout:accessory", True,
"layout:activator", "farClip",
],
"flatten" : [

"description",
"""
Output a flat image, instead of output a deep image with any samples within the range.
Outputs a flat image, instead of output a deep image with any samples within the range.
Flattening as part of DeepSlice is up to 2X faster than flattening afterwards, and is
convenient if you're using a DeepSlice to preview the contents of a deep image by
scrubbing through depth.
""",

],
Expand Down
Loading

0 comments on commit bdc2b9a

Please sign in to comment.