示例#1
0
	def testMismatchedDataWindow( self ) :

		# Set up a situation where we're copying channels
		# from an image with a smaller data window than the
		# primary input.
		main = self.__constantLayer( "", IECore.Color4f( 1 ), size = IECore.V2i( 64 ) )
		diffuse = self.__constantLayer( "diffuse", IECore.Color4f( 0.5 ), size = IECore.V2i( 60 ) )

		copy = GafferImage.CopyChannels()
		copy["in"][0].setInput( main["out"] )
		copy["in"][1].setInput( diffuse["out"] )
		copy["channels"].setValue( "*" )

		# Format should be taken from the primary input, and data window should be the union
		# of both input data windows.

		self.assertEqual( copy["out"]["format"].getValue(), main["out"]["format"].getValue() )
		self.assertEqual( copy["out"]["dataWindow"].getValue(), main["out"]["dataWindow"].getValue() )

		# And CopyChannels must take care to properly fill in with
		# black any missing areas from the second input.

		for channel in ( "R", "G", "B", "A" ) :

			diffuseDW = diffuse["out"]["dataWindow"].getValue()
			copyDW = copy["out"]["dataWindow"].getValue()
			sampler = GafferImage.Sampler( copy["out"], "diffuse." + channel, copyDW )
			for x in range( copyDW.min.x, copyDW.max.x ) :
				for y in range( copyDW.min.y, copyDW.max.y ) :
					if GafferImage.BufferAlgo.contains( diffuseDW, IECore.V2i( x, y ) ) :
						self.assertEqual( sampler.sample( x, y ), 0.5 )
					else :
						self.assertEqual( sampler.sample( x, y ), 0 )
示例#2
0
文件: CDLTest.py 项目: wubugui/gaffer
    def testMultipleLayers(self):

        main = GafferImage.Constant()
        main["color"].setValue(imath.Color4f(1, 0.5, 0.25, 1))

        diffuse = GafferImage.Constant()
        diffuse["color"].setValue(imath.Color4f(0.25, 0.5, 0.75, 1))
        diffuse["layer"].setValue("diffuse")

        m = GafferImage.CopyChannels()
        m["in"][0].setInput(main["out"])
        m["in"][1].setInput(diffuse["out"])
        m["channels"].setValue("*")

        cdl = GafferImage.CDL()
        cdl["in"].setInput(m["out"])

        self.assertImagesEqual(cdl["out"], m["out"])

        mainCDLSampler = GafferImage.ImageSampler()
        mainCDLSampler["image"].setInput(cdl["out"])
        mainCDLSampler["pixel"].setValue(imath.V2f(0.5))
        mainCDLSampler["channels"].setValue(
            IECore.StringVectorData(["R", "G", "B", "A"]))

        diffuseCDLSampler = GafferImage.ImageSampler()
        diffuseCDLSampler["image"].setInput(cdl["out"])
        diffuseCDLSampler["pixel"].setValue(imath.V2f(0.5))
        diffuseCDLSampler["channels"].setValue(
            IECore.StringVectorData(["diffuse." + x for x in "RGBA"]))

        self.assertEqual(mainCDLSampler["color"].getValue(),
                         main["color"].getValue())
        self.assertEqual(diffuseCDLSampler["color"].getValue(),
                         diffuse["color"].getValue())

        cdl["saturation"].setValue(0.5)

        self.assertNotEqual(mainCDLSampler["color"].getValue(),
                            main["color"].getValue())
        self.assertEqual(diffuseCDLSampler["color"].getValue(),
                         diffuse["color"].getValue())

        cdl["channels"].setValue("*[RGB]")

        self.assertNotEqual(mainCDLSampler["color"].getValue(),
                            main["color"].getValue())
        self.assertNotEqual(diffuseCDLSampler["color"].getValue(),
                            diffuse["color"].getValue())
        self.assertNotEqual(mainCDLSampler["color"].hash(),
                            diffuseCDLSampler["color"].hash())
        self.assertNotEqual(mainCDLSampler["color"].getValue(),
                            diffuseCDLSampler["color"].getValue())

        cdl["channels"].setValue("diffuse.[RGB]")

        self.assertEqual(mainCDLSampler["color"].getValue(),
                         main["color"].getValue())
        self.assertNotEqual(diffuseCDLSampler["color"].getValue(),
                            diffuse["color"].getValue())
示例#3
0
	def testChannelsPlug( self ) :

		main = self.__constantLayer( "", IECore.Color4f( 1, 0.5, 0.25, 1 ) )
		diffuse = self.__constantLayer( "diffuse", IECore.Color4f( 0, 0.25, 0.5, 1 ) )

		copy = GafferImage.CopyChannels()
		copy["in"][0].setInput( main["out"] )
		copy["in"][1].setInput( diffuse["out"] )

		copy["channels"].setValue( "diffuse.R" )

		self.assertEqual(
			copy["out"]["channelNames"].getValue(),
			IECore.StringVectorData( [ "R", "G", "B", "A", "diffuse.R" ] ),
		)

		copy["channels"].setValue( "diffuse.R diffuse.B" )

		self.assertEqual(
			copy["out"]["channelNames"].getValue(),
			IECore.StringVectorData( [ "R", "G", "B", "A", "diffuse.R", "diffuse.B" ] ),
		)

		copy["channels"].setValue( "diffuse.*" )

		self.assertEqual(
			copy["out"]["channelNames"].getValue(),
			IECore.StringVectorData( [ "R", "G", "B", "A", "diffuse.R", "diffuse.G", "diffuse.B", "diffuse.A" ] ),
		)
示例#4
0
	def testAffectsChannelNames( self ) :

		c1 = GafferImage.Constant()
		c2 = GafferImage.Constant()

		copy = GafferImage.CopyChannels()
		copy["in"][0].setInput( c1["out"] )
		copy["in"][1].setInput( c2["out"] )

		cs = GafferTest.CapturingSlot( copy.plugDirtiedSignal() )

		c2["layer"].setValue( "diffuse" )
		self.assertTrue( copy["out"]["channelNames"] in [ x[0] for x in cs ] )

		del cs[:]
		copy["channels"].setValue( "diffuse.R" )
		self.assertTrue( copy["out"]["channelNames"] in [ x[0] for x in cs ] )
示例#5
0
    def testSimpleLayers(self):

        expected = GafferImage.ImageReader()
        expected["fileName"].setValue(self.layersPath)

        constant = GafferImage.Constant()
        constant["format"].setValue(GafferImage.Format(10, 10, 1.000))
        constant["color"].setValue(IECore.Color4f(1, 0, 0, 1))

        crop = GafferImage.Crop()
        crop["affectDisplayWindow"].setValue(False)
        crop["in"].setInput(constant["out"])

        delete = GafferImage.DeleteChannels()
        delete["channels"].setValue("A")
        delete["in"].setInput(crop["out"])

        collect = GafferImage.CollectImages()
        collect["rootLayers"].setValue(IECore.StringVectorData(['0', '1',
                                                                '2']))
        collect["in"].setInput(delete["out"])

        e = Gaffer.Expression()
        crop.addChild(e)
        e.setExpression(
            inspect.cleandoc("""
		layer = context.get( "collect:layerName", None )

		if layer:
			o = IECore.V2i(2, 2 ) * ( 1 + int( layer ) )
			area = IECore.Box2i( o, IECore.V2i( 1, 1 ) + o )
		else:
			area = IECore.Box2i( IECore.V2i( 3, 1 ), IECore.V2i( 4, 2 ) )

		parent["area"] = area
		"""), "python")

        copyChannels = GafferImage.CopyChannels()
        copyChannels["channels"].setValue("*")
        copyChannels["in"][0].setInput(crop["out"])
        copyChannels["in"][1].setInput(collect["out"])

        self.assertImagesEqual(copyChannels["out"],
                               expected["out"],
                               ignoreMetadata=True)
示例#6
0
    def testPerLayerExpression(self):

        script = Gaffer.ScriptNode()

        script["c1"] = GafferImage.Constant()
        script["c1"]["color"].setValue(imath.Color4f(1))

        script["c2"] = GafferImage.Constant()
        script["c2"]["color"].setValue(imath.Color4f(1))
        script["c2"]["layer"].setValue("B")

        script["copyChannels"] = GafferImage.CopyChannels()
        script["copyChannels"]["in"][0].setInput(script["c1"]["out"])
        script["copyChannels"]["in"][1].setInput(script["c2"]["out"])
        script["copyChannels"]["channels"].setValue("*")

        script["grade"] = GafferImage.Grade()
        script["grade"]["in"].setInput(script["copyChannels"]["out"])
        script["grade"]["channels"].setValue("*")

        script["expression"] = Gaffer.Expression()
        script["expression"].setExpression(
            inspect.cleandoc("""
			import GafferImage
			layerName = GafferImage.ImageAlgo.layerName( context["image:channelName" ] )
			parent["grade"]["gain"] = imath.Color4f( 1 if layerName == "B" else 0.5 )
			"""))

        sampler = GafferImage.ImageSampler()
        sampler["image"].setInput(script["grade"]["out"])
        sampler["pixel"].setValue(imath.V2f(10.5))

        sampler["channels"].setValue(
            IECore.StringVectorData(["R", "G", "B", "A"]))
        self.assertEqual(sampler["color"].getValue(), imath.Color4f(0.5))

        sampler["channels"].setValue(
            IECore.StringVectorData(["B.R", "B.G", "B.B", "B.A"]))
        self.assertEqual(sampler["color"].getValue(), imath.Color4f(1))
示例#7
0
	def test( self ) :

		# Set up a copy where the main layer comes from the first
		# input and the diffuse layer is copied in from a second input.

		main = self.__constantLayer( "", IECore.Color4f( 1, 0.5, 0.25, 1 ) )
		diffuse = self.__constantLayer( "diffuse", IECore.Color4f( 0, 0.25, 0.5, 1 ) )

		copy = GafferImage.CopyChannels()
		copy["in"][0].setInput( main["out"] )
		copy["in"][1].setInput( diffuse["out"] )
		copy["channels"].setValue( "*" )

		# Check that our new image has all the expected channels.

		self.assertEqual(
			copy["out"]["channelNames"].getValue(),
			IECore.StringVectorData( [ "R", "G", "B", "A", "diffuse.R", "diffuse.G", "diffuse.B", "diffuse.A" ] ),
		)

		# Check that each channel is a perfect pass-through from the
		# relevant input, sharing the same entries in the cache.

		for constant in ( main, diffuse ) :
			for channel in ( "R", "G", "B", "A" ) :

				if constant["layer"].getValue() :
					channel = constant["layer"].getValue() + "." + channel

				self.assertEqual(
					copy["out"].channelDataHash( channel, IECore.V2i( 0 ) ),
					constant["out"].channelDataHash( channel, IECore.V2i( 0 ) ),
				)

				self.assertTrue(
					copy["out"].channelData( channel, IECore.V2i( 0 ), _copy = False ).isSame(
						constant["out"].channelData( channel, IECore.V2i( 0 ), _copy = False )
					)
				)
示例#8
0
    def testMerging(self):

        allFilter = GafferScene.PathFilter()
        allFilter["paths"].setValue(IECore.StringVectorData(['/...']))

        plane = GafferScene.Plane()
        plane["divisions"].setValue(imath.V2i(20, 20))

        # Assign a basic gradient shader
        uvGradientCode = GafferOSL.OSLCode()
        uvGradientCode["out"].addChild(
            Gaffer.Color3fPlug("out", direction=Gaffer.Plug.Direction.Out))
        uvGradientCode["code"].setValue('out = color( u, v, 0.5 );')

        shaderAssignment = GafferScene.ShaderAssignment()
        shaderAssignment["in"].setInput(plane["out"])
        shaderAssignment["filter"].setInput(allFilter["out"])
        shaderAssignment["shader"].setInput(uvGradientCode["out"]["out"])

        # Set up a random id from 0 - 3 on each face

        randomCode = GafferOSL.OSLCode()
        randomCode["out"].addChild(
            Gaffer.IntPlug("randomId", direction=Gaffer.Plug.Direction.Out))
        randomCode["code"].setValue(
            'randomId = int(cellnoise( P * 100 ) * 4);')

        outInt = GafferOSL.OSLShader()
        outInt.loadShader("ObjectProcessing/OutInt")
        outInt["parameters"]["name"].setValue('randomId')
        outInt["parameters"]["value"].setInput(randomCode["out"]["randomId"])

        outObject = GafferOSL.OSLShader()
        outObject.loadShader("ObjectProcessing/OutObject")
        outObject["parameters"]["in0"].setInput(
            outInt["out"]["primitiveVariable"])

        oSLObject = GafferOSL.OSLObject()
        oSLObject["in"].setInput(shaderAssignment["out"])
        oSLObject["filter"].setInput(allFilter["out"])
        oSLObject["shader"].setInput(outObject["out"])
        oSLObject["interpolation"].setValue(2)

        # Create 4 meshes by picking each of the 4 ids

        deleteContextVariables = Gaffer.DeleteContextVariables()
        deleteContextVariables.setup(GafferScene.ScenePlug())
        deleteContextVariables["variables"].setValue('collect:rootName')
        deleteContextVariables["in"].setInput(oSLObject["out"])

        pickCode = GafferOSL.OSLCode()
        pickCode["parameters"].addChild(Gaffer.IntPlug("targetId"))
        pickCode["out"].addChild(
            Gaffer.IntPlug("cull", direction=Gaffer.Plug.Direction.Out))
        pickCode["code"].setValue(
            'int randomId; getattribute( "randomId", randomId ); cull = randomId != targetId;'
        )

        expression = Gaffer.Expression()
        pickCode.addChild(expression)
        expression.setExpression(
            'parent.parameters.targetId = stoi( context( "collect:rootName", "0" ) );',
            "OSL")

        outInt1 = GafferOSL.OSLShader()
        outInt1.loadShader("ObjectProcessing/OutInt")
        outInt1["parameters"]["name"].setValue('deleteFaces')
        outInt1["parameters"]["value"].setInput(pickCode["out"]["cull"])

        outObject1 = GafferOSL.OSLShader()
        outObject1.loadShader("ObjectProcessing/OutObject")
        outObject1["parameters"]["in0"].setInput(
            outInt1["out"]["primitiveVariable"])

        oSLObject1 = GafferOSL.OSLObject()
        oSLObject1["in"].setInput(deleteContextVariables["out"])
        oSLObject1["filter"].setInput(allFilter["out"])
        oSLObject1["shader"].setInput(outObject1["out"])
        oSLObject1["interpolation"].setValue(2)

        deleteFaces = GafferScene.DeleteFaces()
        deleteFaces["in"].setInput(oSLObject1["out"])
        deleteFaces["filter"].setInput(allFilter["out"])

        collectScenes = GafferScene.CollectScenes()
        collectScenes["in"].setInput(deleteFaces["out"])
        collectScenes["rootNames"].setValue(
            IECore.StringVectorData(['0', '1', '2', '3']))
        collectScenes["sourceRoot"].setValue('/plane')

        # First variant:  bake everything, covering the whole 1001 UDIM

        customAttributes1 = GafferScene.CustomAttributes()
        customAttributes1["attributes"].addMember(
            'bake:fileName',
            IECore.StringData(
                '${bakeDirectory}/complete/<AOV>/<AOV>.<UDIM>.exr'))
        customAttributes1["in"].setInput(collectScenes["out"])

        # Second vaiant: bake just 2 of the 4 meshes, leaving lots of holes that will need filling
        pruneFilter = GafferScene.PathFilter()
        pruneFilter["paths"].setValue(IECore.StringVectorData(['/2', '/3']))

        prune = GafferScene.Prune()
        prune["in"].setInput(collectScenes["out"])
        prune["filter"].setInput(pruneFilter["out"])

        customAttributes2 = GafferScene.CustomAttributes()
        customAttributes2["attributes"].addMember(
            'bake:fileName',
            IECore.StringData(
                '${bakeDirectory}/incomplete/<AOV>/<AOV>.<UDIM>.exr'))
        customAttributes2["in"].setInput(prune["out"])

        # Third variant: bake everything, but with one mesh at a higher resolution

        customAttributes3 = GafferScene.CustomAttributes()
        customAttributes3["attributes"].addMember(
            'bake:fileName',
            IECore.StringData(
                '${bakeDirectory}/mismatch/<AOV>/<AOV>.<UDIM>.exr'))
        customAttributes3["in"].setInput(collectScenes["out"])

        pathFilter2 = GafferScene.PathFilter()
        pathFilter2["paths"].setValue(IECore.StringVectorData(['/2']))

        customAttributes = GafferScene.CustomAttributes()
        customAttributes["attributes"].addMember('bake:resolution',
                                                 IECore.IntData(200))
        customAttributes["filter"].setInput(pathFilter2["out"])
        customAttributes["in"].setInput(customAttributes3["out"])

        # Merge the 3 variants
        mergeGroup = GafferScene.Group()
        mergeGroup["in"][-1].setInput(customAttributes["out"])
        mergeGroup["in"][-1].setInput(customAttributes1["out"])
        mergeGroup["in"][-1].setInput(customAttributes2["out"])

        arnoldTextureBake = GafferArnold.ArnoldTextureBake()
        arnoldTextureBake["in"].setInput(mergeGroup["out"])
        arnoldTextureBake["filter"].setInput(allFilter["out"])
        arnoldTextureBake["bakeDirectory"].setValue(self.temporaryDirectory() +
                                                    '/bakeMerge/')
        arnoldTextureBake["defaultResolution"].setValue(128)

        # We want to check the intermediate results
        arnoldTextureBake["cleanupIntermediateFiles"].setValue(False)

        # Dispatch the bake
        script = Gaffer.ScriptNode()
        script.addChild(arnoldTextureBake)
        dispatcher = GafferDispatch.LocalDispatcher()
        dispatcher["jobsDirectory"].setValue(self.temporaryDirectory())
        dispatcher.dispatch([arnoldTextureBake])

        # Check results
        imageReader = GafferImage.ImageReader()

        outLayer = GafferOSL.OSLShader()
        outLayer.loadShader("ImageProcessing/OutLayer")
        outLayer["parameters"]["layerColor"].setInput(
            uvGradientCode["out"]["out"])

        outImage = GafferOSL.OSLShader()
        outImage.loadShader("ImageProcessing/OutImage")
        outImage["parameters"]["in0"].setInput(outLayer["out"]["layer"])
        oSLImage = GafferOSL.OSLImage()
        oSLImage["in"].setInput(imageReader["out"])
        oSLImage["shader"].setInput(outImage["out"])

        merge3 = GafferImage.Merge()
        merge3["in"]["in0"].setInput(oSLImage["out"])
        merge3["in"]["in1"].setInput(imageReader["out"])
        merge3["operation"].setValue(10)

        edgeDetect = self.SimpleEdgeDetect()
        edgeDetect["in"].setInput(imageReader["out"])

        edgeStats = GafferImage.ImageStats()
        edgeStats["in"].setInput(edgeDetect["out"])

        refDiffStats = GafferImage.ImageStats()
        refDiffStats["in"].setInput(merge3["out"])

        oneLayerReader = GafferImage.ImageReader()

        grade = GafferImage.Grade()
        grade["in"].setInput(oneLayerReader["out"])
        grade["channels"].setValue('[A]')
        grade["blackPoint"].setValue(imath.Color4f(0, 0, 0, 0.999899983))

        copyChannels = GafferImage.CopyChannels()
        copyChannels["in"]["in0"].setInput(merge3["out"])
        copyChannels["in"]["in1"].setInput(grade["out"])
        copyChannels["channels"].setValue('[A]')

        premultiply = GafferImage.Premultiply()
        premultiply["in"].setInput(copyChannels["out"])

        refDiffCoveredStats = GafferImage.ImageStats()
        refDiffCoveredStats["in"].setInput(premultiply["out"])

        # We are testing 3 different cases:
        # complete : Should be an exact match.
        # incomplete : Expect some mild variance of slopes and some error, because we have to
        #              reconstruct a lot of missing data.
        # mismatch : We should get a larger image, sized to the highest override on any mesh.
        #            Match won't be as perfect, because we're combining source images at
        #            different resolutions
        for name, expectedSize, maxEdge, maxRefDiff, maxMaskedDiff in [
            ("complete", 128, 0.01, 0.000001, 0.000001),
            ("incomplete", 128, 0.05, 0.15, 0.000001),
            ("mismatch", 200, 0.01, 0.01, 0.01)
        ]:
            imageReader["fileName"].setValue(self.temporaryDirectory() +
                                             "/bakeMerge/" + name +
                                             "/beauty/beauty.1001.tx")
            oneLayerReader["fileName"].setValue(self.temporaryDirectory() +
                                                "/bakeMerge/" + name +
                                                "/beauty/beauty.1001.exr")

            self.assertEqual(imageReader["out"]["format"].getValue().width(),
                             expectedSize)
            self.assertEqual(imageReader["out"]["format"].getValue().height(),
                             expectedSize)

            edgeStats["area"].setValue(
                imath.Box2i(imath.V2i(1), imath.V2i(expectedSize - 1)))
            refDiffStats["area"].setValue(
                imath.Box2i(imath.V2i(1), imath.V2i(expectedSize - 1)))
            refDiffCoveredStats["area"].setValue(
                imath.Box2i(imath.V2i(0), imath.V2i(expectedSize)))

            # Blue channel is constant, so everything should line up perfectly
            self.assertEqual(0, edgeStats["max"].getValue()[2])
            self.assertEqual(0, refDiffStats["max"].getValue()[2])
            self.assertEqual(0, refDiffCoveredStats["max"].getValue()[2])

            for i in range(2):

                # Make sure we've got actual data, by checking that we have some error ( we're not expecting
                # to perfectly reconstruct the gradient when the input is incomplete )
                self.assertGreater(edgeStats["max"].getValue()[i], 0.005)
                if name == "incomplete":
                    self.assertGreater(edgeStats["max"].getValue()[i], 0.03)
                    self.assertGreater(refDiffStats["max"].getValue()[i], 0.06)

                self.assertLess(edgeStats["max"].getValue()[i], maxEdge)
                self.assertLess(refDiffStats["max"].getValue()[i], maxRefDiff)
                self.assertLess(refDiffCoveredStats["max"].getValue()[i],
                                maxMaskedDiff)
示例#9
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 )
示例#10
0
    def testWarpImage(self):
        def __warpImage(size, distortion, idistortStyle):
            w = IECore.Box2i(IECore.V2i(0), size - IECore.V2i(1))
            image = IECore.ImagePrimitive(w, w)

            R = IECore.FloatVectorData(size.x * size.y)
            G = IECore.FloatVectorData(size.x * size.y)

            for iy in range(size.y):
                for ix in range(size.x):
                    x = (ix + 0.5) / size.x
                    y = 1 - (iy + 0.5) / size.y
                    if idistortStyle:
                        R[iy * size.x +
                          ix] = distortion * math.sin(y * 8) * size.x
                        G[iy * size.x +
                          ix] = distortion * math.sin(x * 8) * size.y
                    else:
                        R[iy * size.x + ix] = x + distortion * math.sin(y * 8)
                        G[iy * size.x + ix] = y + distortion * math.sin(x * 8)

            image["R"] = IECore.PrimitiveVariable(
                IECore.PrimitiveVariable.Interpolation.Vertex, R)
            image["G"] = IECore.PrimitiveVariable(
                IECore.PrimitiveVariable.Interpolation.Vertex, G)

            return image

        def __dotGrid(size):
            w = IECore.Box2i(IECore.V2i(0), size - IECore.V2i(1))
            image = IECore.ImagePrimitive(w, w)

            R = IECore.FloatVectorData(size.x * size.y)
            G = IECore.FloatVectorData(size.x * size.y)
            B = IECore.FloatVectorData(size.x * size.y)

            for iy in range(0, size.y):
                for ix in range(0, size.x):
                    q = max(ix % 16, iy % 16)

                    R[iy * size.x + ix] = q < 1
                    G[iy * size.x + ix] = q < 4
                    B[iy * size.x + ix] = q < 8

            image["R"] = IECore.PrimitiveVariable(
                IECore.PrimitiveVariable.Interpolation.Vertex, R)
            image["G"] = IECore.PrimitiveVariable(
                IECore.PrimitiveVariable.Interpolation.Vertex, G)
            image["B"] = IECore.PrimitiveVariable(
                IECore.PrimitiveVariable.Interpolation.Vertex, B)

            return image

        objectToImageSource = GafferImage.ObjectToImage()
        objectToImageSource["object"].setValue(__dotGrid(IECore.V2i(300)))

        # TODO - reorder channels of our source image because ObjectToImage outputs in opposite order to
        # the rest of Gaffer.  This probably should be fixed in ObjectToImage,
        # or we shouldn't depend on channel order to check if images are equal?
        sourceReorderConstant = GafferImage.Constant()
        sourceReorderConstant["format"].setValue(
            GafferImage.Format(300, 300, 1.000))
        sourceReorderDelete = GafferImage.DeleteChannels()
        sourceReorderDelete["channels"].setValue(IECore.StringVectorData(["A"
                                                                          ]))
        sourceReorderDelete["in"].setInput(sourceReorderConstant["out"])
        sourceReorder = GafferImage.CopyChannels()
        sourceReorder["channels"].setValue("R G B")
        sourceReorder["in"]["in0"].setInput(sourceReorderDelete["out"])
        sourceReorder["in"]["in1"].setInput(objectToImageSource["out"])

        objectToImageVector = GafferImage.ObjectToImage()

        vectorWarp = GafferImage.VectorWarp()
        vectorWarp["in"].setInput(sourceReorder["out"])
        vectorWarp["vector"].setInput(objectToImageVector["out"])

        # Test that a warp with no distortion and a box filter reproduces the input
        objectToImageVector["object"].setValue(
            __warpImage(IECore.V2i(300), 0, False))
        vectorWarp["filter"].setValue("box")
        self.assertImagesEqual(vectorWarp["out"],
                               sourceReorder["out"],
                               maxDifference=0.00001)

        # Test that a warp with distortion produces an expected output
        objectToImageVector["object"].setValue(
            __warpImage(IECore.V2i(300), 0.2, False))
        vectorWarp["filter"].setValue("blackman-harris")

        # Enable to write out images for visual comparison
        if False:
            testWriter = GafferImage.ImageWriter()
            testWriter["in"].setInput(vectorWarp["out"])
            testWriter["fileName"].setValue("/tmp/dotGrid.warped.exr")
            testWriter["task"].execute()

        expectedReader = GafferImage.ImageReader()
        expectedReader["fileName"].setValue(
            os.path.dirname(__file__) + "/images/dotGrid.warped.exr")

        # Test that we can get the same result using pixel offsets instead of normalized coordinates
        objectToImageVector["object"].setValue(
            __warpImage(IECore.V2i(300), 0.2, True))
        vectorWarp["vectorMode"].setValue(
            GafferImage.VectorWarp.VectorMode.Relative)
        vectorWarp["vectorUnits"].setValue(
            GafferImage.VectorWarp.VectorUnits.Pixels)

        self.assertImagesEqual(vectorWarp["out"],
                               expectedReader["out"],
                               maxDifference=0.0005,
                               ignoreMetadata=True)
示例#11
0
    def __init__(self, name="ColoriseSHO"):

        GafferImage.ImageProcessor.__init__(self, name)

        self["show"] = Gaffer.IntPlug(defaultValue=0, minValue=0, maxValue=3)

        # Channel colorising

        merge = GafferImage.Merge()
        self["__Merge"] = merge
        merge["operation"].setValue(0)

        outputSwitch = Gaffer.Switch()
        self["__Switch_output"] = outputSwitch
        outputSwitch.setup(self["out"])
        outputSwitch["index"].setInput(self["show"])
        outputSwitch["in"][0].setInput(merge["out"])

        for channel in GafferAstro.NarrowbandChannels:

            self["source%s" % channel] = Gaffer.StringPlug(
                defaultValue='%s.input' % channel)
            self["range%s" %
                 channel] = Gaffer.V2fPlug(defaultValue=imath.V2f(0, 1))
            self["map%s" % channel] = Gaffer.SplinefColor4fPlug(
                defaultValue=self.__mapDefaults[channel])
            self["saturation%s" % channel] = Gaffer.FloatPlug(defaultValue=1.0,
                                                              minValue=0.0)
            self["multiply%s" % channel] = Gaffer.FloatPlug(defaultValue=1.0)
            self["gamma%s" % channel] = Gaffer.FloatPlug(defaultValue=1.0)

            colorise = GafferAstro.Colorise()
            self["__Colorise_%s" % channel] = colorise

            colorise["in"].setInput(self["in"])
            colorise["channel"].setInput(self["source%s" % channel])
            colorise["mapEnabled"].setValue(True)
            colorise["range"].setInput(self["range%s" % channel])
            colorise["enabled"].setInput(colorise["channel"])
            # Work around issue where setInput doesn't sync the number of knots
            colorise["map"].setValue(self["map%s" % channel].getValue())
            colorise["map"].setInput(self["map%s" % channel])

            cdl = GafferImage.CDL()
            self["__CDL_%s" % channel] = cdl
            cdl["in"].setInput(colorise["out"])
            cdl["saturation"].setInput(self["saturation%s" % channel])

            grade = GafferImage.Grade()
            self["__Grade_%s" % channel] = grade
            grade["in"].setInput(cdl["out"])
            grade["multiply"].gang()
            grade["multiply"]["r"].setInput(self["multiply%s" % channel])
            grade["gamma"].gang()
            grade["gamma"]["r"].setInput(self["gamma%s" % channel])

            merge["in"][len(merge["in"]) - 1].setInput(grade["out"])
            outputSwitch["in"][len(outputSwitch["in"]) - 1].setInput(
                grade["out"])

        self["saturation"] = Gaffer.FloatPlug(defaultValue=1.0, minValue=0.0)
        self["blackPoint"] = Gaffer.FloatPlug(defaultValue=0.0)
        self["whitePoint"] = Gaffer.FloatPlug(defaultValue=1.0)
        self["multiply"] = Gaffer.Color4fPlug(
            defaultValue=imath.Color4f(1, 1, 1, 1))
        self["gamma"] = Gaffer.FloatPlug(defaultValue=1.0, minValue=0.0)

        outputCdl = GafferImage.CDL()
        self["__CDL_output"] = outputCdl
        outputCdl["in"].setInput(outputSwitch["out"])
        outputCdl["saturation"].setInput(self["saturation"])

        outputGrade = GafferImage.Grade()
        self["__Grade_output"] = outputGrade
        outputGrade["in"].setInput(outputCdl["out"])
        outputGrade["blackPoint"].gang()
        outputGrade["blackPoint"]["r"].setInput(self["blackPoint"])
        outputGrade["whitePoint"].gang()
        outputGrade["whitePoint"]["r"].setInput(self["whitePoint"])
        outputGrade["multiply"].setInput(self["multiply"])
        outputGrade["gamma"].gang()
        outputGrade["gamma"]["r"].setInput(self["gamma"])

        copyChannels = GafferImage.CopyChannels()
        self["__CopyChannels"] = copyChannels
        copyChannels["in"][0].setInput(self["in"])
        copyChannels["in"][1].setInput(outputGrade["out"])
        copyChannels["channels"].setValue("*")

        self["out"].setInput(copyChannels["out"])
示例#12
0
    def __init__(self, name="MultiStarnet"):

        GafferDispatch.TaskNode.__init__(self, name)

        self["fileName"] = Gaffer.StringPlug(defaultValue='${channel}.tif', )

        self["in"] = GafferImage.ImagePlug("in")

        scale = GafferAstro.Scale()
        self["__Scale"] = scale
        scale["in"].setInput(self["in"])

        starnet = GafferAstro.Starnet()
        self["__Starnet"] = starnet
        starnet["in"].setInput(scale["out"])
        starnet["fileName"].setInput(self["fileName"])
        Gaffer.PlugAlgo.promote(starnet["dataType"])

        resize = GafferImage.Resize()
        self["__Resize"] = resize
        resize["in"].setInput(starnet["out"])

        scaleExpression = Gaffer.Expression()
        self["__ScaleExpression"] = scaleExpression
        scaleExpression.setExpression(
            inspect.cleandoc("""
				import GafferImage
				enabled = parent["__Scale"]["factor"] != 1
				parent["__Scale"]["enabled"] = enabled
				inFormat = parent["__Scale"]["in"]["format"]
				parent["__Resize"]["format"] = GafferImage.Format( inFormat.width(), inFormat.height(), 1.000 )
				parent["__Resize"]["enabled"] = enabled
			"""), "python")

        spreadsheet = Gaffer.Spreadsheet()
        self["__Spreadsheet"] = spreadsheet
        spreadsheet["selector"].setValue("${channel}")
        Gaffer.Metadata.registerValue(spreadsheet["rows"],
                                      "spreadsheet:defaultRowVisible",
                                      False,
                                      persistent=False)
        Gaffer.Metadata.registerValue(spreadsheet["rows"],
                                      "spreadsheet:columnsNeedSerialisation",
                                      False,
                                      persistent=False)

        spreadsheet["rows"].addColumn(Gaffer.StringPlug("source"), "source")
        starnet["channels"].setInput(spreadsheet["out"]["source"])
        Gaffer.Metadata.registerValue(
            spreadsheet["rows"].defaultRow()["cells"]["source"]["value"],
            "plugValueWidget:type",
            "GafferUI.PresetsPlugValueWidget",
            persistent=False)
        Gaffer.Metadata.registerValue(
            spreadsheet["rows"].defaultRow()["cells"]["source"]["value"],
            "presetsPlugValueWidget:allowCustom",
            True,
            persistent=False)
        Gaffer.Metadata.registerValue(
            MultiStarnet, "rows.*.cells.source.value", "presetNames",
            lambda plug: IECore.StringVectorData(_channelNames(plug)))
        Gaffer.Metadata.registerValue(
            MultiStarnet, "rows.*.cells.source.value", "presetValues",
            lambda plug: IECore.StringVectorData(_channelNames(plug)))

        spreadsheet["rows"].addColumn(
            Gaffer.FloatPlug("scale", minValue=0, defaultValue=1), "scale")
        scale["factor"].setInput(spreadsheet["out"]["scale"])

        promotedRowsPlug = Gaffer.PlugAlgo.promote(spreadsheet["rows"])
        Gaffer.Metadata.registerValue(promotedRowsPlug,
                                      "spreadsheet:columnsNeedSerialisation",
                                      False,
                                      persistent=False)

        wedge = GafferDispatch.Wedge()
        self["__Wedge"] = wedge
        wedge["variable"].setValue("channel")
        wedge["mode"].setValue(5)
        wedge["strings"].setInput(spreadsheet["activeRowNames"])
        wedge["preTasks"]["preTask0"].setInput(starnet["task"])

        collect = GafferAstro.CollectChannels()
        self["__Collect"] = collect
        collect["in"].setInput(resize["out"])
        collect["channelVariable"].setValue("channel")
        collect["channels"].setInput(spreadsheet["activeRowNames"])

        copy = GafferImage.CopyChannels()
        self["__Copy"] = copy
        copy["channels"].setValue("*")
        copy["in"][0].setInput(self["in"])
        copy["in"][1].setInput(collect["out"])

        self["out"] = GafferImage.ImagePlug(
            direction=Gaffer.Plug.Direction.Out)
        self["out"].setInput(copy["out"])

        self["task"].setInput(wedge["task"])
    def __init__(self, name="MultiPixInsight"):

        GafferDispatch.TaskNode.__init__(self, name)

        self["fileName"] = Gaffer.StringPlug(defaultValue='${channel}.xisf', )

        self["in"] = GafferImage.ImagePlug("in")

        pixInsight = GafferAstro.PixInsight()
        self["__PixInsight"] = pixInsight
        pixInsight["in"].setInput(self["in"])
        pixInsight["fileName"].setInput(self["fileName"])
        Gaffer.PlugAlgo.promote(pixInsight["dataType"])

        spreadsheet = Gaffer.Spreadsheet()
        self["__Spreadsheet"] = spreadsheet
        spreadsheet["selector"].setValue("${channel}")

        Gaffer.Metadata.registerValue(spreadsheet["rows"],
                                      "spreadsheet:columnsNeedSerialisation",
                                      False,
                                      persistent=False)

        spreadsheet["rows"].addColumn(Gaffer.StringPlug("source"), "source")
        pixInsight["channels"].setInput(spreadsheet["out"]["source"])
        Gaffer.Metadata.registerValue(
            spreadsheet["rows"].defaultRow()["cells"]["source"]["value"],
            "plugValueWidget:type",
            "GafferUI.PresetsPlugValueWidget",
            persistent=False)
        Gaffer.Metadata.registerValue(
            spreadsheet["rows"].defaultRow()["cells"]["source"]["value"],
            "presetsPlugValueWidget:allowCustom",
            True,
            persistent=False)
        Gaffer.Metadata.registerValue(
            MultiPixInsight, "rows.*.cells.source.value", "presetNames",
            lambda plug: IECore.StringVectorData(_channelNames(plug)))
        Gaffer.Metadata.registerValue(
            MultiPixInsight, "rows.*.cells.source.value", "presetValues",
            lambda plug: IECore.StringVectorData(_channelNames(plug)))

        spreadsheet["rows"].addColumn(pixInsight["pixScript"])
        Gaffer.MetadataAlgo.copy(
            pixInsight["pixScript"],
            spreadsheet["rows"].defaultRow()["cells"]["pixScript"]["value"],
            exclude="spreadsheet:columnName layout:* deletable")

        pixInsight["pixScript"].setInput(spreadsheet["out"]["pixScript"])

        promotedRowsPlug = Gaffer.PlugAlgo.promote(spreadsheet["rows"])
        Gaffer.Metadata.registerValue(promotedRowsPlug,
                                      "spreadsheet:columnsNeedSerialisation",
                                      False,
                                      persistent=False)

        Gaffer.PlugAlgo.promote(pixInsight["variables"])

        wedge = GafferDispatch.Wedge()
        self["__Wedge"] = wedge
        wedge["variable"].setValue("channel")
        wedge["mode"].setValue(5)
        wedge["strings"].setInput(spreadsheet["activeRowNames"])
        wedge["preTasks"]["preTask0"].setInput(pixInsight["task"])

        collect = GafferAstro.CollectChannels()
        self["__Collect"] = collect
        collect["in"].setInput(pixInsight["out"])
        collect["channelVariable"].setValue("channel")
        collect["channels"].setInput(spreadsheet["activeRowNames"])

        copy = GafferImage.CopyChannels()
        self["__Copy"] = copy
        copy["channels"].setValue("*")
        copy["in"][0].setInput(self["in"])
        copy["in"][1].setInput(collect["out"])

        self["out"] = GafferImage.ImagePlug(
            direction=Gaffer.Plug.Direction.Out)
        self["out"].setInput(copy["out"])

        self["task"].setInput(wedge["task"])