def testDeep( self ) : representativeDeep = GafferImage.ImageReader() representativeDeep["fileName"].setValue( self.representativeDeepImagePath ) deepCrop = GafferImage.Crop() deepCrop["in"].setInput( representativeDeep["out"] ) postFlatten = GafferImage.DeepToFlat() postFlatten["in"].setInput( deepCrop["out"] ) preFlatten = GafferImage.DeepToFlat() preFlatten["in"].setInput( representativeDeep["out"] ) flatCrop = GafferImage.Crop() flatCrop["in"].setInput( preFlatten["out"] ) dataWindow = representativeDeep["out"].dataWindow() for affectDisplay in [ True, False ]: for area in [ imath.Box2i( imath.V2i( 0, 0 ), imath.V2i( 150, 100 ) ), imath.Box2i( imath.V2i( -10, -13 ), imath.V2i( 157, 103 ) ), imath.Box2i( imath.V2i( 10, 13 ), imath.V2i( 143, 77 ) ), imath.Box2i( imath.V2i( 37, 65 ), imath.V2i( 101, 67 ) ), imath.Box2i( imath.V2i( 0, 0 ), imath.V2i( 149, 99 ) ) ] : deepCrop["area"].setValue( area ) flatCrop["area"].setValue( area ) self.assertImagesEqual( postFlatten["out"], flatCrop["out"] )
def testDeepWithFlatMask(self): # Set up a mask maskReader = GafferImage.ImageReader() maskReader["fileName"].setValue(self.radialPath) maskText = GafferImage.Text() maskText["in"].setInput(maskReader["out"]) maskText["area"].setValue( imath.Box2i(imath.V2i(0, 0), imath.V2i(256, 256))) maskText["text"].setValue('Test\nTest\nTest\nTest') maskOffset = GafferImage.Offset() maskOffset["in"].setInput(maskText["out"]) representativeDeepImage = GafferImage.ImageReader() representativeDeepImage["fileName"].setValue( self.representativeDeepImagePath) deepGradeBlack = GafferImage.Grade() deepGradeBlack["in"].setInput(representativeDeepImage["out"]) deepGradeBlack["multiply"].setValue(imath.Color4f(0, 0, 0, 1)) deepMix = GafferImage.Mix() deepMix["in"]["in0"].setInput(representativeDeepImage["out"]) deepMix["in"]["in1"].setInput(deepGradeBlack["out"]) deepMix["mask"].setInput(maskOffset["out"]) deepMix["maskChannel"].setValue('R') postFlatten = GafferImage.DeepToFlat() postFlatten["in"].setInput(deepMix["out"]) preFlatten = GafferImage.DeepToFlat() preFlatten["in"].setInput(representativeDeepImage["out"]) flatGradeBlack = GafferImage.Grade() flatGradeBlack["in"].setInput(preFlatten["out"]) flatGradeBlack["multiply"].setValue(imath.Color4f(0, 0, 0, 1)) flatMix = GafferImage.Mix() flatMix["in"]["in0"].setInput(preFlatten["out"]) flatMix["in"]["in1"].setInput(flatGradeBlack["out"]) flatMix["mask"].setInput(maskOffset["out"]) flatMix["maskChannel"].setValue('R') for o in [ imath.V2i(0, 0), imath.V2i(-3, -8), imath.V2i(-7, -79), imath.V2i(12, 8) ]: maskOffset["offset"].setValue(o) self.assertImagesEqual(postFlatten["out"], flatMix["out"], maxDifference=0.000003)
def testBasics( self ): representativeImage = GafferImage.ImageReader() representativeImage["fileName"].setValue( self.representativeImagePath ) flatImage = GafferImage.ImageReader() flatImage["fileName"].setValue( self.flatImagePath ) rc = GafferImage.DeepRecolor() rc["in"].setInput( representativeImage["out"] ) rc["colorSource"].setInput( flatImage["out"] ) representativeSampleCounts = GafferImage.DeepSampleCounts() representativeSampleCounts["in"].setInput( representativeImage["out"] ) rcSampleCounts = GafferImage.DeepSampleCounts() rcSampleCounts["in"].setInput( rc["out"] ) # Make sure we keep all the deep samples self.assertImagesEqual( representativeSampleCounts["out"], rcSampleCounts["out"] ) rcFlat = GafferImage.DeepToFlat() rcFlat["in"].setInput( rc["out"] ) representativeFlat = GafferImage.DeepToFlat() representativeFlat["in"].setInput( representativeImage["out"] ) unpremult = GafferImage.Unpremultiply() unpremult["in"].setInput( flatImage["out"] ) flatCombine = GafferImage.CopyChannels() flatCombine["in"][0].setInput( representativeFlat["out"] ) flatCombine["in"][1].setInput( unpremult["out"] ) flatCombine["channels"].setValue( "[RGB]" ) premult = GafferImage.Premultiply() premult["in"].setInput( flatCombine["out"] ) # Make sure that the default recolor matches the flat value of premulting by the deep alpha self.assertImagesEqual( rcFlat["out"], premult["out"], maxDifference = 1e-6 ) compare = GafferImage.Merge() compare["in"][0].setInput( rcFlat["out"] ) compare["in"][1].setInput( premult["out"] ) compare["operation"].setValue( GafferImage.Merge.Operation.Difference ) compareStats = GafferImage.ImageStats() compareStats["in"].setInput( compare["out"] ) compareStats["area"].setValue( imath.Box2i( imath.V2i( 0, 0 ), imath.V2i( 150, 100 ) ) ) m = compareStats["max"].getValue() a = compareStats["average"].getValue() for i in range( 4 ): self.assertLessEqual( m[i], 1e-6 ) self.assertLessEqual( a[i], 1e-8 ) rc["useColorSourceAlpha"].setValue( True ) m = compareStats["max"].getValue() a = compareStats["average"].getValue() for i in range( 3 ): self.assertGreater( m[i], 0.4 ) self.assertGreater( a[i], 0.0001 ) # Make sure that using useColorSourceAlpha basically matches the original color source after # flattening. ( It's not exact because of a few pixels with zero samples in the deep which # we can't do anything with ) compare["in"][1].setInput( flatImage["out"] ) m = compareStats["max"].getValue() a = compareStats["average"].getValue() for i in range( 4 ): self.assertLessEqual( m[i], 0.5 ) self.assertLessEqual( a[i], 0.0003 )
def testDeep(self): # Simple network to swap channels inLayer = GafferOSL.OSLShader() inLayer.loadShader("ImageProcessing/InLayer") colorToFloat = GafferOSL.OSLShader() colorToFloat.loadShader("Conversion/ColorToFloat") colorToFloat["parameters"]["c"].setInput(inLayer["out"]["layerColor"]) floatToColor = GafferOSL.OSLShader() floatToColor.loadShader("Conversion/FloatToColor") floatToColor["parameters"]["r"].setInput(colorToFloat["out"]["b"]) floatToColor["parameters"]["g"].setInput(colorToFloat["out"]["r"]) floatToColor["parameters"]["b"].setInput(colorToFloat["out"]["g"]) # Read in a deep image imageReader = GafferImage.ImageReader() imageReader["fileName"].setValue(self.representativeDeepImagePath) # Try running OSLImage on deep image, then flattening oslImageDeep = GafferOSL.OSLImage() oslImageDeep["channels"].addChild( Gaffer.NameValuePlug( "", Gaffer.Color3fPlug( "value", defaultValue=imath.Color3f(1, 1, 1), flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ), True, "channel", Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) oslImageDeep["in"].setInput(imageReader["out"]) oslImageDeep["channels"]["channel"]["value"].setInput( floatToColor["out"]["c"]) postFlatten = GafferImage.DeepToFlat() postFlatten["in"].setInput(oslImageDeep["out"]) # Try running OSLImage on already flattened image preFlatten = GafferImage.DeepToFlat() preFlatten["in"].setInput(imageReader["out"]) oslImageFlat = GafferOSL.OSLImage() oslImageFlat["channels"].addChild( Gaffer.NameValuePlug( "", Gaffer.Color3fPlug( "value", defaultValue=imath.Color3f(1, 1, 1), flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ), True, "channel", Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) oslImageFlat["in"].setInput(preFlatten["out"]) oslImageFlat["channels"]["channel"]["value"].setInput( floatToColor["out"]["c"]) # Results should match self.assertImagesEqual(postFlatten["out"], oslImageFlat["out"]) # Also test reading from UV shaderGlobals = GafferOSL.OSLShader("Globals") shaderGlobals.loadShader("Utility/Globals") uvToColor = GafferOSL.OSLShader() uvToColor.loadShader("Conversion/FloatToColor") uvToColor["parameters"]["r"].setInput(shaderGlobals["out"]["globalU"]) uvToColor["parameters"]["g"].setInput(shaderGlobals["out"]["globalV"]) inAlpha = GafferOSL.OSLShader() inAlpha.loadShader("ImageProcessing/InChannel") inAlpha["parameters"]["channelName"].setValue('A') multiplyAlpha = GafferOSL.OSLShader() multiplyAlpha.loadShader("Maths/MultiplyColor") multiplyAlpha["parameters"]["a"].setInput(uvToColor["out"]["c"]) multiplyAlpha["parameters"]["b"]["r"].setInput( inAlpha["out"]["channelValue"]) multiplyAlpha["parameters"]["b"]["g"].setInput( inAlpha["out"]["channelValue"]) multiplyAlpha["parameters"]["b"]["b"].setInput( inAlpha["out"]["channelValue"]) oslImageDeep["channels"]["channel"]["value"].setInput( multiplyAlpha["out"]["out"]) outImage = GafferImage.ImageAlgo.image(postFlatten["out"]) size = outImage.dataWindow.size() + imath.V2i(1) i = 0 for y in range(size.y): for x in range(size.x): self.assertAlmostEqual(outImage["R"][i], (x + 0.5) / size.x * outImage["A"][i], places=5) self.assertAlmostEqual(outImage["G"][i], (size.y - y - 0.5) / size.y * outImage["A"][i], places=5) i += 1
def testDeep(self): representativeDeep = GafferImage.ImageReader() representativeDeep["fileName"].setValue( self.representativeDeepImagePath) deepShuffle = GafferImage.Shuffle() deepShuffle["in"].setInput(representativeDeep["out"]) postFlatten = GafferImage.DeepToFlat() postFlatten["in"].setInput(deepShuffle["out"]) preFlatten = GafferImage.DeepToFlat() preFlatten["in"].setInput(representativeDeep["out"]) flatShuffle = GafferImage.Shuffle() flatShuffle["in"].setInput(preFlatten["out"]) flatShuffle["channels"].setInput(deepShuffle["channels"]) deepShuffle["channels"].addChild(deepShuffle.ChannelPlug("R", "B")) deepShuffle["channels"].addChild(deepShuffle.ChannelPlug("G", "R")) deepShuffle["channels"].addChild(deepShuffle.ChannelPlug("B", "G")) deepOrig = GafferImage.ImageAlgo.tiles(representativeDeep["out"]) flatOrig = GafferImage.ImageAlgo.tiles(preFlatten["out"]) flatShuffled = GafferImage.ImageAlgo.tiles(flatShuffle["out"]) deepShuffled = GafferImage.ImageAlgo.tiles(deepShuffle["out"]) self.assertEqual(flatShuffled["R"], flatOrig["B"]) self.assertEqual(flatShuffled["G"], flatOrig["R"]) self.assertEqual(flatShuffled["B"], flatOrig["G"]) self.assertEqual(flatShuffled["A"], flatOrig["A"]) self.assertEqual(deepShuffled["R"], deepOrig["B"]) self.assertEqual(deepShuffled["G"], deepOrig["R"]) self.assertEqual(deepShuffled["B"], deepOrig["G"]) self.assertEqual(deepShuffled["A"], deepOrig["A"]) self.assertImagesEqual(postFlatten["out"], flatShuffle["out"]) deepShuffle["channels"].clearChildren() deepShuffle["channels"].addChild( deepShuffle.ChannelPlug("R", "__black")) deepShuffle["channels"].addChild( deepShuffle.ChannelPlug("G", "__white")) deepShuffle["channels"].addChild( deepShuffle.ChannelPlug("B", "__black")) flatGreen = GafferImage.ImageAlgo.tiles(flatShuffle["out"]) deepGreen = GafferImage.ImageAlgo.tiles(deepShuffle["out"]) for k in flatGreen["R"].keys(): self.assertEqual(flatGreen["R"][k], GafferImage.ImagePlug.blackTile()) self.assertEqual(flatGreen["G"][k], GafferImage.ImagePlug.whiteTile()) self.assertEqual(flatGreen["B"][k], GafferImage.ImagePlug.blackTile()) numSamples = deepGreen["sampleOffsets"][k][-1] self.assertEqual(deepGreen["R"][k], IECore.FloatVectorData([0.0] * numSamples)) self.assertEqual(deepGreen["G"][k], IECore.FloatVectorData([1.0] * numSamples)) self.assertEqual(deepGreen["B"][k], IECore.FloatVectorData([0.0] * numSamples)) deepPremult = GafferImage.Premultiply() deepPremult["in"].setInput(deepShuffle["out"]) postFlatten["in"].setInput(deepPremult["out"]) flatPremult = GafferImage.Premultiply() flatPremult["in"].setInput(flatShuffle["out"]) self.assertImagesEqual(postFlatten["out"], flatPremult["out"], maxDifference=0.000001)
def testBasics(self): representativeImage = GafferImage.ImageReader() representativeImage["fileName"].setValue(self.representativeImagePath) offset = GafferImage.Offset() offset["in"].setInput(representativeImage["out"]) holdout = GafferImage.DeepHoldout() holdout["in"].setInput(representativeImage["out"]) holdout["holdout"].setInput(offset["out"]) flat = GafferImage.DeepToFlat() flat["in"].setInput(representativeImage["out"]) # For the case of holding out an image by itself, we can find an analytic solution for the # held out alpha. For a composited alpha value A, the held out alpha will be ( 1 - ( 1 - A )^2 ) / 2 # Check that this relationship holds alphaOnlyHoldout = GafferImage.DeleteChannels() alphaOnlyHoldout["in"].setInput(holdout["out"]) alphaOnlyHoldout["mode"].setValue(GafferImage.DeleteChannels.Mode.Keep) alphaOnlyHoldout["channels"].setValue('[A]') complementAndSquare = GafferImage.Grade() complementAndSquare["in"].setInput(flat["out"]) complementAndSquare["channels"].setValue('[A]') complementAndSquare["multiply"].setValue(imath.Color4f(1, 1, 1, -1)) complementAndSquare["offset"].setValue(imath.Color4f(0, 0, 0, 1)) complementAndSquare["gamma"].setValue(imath.Color4f(1, 1, 1, 0.5)) complementAndHalve = GafferImage.Grade() complementAndHalve["in"].setInput(complementAndSquare["out"]) complementAndHalve["channels"].setValue('[A]') complementAndHalve["multiply"].setValue(imath.Color4f(1, 1, 1, -0.5)) complementAndHalve["offset"].setValue(imath.Color4f(0, 0, 0, 0.5)) alphaOnlyReference = GafferImage.DeleteChannels() alphaOnlyReference["in"].setInput(complementAndHalve["out"]) alphaOnlyReference["mode"].setValue( GafferImage.DeleteChannels.Mode.Keep) alphaOnlyReference["channels"].setValue('[A]') self.assertImagesEqual(alphaOnlyHoldout["out"], alphaOnlyReference["out"], maxDifference=1e-6) # For a more complex holdout, we can create a comparison manually using shuffles and a DeepMerge preShuffle = GafferImage.Shuffle() preShuffle["in"].setInput(representativeImage["out"]) preShuffle["channels"].addChild(preShuffle.ChannelPlug( "holdoutR", "R")) preShuffle["channels"].addChild(preShuffle.ChannelPlug( "holdoutG", "G")) preShuffle["channels"].addChild(preShuffle.ChannelPlug( "holdoutB", "B")) preShuffle["channels"].addChild(preShuffle.ChannelPlug( "holdoutA", "A")) manualHoldoutMerge = GafferImage.DeepMerge() manualHoldoutMerge["in"][0].setInput(preShuffle["out"]) manualHoldoutMerge["in"][1].setInput(offset["out"]) manualHoldoutFlatten = GafferImage.DeepToFlat() manualHoldoutFlatten["in"].setInput(manualHoldoutMerge["out"]) postShuffle = GafferImage.Shuffle() postShuffle["in"].setInput(manualHoldoutFlatten["out"]) postShuffle["channels"].addChild( postShuffle.ChannelPlug("R", "holdoutR")) postShuffle["channels"].addChild( postShuffle.ChannelPlug("G", "holdoutG")) postShuffle["channels"].addChild( postShuffle.ChannelPlug("B", "holdoutB")) postShuffle["channels"].addChild( postShuffle.ChannelPlug("A", "holdoutA")) channelCleanup = GafferImage.DeleteChannels() channelCleanup["in"].setInput(postShuffle["out"]) channelCleanup["mode"].setValue(GafferImage.DeleteChannels.Mode.Keep) channelCleanup["channels"].setValue('[RGBAZ]') cropCleanup = GafferImage.Crop() cropCleanup["in"].setInput(channelCleanup["out"]) cropCleanup["area"].setValue( imath.Box2i(imath.V2i(0, 0), imath.V2i(150, 100))) self.assertImagesEqual(holdout["out"], cropCleanup["out"], maxDifference=1e-5) # The way we handle Z is a bit arbitrary, but everything else we should be able to match with # this network with arbitrary inputs holdoutNoZ = GafferImage.DeleteChannels() holdoutNoZ["in"].setInput(holdout["out"]) holdoutNoZ["channels"].setValue('Z') channelCleanup["channels"].setValue('[RGBA]') offset["offset"].setValue(imath.V2i(13, 31)) self.assertImagesEqual(holdoutNoZ["out"], cropCleanup["out"], maxDifference=1e-5) offset["offset"].setValue(imath.V2i(-13, -51)) self.assertImagesEqual(holdoutNoZ["out"], cropCleanup["out"], maxDifference=1e-5) offset["offset"].setValue(imath.V2i(103, -27)) self.assertImagesEqual(holdoutNoZ["out"], cropCleanup["out"], maxDifference=1e-5)
def testDeepMix(self): representativeDeepImage = GafferImage.ImageReader() representativeDeepImage["fileName"].setValue( self.representativeDeepImagePath) # Easier to compare colors if we clamp - this requires unpremulting unpremultiply = GafferImage.Unpremultiply() unpremultiply["in"].setInput(representativeDeepImage["out"]) clamp = GafferImage.Grade() clamp["in"].setInput(unpremultiply["out"]) clamp["whiteClamp"].setValue(True) premultiply = GafferImage.Premultiply() premultiply["in"].setInput(clamp["out"]) # Create a deep image containing a mixture of samples from two offset copies, where # the "offsetted" channel contains a mask showing which of the samples come from # the offsetted copy offset = GafferImage.Offset() offset["in"].setInput(premultiply["out"]) offset["offset"].setValue(imath.V2i(33, -25)) addOffsetMarker = GafferImage.Shuffle() addOffsetMarker["channels"].addChild( GafferImage.Shuffle.ChannelPlug("offsetted", "__white")) addOffsetMarker["in"].setInput(offset["out"]) deepMerge = GafferImage.DeepMerge() deepMerge["in"].addChild( GafferImage.ImagePlug( "in2", flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, )) deepMerge["in"]["in0"].setInput(addOffsetMarker["out"]) deepMerge["in"]["in1"].setInput(premultiply["out"]) gradeBlack = GafferImage.Grade() gradeBlack["in"].setInput(deepMerge["out"]) gradeBlack["channels"].setValue('[RGBA]') gradeBlack["multiply"].setValue(imath.Color4f(0, 0, 0, 0)) mix = GafferImage.Mix("mix") mix["in"]["in0"].setInput(deepMerge["out"]) mix["in"]["in1"].setInput(gradeBlack["out"]) mix["mask"].setInput(deepMerge["out"]) mix["maskChannel"].setValue('offsetted') mixedFlat = GafferImage.DeepToFlat() mixedFlat["in"].setInput(mix["out"]) mergeRef = GafferImage.DeepToFlat() mergeRef["in"].setInput(deepMerge["out"]) startRef = GafferImage.DeepToFlat() startRef["in"].setInput(premultiply["out"]) startDiff = GafferImage.Merge() startDiff["in"]["in0"].setInput(startRef["out"]) startDiff["in"]["in1"].setInput(mixedFlat["out"]) startDiff["operation"].setValue(GafferImage.Merge.Operation.Difference) startDiffStats = GafferImage.ImageStats("startDiffStats") startDiffStats["in"].setInput(startDiff["out"]) startDiffStats["area"].setValue(mix["out"].dataWindow()) mergedDiff = GafferImage.Merge() mergedDiff["in"]["in0"].setInput(mergeRef["out"]) mergedDiff["in"]["in1"].setInput(mixedFlat["out"]) mergedDiff["operation"].setValue( GafferImage.Merge.Operation.Difference) mergedDiffStats = GafferImage.ImageStats("mergedDiffStats") mergedDiffStats["in"].setInput(mergedDiff["out"]) mergedDiffStats["area"].setValue(mix["out"].dataWindow()) # With mix set to 0, the mix outputs the left input with everything mix["mix"].setValue(0.0) self.assertEqual(mergedDiffStats["average"].getValue(), imath.Color4f(0)) self.assertEqual(mergedDiffStats["max"].getValue(), imath.Color4f(0)) self.assertGreater(startDiffStats["average"].getValue()[3], 0.2) self.assertGreater(startDiffStats["max"].getValue()[3], 0.999) for i in range(3): self.assertGreater(startDiffStats["average"].getValue()[i], 0.1) self.assertGreater(startDiffStats["max"].getValue()[i], 0.8) # With mix set to 1, the mix blends the offsetted samples to 0, and outputs just the non-offset # samples mix["mix"].setValue(1.0) for i in range(4): self.assertAlmostEqual(startDiffStats["average"].getValue()[i], 0) self.assertAlmostEqual(startDiffStats["max"].getValue()[i], 0, places=5) self.assertGreater(mergedDiffStats["average"].getValue()[3], 0.2) self.assertGreater(mergedDiffStats["max"].getValue()[3], 0.999) for i in range(3): self.assertGreater(mergedDiffStats["average"].getValue()[i], 0.1) self.assertGreater(mergedDiffStats["max"].getValue()[i], 0.8) # With the mix in between, the result should be a bit closer to both than the farthest # result at either extreme mix["mix"].setValue(0.75) self.assertLess(startDiffStats["average"].getValue()[3], 0.16) self.assertLess(startDiffStats["max"].getValue()[3], 0.8) self.assertLess(mergedDiffStats["average"].getValue()[3], 0.16) self.assertLess(mergedDiffStats["max"].getValue()[3], 0.8) for i in range(3): self.assertLess(startDiffStats["average"].getValue()[i], 0.08) self.assertLess(startDiffStats["max"].getValue()[i], 0.7) self.assertLess(mergedDiffStats["average"].getValue()[i], 0.08) self.assertLess(mergedDiffStats["max"].getValue()[i], 0.7)