Ejemplo n.º 1
0
	def __assertDeepStateProcessing( self, deepPlug, flatReferencePlug, refMaxTolerance, refAverageTolerance, expectedMaxPruning, expectedAveragePruning ) :

		# When testing on complex data, we can test that we are close to our reference

		# We can also check that the different sequences of computation supported by DeepState
		# all give identical results.  There are different code paths through the node depending on
		# the input and output state, and by switching between flattening in one step, vs sorting
		# or tidying before flattening, we can test all these paths.
		oneStepFlatten = GafferImage.DeepState()
		oneStepFlatten["in"].setInput( deepPlug )
		oneStepFlatten["deepState"].setValue( GafferImage.DeepState.TargetState.Flat )

		twoStepASort = GafferImage.DeepState()
		twoStepASort["in"].setInput( deepPlug )
		twoStepASort["deepState"].setValue( GafferImage.DeepState.TargetState.Sorted )
		twoStepAFlatten = GafferImage.DeepState( "TwoStepAFlatten" )
		twoStepAFlatten["in"].setInput( twoStepASort["out"] )
		twoStepAFlatten["deepState"].setValue( GafferImage.DeepState.TargetState.Flat )

		twoStepBTidy = GafferImage.DeepState()
		twoStepBTidy["in"].setInput( deepPlug )
		twoStepBTidy["deepState"].setValue( GafferImage.DeepState.TargetState.Tidy )
		twoStepBFlatten = GafferImage.DeepState( "TwoStepBFlatten" )
		twoStepBFlatten["in"].setInput( twoStepBTidy["out"] )
		twoStepBFlatten["deepState"].setValue( GafferImage.DeepState.TargetState.Flat )

		threeStepSort = GafferImage.DeepState()
		threeStepSort["in"].setInput( deepPlug )
		threeStepSort["deepState"].setValue( GafferImage.DeepState.TargetState.Sorted )
		threeStepTidy = GafferImage.DeepState()
		threeStepTidy["in"].setInput( threeStepSort["out"] )
		threeStepTidy["deepState"].setValue( GafferImage.DeepState.TargetState.Tidy )
		threeStepFlatten = GafferImage.DeepState( "ThreeStepFlatten")
		threeStepFlatten["in"].setInput( threeStepTidy["out"] )
		threeStepFlatten["deepState"].setValue( GafferImage.DeepState.TargetState.Flat )

		pruneOne = GafferImage.DeepState()
		pruneOne["in"].setInput( deepPlug )
		pruneOne["deepState"].setValue( GafferImage.DeepState.TargetState.Tidy )
		pruneOne["pruneOccluded"].setValue( True )
		pruneOne["occludedThreshold"].setValue( 1.0 )
		pruneOneFlatten = GafferImage.DeepState( "PruneOneFlatten" )
		pruneOneFlatten["in"].setInput( pruneOne["out"] )
		pruneOneFlatten["deepState"].setValue( GafferImage.DeepState.TargetState.Flat )

		prunePointNine = GafferImage.DeepState()
		prunePointNine["in"].setInput( deepPlug )
		prunePointNine["deepState"].setValue( GafferImage.DeepState.TargetState.Tidy )
		prunePointNine["pruneOccluded"].setValue( True )
		prunePointNine["occludedThreshold"].setValue( 0.9 )
		prunePointNineFlatten = GafferImage.DeepState( "PrunePointNineFlatten" )
		prunePointNineFlatten["in"].setInput( prunePointNine["out"] )
		prunePointNineFlatten["deepState"].setValue( GafferImage.DeepState.TargetState.Flat )

		diff = GafferImage.Merge()
		diff['operation'].setValue( GafferImage.Merge.Operation.Difference )
		diff['in'][0].setInput( oneStepFlatten["out"] )
		diff['in'][1].setInput( flatReferencePlug )

		stats = GafferImage.ImageStats()
		stats["in"].setInput( diff["out"] )
		stats["area"].setValue( diff["out"].dataWindow() )

		m = stats["max"].getValue()
		a = stats["average"].getValue()
		for i in range( 4 ):
			self.assertLessEqual( m[i], refMaxTolerance[i], "%s Channel : Max deviation from reference too high" % "RGBA"[i] )
			self.assertLessEqual( a[i], refAverageTolerance[i], "%s Channel : Average deviation from reference too high" % "RGBA"[i] )

		for method in [ twoStepAFlatten, twoStepBFlatten, threeStepFlatten, pruneOneFlatten, prunePointNineFlatten ]:
			diff["in"][1].setInput( method["out"] )
			if method in [ pruneOneFlatten, prunePointNineFlatten ]:
				# Pruning does require merging alpha at the back before alpha at the front, so floating point
				# imprecision in alpha is introduced
				self.assertLess( stats["max"].getValue(), imath.Color4f( 0.000006, 0.000007, 0.000006, 0.000001 ), "Compute method %s does not match single stage flatten" % method.getName() )
			else:
				# Without pruning, the alpha is processed identically
				self.assertLess( stats["max"].getValue(), imath.Color4f( 0.000007, 0.000007, 0.000007, 0.0000006 ), "Compute method %s does not match single stage flatten" % method.getName() )

		tidyCounts = GafferImage.DeepSampleCounts()
		tidyCounts["in"].setInput( twoStepBTidy["out"] )

		pruneOneCounts = GafferImage.DeepSampleCounts()
		pruneOneCounts["in"].setInput( pruneOne["out"] )

		pruneOneDiff = GafferImage.Merge()
		pruneOneDiff["operation"].setValue( GafferImage.Merge.Operation.Subtract )
		pruneOneDiff["in"][0].setInput( tidyCounts["out"] )
		pruneOneDiff["in"][1].setInput( pruneOneCounts["out"] )

		pruneOneStats = GafferImage.ImageStats()
		pruneOneStats["in"].setInput( pruneOneDiff["out"] )
		pruneOneStats["area"].setValue( diff["out"].dataWindow() )

		prunePointNineCounts = GafferImage.DeepSampleCounts()
		prunePointNineCounts["in"].setInput( prunePointNine["out"] )

		prunePointNineDiff = GafferImage.Merge()
		prunePointNineDiff["operation"].setValue( GafferImage.Merge.Operation.Subtract )
		prunePointNineDiff["in"][0].setInput( tidyCounts["out"] )
		prunePointNineDiff["in"][1].setInput( prunePointNineCounts["out"] )

		prunePointNineStats = GafferImage.ImageStats()
		prunePointNineStats["in"].setInput( prunePointNineDiff["out"] )
		prunePointNineStats["area"].setValue( diff["out"].dataWindow() )

		# All of tests contain some pixels where no samples can be pruned
		# ( But the number of samples should definitely never increase )
		self.assertEqual( pruneOneStats["max"].getValue()[0], 0 )
		self.assertEqual( prunePointNineStats["max"].getValue()[0], 0 )

		# These are rough heuristics, but make sure we are pruning something, and that the .9 threshold
		# prunes more.
		self.assertLessEqual( pruneOneStats["min"].getValue()[0], -expectedMaxPruning )
		self.assertLessEqual( prunePointNineStats["min"].getValue()[0], -expectedMaxPruning )
		self.assertLessEqual( pruneOneStats["average"].getValue()[0], -expectedAveragePruning )
		self.assertLessEqual( prunePointNineStats["average"].getValue()[0], pruneOneStats["average"].getValue()[0] * 2 )


		# Assert that we can repeat an operation on data where it has already been applied, and nothing happens
		resort = GafferImage.DeepState()
		resort["in"].setInput( threeStepSort["out"] )
		resort["deepState"].setValue( GafferImage.DeepState.TargetState.Sorted )
		self.assertImagesEqual( resort["out"], threeStepSort["out"] )

		reprunePointNine = GafferImage.DeepState()
		reprunePointNine["in"].setInput( prunePointNine["out"] )
		reprunePointNine["deepState"].setValue( GafferImage.DeepState.TargetState.Tidy )
		reprunePointNine["pruneOccluded"].setValue( True )
		reprunePointNine["occludedThreshold"].setValue( 0.9 )
		self.assertImagesEqual( reprunePointNine["out"], prunePointNine["out"] )

		reflatten = GafferImage.DeepState()
		reflatten["in"].setInput( oneStepFlatten["out"] )
		reflatten["deepState"].setValue( GafferImage.DeepState.TargetState.Flat )
		self.assertImagesEqual( reflatten["out"], oneStepFlatten["out"] )
Ejemplo n.º 2
0
	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 )
Ejemplo n.º 3
0
	def testPracticalTransparencyPrune( self ) :
		representativeImage = GafferImage.ImageReader()
		representativeImage["fileName"].setValue( self.representativeImagePath )

		empty = GafferImage.Empty()
		empty["format"].setValue( GafferImage.Format( imath.Box2i( imath.V2i( 0 ), imath.V2i( 150, 100 ) ), 1 ) )

		properlyLabelledIn = GafferImage.DeepMerge()
		properlyLabelledIn["in"][0].setInput( representativeImage["out"] )
		properlyLabelledIn["in"][1].setInput( empty["out"] )

		# The representative image from Arnold actually contains overlaps one floating point epsilon in width.
		# Get rid of those, and then we can see the sampleCounts change in a predictable way
		actuallyTidyIn = GafferImage.DeepState()
		actuallyTidyIn["in"].setInput( properlyLabelledIn["out"] )

		prune = GafferImage.DeepState()
		prune["in"].setInput( actuallyTidyIn["out"] )
		prune["pruneTransparent"].setValue( True )

		flatRef = GafferImage.DeepState()
		flatRef["in"].setInput( actuallyTidyIn["out"] )
		flatRef["deepState"].setValue( GafferImage.DeepState.TargetState.Flat )

		flatPrune = GafferImage.DeepState()
		flatPrune["in"].setInput( prune["out"] )
		flatPrune["deepState"].setValue( GafferImage.DeepState.TargetState.Flat )

		diff = GafferImage.Merge()
		diff['operation'].setValue( GafferImage.Merge.Operation.Difference )
		diff['in'][0].setInput( flatPrune["out"] )
		diff['in'][1].setInput( flatRef["out"] )

		diffStats = GafferImage.ImageStats()
		diffStats["in"].setInput( diff["out"] )
		diffStats["area"].setValue( diff["out"].dataWindow() )


		origCounts = GafferImage.DeepSampleCounts()
		origCounts["in"].setInput( actuallyTidyIn["out"] )

		prunedCounts = GafferImage.DeepSampleCounts()
		prunedCounts["in"].setInput( prune["out"] )

		diffCounts = GafferImage.Merge()
		diffCounts["operation"].setValue( GafferImage.Merge.Operation.Subtract )
		diffCounts["in"][0].setInput( origCounts["out"] )
		diffCounts["in"][1].setInput( prunedCounts["out"] )

		diffCountsStats = GafferImage.ImageStats()
		diffCountsStats["in"].setInput( diffCounts["out"] )
		diffCountsStats["area"].setValue( diffCounts["out"].dataWindow() )

		self.assertEqual( diffCountsStats["max"].getValue()[0], 0 )
		# For some reason, our test data from Arnold has a bunch of transparent pixels to start with,
		# so we've got some stuff to throw out
		self.assertLess( diffCountsStats["min"].getValue()[0], -20 )
		self.assertLess( diffCountsStats["min"].getValue()[0], -0.26 )

		# We've got some moderate error introduced by discarding transparent.  Why is it so large?
		# Looks like those transparent pixels are slightly emissive
		for i in range( 4 ):
			self.assertLessEqual( diffStats["max"].getValue()[i], [0.00001,0.00001,0.00001,0][i] )
			self.assertGreaterEqual( diffStats["max"].getValue()[i], [0.000001,0.000001,0.000001,0][i] )

		# By premulting/unpremulting, we zero out samples with no alpha
		premultiply = GafferImage.Premultiply()
		premultiply["in"].setInput( actuallyTidyIn["out"] )
		unpremultiply = GafferImage.Unpremultiply()
		unpremultiply["in"].setInput( premultiply["out"] )
		flatRef["in"].setInput( unpremultiply["out"] )
		prune["in"].setInput( unpremultiply["out"] )

		# That gets us a couple extra digits of matching - this is more like what we would expect based
		# on floating point precision
		for i in range( 4 ):
			self.assertLessEqual( diffStats["max"].getValue()[i], [0.0000005,0.0000005,0.0000005,0][i] )

		# But now lets hack it to really make some transparent pixels
		grade = GafferImage.Grade()
		grade["in"].setInput( actuallyTidyIn["out"] )
		grade["channels"].setValue( '[A]' )
		grade["multiply"]["a"].setValue( 1.5 )
		grade["offset"]["a"].setValue( -0.5 )

		premultiply['in'].setInput( grade["out"] )

		# Now we can kill lots of samples
		self.assertEqual( diffCountsStats["max"].getValue()[0], 0 )
		self.assertLess( diffCountsStats["min"].getValue()[0], -200 )
		self.assertLess( diffCountsStats["min"].getValue()[0], -10 )

		# And the flattened results still match closely
		for i in range( 4 ):
			self.assertLessEqual( diffStats["max"].getValue()[i], [0.0000005,0.0000005,0.0000005,0.0000002][i] )