public class KeyPointGroundTruthTests : GroundTruthTestBase , IPrebuildSetup , IPostBuildCleanup
{
private const string kAnimatedCubeScenePath = "Packages/com.unity.perception/Tests/Runtime/TestAssets/AnimatedCubeScene.unity" ;
private const string kCubeScenePath = "Packages/com.unity.perception/Tests/Runtime/TestAssets/CubeScene.unity" ;
private const double k_Delta = . 0 1 ;
public void Setup ( )
scenes . Add ( new UnityEditor . EditorBuildSettingsScene ( kAnimatedCubeScenePath , true ) ) ;
scenes . Add ( new UnityEditor . EditorBuildSettingsScene ( kCubeScenePath , true ) ) ;
UnityEditor . EditorBuildSettings . scenes = scenes . ToArray ( ) ;
#endif
}
#if UNITY_EDITOR
var scenes = UnityEditor . EditorBuildSettings . scenes ;
scenes = scenes . Where ( s = > s . path ! = kAnimatedCubeScenePath ) . ToArray ( ) ;
scenes = scenes . Where ( s = > s . path ! = kAnimatedCubeScenePath & & s . path ! = kCubeScenePath ) . ToArray ( ) ;
[UnitySetUp]
public IEnumerator SetupTest ( )
{
foreach ( var p in LoadCubeScene ( ) ) yield return p ;
}
static GameObject SetupCamera ( IdLabelConfig config , KeypointTemplate template , Action < int , List < KeypointLabeler . KeypointEntry > > computeListener , RenderTexture renderTexture = null , KeypointObjectFilter keypointObjectFilter = KeypointObjectFilter . Visible )
{
var cameraObject = new GameObject ( ) ;
return cameraObject ;
}
static KeypointTemplate CreateTestTemplate ( Guid guid , string label )
static KeypointTemplate CreateTestTemplate ( Guid guid , string label , float selfOcclusionDistance = 0.15f )
{
var keypoints = new [ ]
{
associateToRig = false ,
color = Color . black
color = Color . black ,
selfOcclusionDistance = selfOcclusionDistance
color = Color . black
color = Color . black ,
selfOcclusionDistance = selfOcclusionDistance
color = Color . black
color = Color . black ,
selfOcclusionDistance = selfOcclusionDistance
color = Color . black
color = Color . black ,
selfOcclusionDistance = selfOcclusionDistance
color = Color . black
color = Color . black ,
selfOcclusionDistance = selfOcclusionDistance
color = Color . black
color = Color . black ,
selfOcclusionDistance = selfOcclusionDistance
color = Color . black
color = Color . black ,
selfOcclusionDistance = selfOcclusionDistance
color = Color . black
color = Color . black ,
selfOcclusionDistance = selfOcclusionDistance
color = Color . black
color = Color . black ,
selfOcclusionDistance = selfOcclusionDistance
}
} ;
return cfg ;
}
static void SetupCubeJoint ( GameObject cube , KeypointTemplate template , string label , float x , float y , float z )
static void SetupCubeJoint ( GameObject cube , string label , float x , float y , float z , float? selfOcclusionDistance = null )
joint . transform . parent = cube . transform ;
joint . transform . SetParent ( cube . transform , false ) ;
jointLabel . templateInformation = new List < JointLabel . TemplateData > ( ) ;
var templateData = new JointLabel . TemplateData
jointLabel . labels . Add ( label ) ;
if ( selfOcclusionDistance . HasValue )
template = template ,
label = label
} ;
jointLabel . templateInformation . Add ( templateData ) ;
jointLabel . overrideSelfOcclusionDistance = true ;
jointLabel . selfOcclusionDistance = selfOcclusionDistance . Value ;
}
else
jointLabel . overrideSelfOcclusionDistance = false ;
static void SetupCubeJoints ( GameObject cube , KeypointTemplate template )
static void SetupCubeJoints ( GameObject cube , KeypointTemplate template , float? selfOcclusionDistance = null )
SetupCubeJoint ( cube , template , "FrontLowerLeft" , - dim , - dim , - dim ) ;
SetupCubeJoint ( cube , template , "FrontUpperLeft" , - dim , dim , - dim ) ;
SetupCubeJoint ( cube , template , "FrontUpperRight" , dim , dim , - dim ) ;
SetupCubeJoint ( cube , template , "FrontLowerRight" , dim , - dim , - dim ) ;
SetupCubeJoint ( cube , template , "BackLowerLeft" , - dim , - dim , dim ) ;
SetupCubeJoint ( cube , template , "BackUpperLeft" , - dim , dim , dim ) ;
SetupCubeJoint ( cube , template , "BackUpperRight" , dim , dim , dim ) ;
SetupCubeJoint ( cube , template , "BackLowerRight" , dim , - dim , dim ) ;
SetupCubeJoint ( cube , "FrontLowerLeft" , - dim , - dim , - dim , selfOcclusionDistance ) ;
SetupCubeJoint ( cube , "FrontUpperLeft" , - dim , dim , - dim , selfOcclusionDistance ) ;
SetupCubeJoint ( cube , "FrontUpperRight" , dim , dim , - dim , selfOcclusionDistance ) ;
SetupCubeJoint ( cube , "FrontLowerRight" , dim , - dim , - dim , selfOcclusionDistance ) ;
SetupCubeJoint ( cube , "BackLowerLeft" , - dim , - dim , dim , selfOcclusionDistance ) ;
SetupCubeJoint ( cube , "BackUpperLeft" , - dim , dim , dim , selfOcclusionDistance ) ;
SetupCubeJoint ( cube , "BackUpperRight" , dim , dim , dim , selfOcclusionDistance ) ;
SetupCubeJoint ( cube , "BackLowerRight" , dim , - dim , dim , selfOcclusionDistance ) ;
}
[UnityTest]
incoming . Add ( new List < KeypointLabeler . KeypointEntry > ( data ) ) ;
} , texture ) ;
var cube = TestHelper . Create LabeledCube( scale : 6 , z : 8 ) ;
var cube = Setup LabeledCube( scale : 6 , z : 8 ) ;
SetupCubeJoints ( cube , template ) ;
cube . SetActive ( true ) ;
Assert . AreEqual ( t . keypoints [ 5 ] . y , t . keypoints [ 6 ] . y ) ;
for ( var i = 0 ; i < 9 ; i + + ) Assert . AreEqual ( i , t . keypoints [ i ] . index ) ;
for ( var i = 0 ; i < 8 ; i + + ) Assert . AreEqual ( 2 , t . keypoints [ i ] . state ) ;
for ( var i = 0 ; i < 4 ; i + + ) Assert . AreEqual ( 2 , t . keypoints [ i ] . state ) ;
for ( var i = 4 ; i < 8 ; i + + ) Assert . AreEqual ( 1 , t . keypoints [ i ] . state ) ;
Assert . Zero ( t . keypoints [ 8 ] . state ) ;
Assert . Zero ( t . keypoints [ 8 ] . x ) ;
Assert . Zero ( t . keypoints [ 8 ] . y ) ;
incoming . Add ( new List < KeypointLabeler . KeypointEntry > ( data ) ) ;
} , texture ) ;
var cube = TestHelper . Create LabeledCube( scale : 6 , z : 8 ) ;
var cube = Setup LabeledCube( scale : 6 , z : 8 ) ;
SetupCubeJoints ( cube , template ) ;
var labeling = cube . GetComponent < Labeling > ( ) ;
Assert . AreEqual ( t . keypoints [ 5 ] . y , t . keypoints [ 6 ] . y ) ;
for ( var i = 0 ; i < 9 ; i + + ) Assert . AreEqual ( i , t . keypoints [ i ] . index ) ;
for ( var i = 0 ; i < 8 ; i + + ) Assert . AreEqual ( 2 , t . keypoints [ i ] . state ) ;
for ( var i = 0 ; i < 4 ; i + + ) Assert . AreEqual ( 2 , t . keypoints [ i ] . state ) ;
for ( var i = 4 ; i < 8 ; i + + ) Assert . AreEqual ( 1 , t . keypoints [ i ] . state ) ;
Assert . Zero ( t . keypoints [ 8 ] . state ) ;
Assert . Zero ( t . keypoints [ 8 ] . x ) ;
Assert . Zero ( t . keypoints [ 8 ] . y ) ;
incoming . Add ( new List < KeypointLabeler . KeypointEntry > ( data ) ) ;
} ) ;
var cube = TestHelper . Create LabeledCube( scale : 6 , z : 8 ) ;
var cube = Setup LabeledCube( scale : 6 , z : 8 ) ;
SetupCubeJoints ( cube , template ) ;
cube . transform . position = new Vector3 ( - 1 0 0 0 , - 1 0 0 0 , 0 ) ;
} , texture ) ;
cam . GetComponent < PerceptionCamera > ( ) . showVisualizations = false ;
var cube = TestHelper . Create LabeledCube( scale : 6 , z : 8 ) ;
SetupCubeJoint ( cube , template , "Center" , 0 , 0 , 0 ) ;
var cube = Setup LabeledCube( scale : 6 , z : 8 ) ;
SetupCubeJoint ( cube , "Center" , 0 , 0 , - . 5f ) ;
cube . SetActive ( true ) ;
cam . SetActive ( true ) ;
var testCase2 = incoming [ 1 ] ;
Assert . AreEqual ( 1 , testCase2 . Count ) ;
var t2 = testCase2 . First ( ) ;
Assert . AreEqual ( 4 4 5 , t2 . keypoints [ 0 ] . x , 1 ) ;
Assert . AreEqual ( 4 1 6 , t2 . keypoints [ 0 ] . x , 1 ) ;
Assert . AreEqual ( 7 6 8 / 2 , t2 . keypoints [ 0 ] . y ) ;
}
incoming . Add ( new List < KeypointLabeler . KeypointEntry > ( data ) ) ;
} , texture ) ;
var cube = TestHelper . Create LabeledCube( scale : 6 , z : 8 ) ;
var cube = Setup LabeledCube( scale : 6 , z : 8 ) ;
SetupCubeJoints ( cube , template ) ;
cube . transform . position + = Vector3 . right * 1 3.5f ;
incoming . Add ( new List < KeypointLabeler . KeypointEntry > ( data ) ) ;
} , texture ) ;
var cube = TestHelper . Create LabeledCube( scale : 6 , z : 8 ) ;
var cube = Setup LabeledCube( scale : 6 , z : 8 ) ;
SetupCubeJoints ( cube , template ) ;
cube . SetActive ( true ) ;
AddTestObjectForCleanup ( cube ) ;
//for (int i = 0; i < 10000; i++)
yield return null ;
//force all async readbacks to complete
Assert . AreEqual ( t . keypoints [ 5 ] . y , t . keypoints [ 6 ] . y ) ;
for ( var i = 0 ; i < 9 ; i + + ) Assert . AreEqual ( i , t . keypoints [ i ] . index ) ;
for ( var i = 0 ; i < 8 ; i + + ) Assert . AreEqual ( 2 , t . keypoints [ i ] . state ) ;
for ( var i = 0 ; i < 4 ; i + + ) Assert . AreEqual ( 2 , t . keypoints [ i ] . state ) ;
for ( var i = 4 ; i < 8 ; i + + ) Assert . AreEqual ( 1 , t . keypoints [ i ] . state ) ;
Assert . Zero ( t . keypoints [ 8 ] . state ) ;
Assert . Zero ( t . keypoints [ 8 ] . x ) ;
Assert . Zero ( t . keypoints [ 8 ] . y ) ;
private void CreateFullyOccludedScene ( KeypointTemplate template , GameObject cam )
{
var cube = TestHelper . Create LabeledCube( scale : 6 , z : 8 ) ;
var cube = Setup LabeledCube( scale : 6 , z : 8 ) ;
SetupCubeJoints ( cube , template ) ;
var blocker = GameObject . CreatePrimitive ( PrimitiveType . Cube ) ;
incoming . Add ( data ) ;
} , texture , keypointObjectFilter ) ;
var cube = TestHelper . Create LabeledCube( scale : 6 , z : - 1 0 0 ) ;
var cube = Setup LabeledCube( scale : 6 , z : - 1 0 0 ) ;
SetupCubeJoints ( cube , template ) ;
cube . SetActive ( true ) ;
incoming . Add ( data ) ;
} , texture , KeypointObjectFilter . All ) ;
var cube = TestHelper . Create LabeledCube( scale : 6 , z : - 2 0 ) ;
var cube = Setup LabeledCube( scale : 6 , z : - 2 0 ) ;
SetupCubeJoints ( cube , template ) ;
cube . SetActive ( true ) ;
incoming . Add ( new List < KeypointLabeler . KeypointEntry > ( data ) ) ;
} , texture ) ;
var cube = TestHelper . Create LabeledCube( scale : 6 , z : 8 ) ;
var cube = Setup LabeledCube( scale : 6 , z : 8 ) ;
SetupCubeJoints ( cube , template ) ;
var blocker = GameObject . CreatePrimitive ( PrimitiveType . Cube ) ;
Assert . AreEqual ( 2 , t . keypoints [ 0 ] . state ) ;
Assert . AreEqual ( 2 , t . keypoints [ 1 ] . state ) ;
Assert . AreEqual ( 2 , t . keypoints [ 4 ] . state ) ;
Assert . AreEqual ( 2 , t . keypoints [ 5 ] . state ) ;
Assert . AreEqual ( 1 , t . keypoints [ 4 ] . state ) ;
Assert . AreEqual ( 1 , t . keypoints [ 5 ] . state ) ;
Assert . AreEqual ( 1 , t . keypoints [ 2 ] . state ) ;
Assert . AreEqual ( 1 , t . keypoints [ 3 ] . state ) ;
var labeling = cube . AddComponent < Labeling > ( ) ;
labeling . labels . Add ( "label" ) ;
SetupCubeJoint ( cube , template , "Center" , 0f , 0f , 0 f) ;
SetupCubeJoint ( cube , "Center" , 0f , 0f , - . 5 f) ;
cube . SetActive ( true ) ;
cam . SetActive ( true ) ;
Assert . AreEqual ( 2 , t . keypoints [ 8 ] . state ) ;
}
static IEnumerable < ( float scale , bool expectObject , int expectedState , KeypointObjectFilter keypointFilter , Vector2 expectedTopLeft , Vector2 expectedBottomRight ) > Keypoint_OnBox_ReportsProperCoordinates_TestCases ( )
static IEnumerable < ( float scale , bool expectObject , int expectedStateFront , int expectedStateBack , KeypointObjectFilter keypointFilter , Vector2 expectedTopLeft , Vector2 expectedBottomRight ) > Keypoint_OnBox_ReportsProperCoordinates_TestCases ( )
1 ,
KeypointObjectFilter . Visible ,
new Vector2 ( 0 , 0 ) ,
new Vector2 ( 1 0 2 3.99f , 1 0 2 3.99f ) ) ;
0 ,
0 ,
KeypointObjectFilter . Visible ,
new Vector2 ( 0 , 0 ) ,
true ,
0 ,
0 ,
KeypointObjectFilter . Visible ,
new Vector2 ( 0 , 0 ) ,
new Vector2 ( 0 , 0 ) ) ;
1 ,
1 ,
KeypointObjectFilter . Visible ,
new Vector2 ( 5 1 2 , 5 1 2 ) ,
true ,
1 ,
1 ,
KeypointObjectFilter . VisibleAndOccluded ,
new Vector2 ( 5 1 2 , 5 1 2 ) ,
new Vector2 ( 5 1 2 , 5 1 2 ) ) ;
[ValueSource(nameof(Keypoint_OnBox_ReportsProperCoordinates_TestCases))]
( float scale , bool expectObject , int expectedState , KeypointObjectFilter keypointFilter , Vector2 expectedTopLeft , Vector2 expectedBottomRight ) args )
( float scale , bool expectObject , int expectedStateFront , int expectedStateBack , KeypointObjectFilter keypointFilter , Vector2 expectedTopLeft , Vector2 expectedBottomRight ) args )
{
var incoming = new List < List < KeypointLabeler . KeypointEntry > > ( ) ;
var template = CreateTestTemplate ( Guid . NewGuid ( ) , "TestTemplate" ) ;
camComponent . orthographic = true ;
camComponent . orthographicSize = . 5f ;
var cube = TestHelper . CreateLabeledCube ( scale : args . scale , z : 8 ) ;
//For some reason the back of this cube is being resolved to 7.5 away from the camera, but on the CPU side it is being recorded as 18.34375
var cube = SetupLabeledCube ( scale : args . scale , z : 0 ) ;
SetupCubeJoints ( cube , template ) ;
cube . SetActive ( true ) ;
AddTestObjectForCleanup ( cube ) ;
//for (int i = 0; i < 10000; i++)
yield return null ;
//force all async readbacks to complete
Assert . AreEqual ( template . templateID . ToString ( ) , t . template_guid ) ;
Assert . AreEqual ( 9 , t . keypoints . Length ) ;
CollectionAssert . AreEqual ( Enumerable . Repeat ( args . expectedState , 8 ) , t . keypoints . Take ( 8 ) . Select ( k = > k . state ) , "State mismatch" ) ;
CollectionAssert . AreEqual ( Enumerable . Repeat ( args . expectedStateFront , 4 ) ,
t . keypoints . Take ( 4 ) . Select ( k = > k . state ) ,
"State mismatch on front" ) ;
CollectionAssert . AreEqual ( Enumerable . Repeat ( args . expectedStateBack , 4 ) ,
t . keypoints . Skip ( 4 ) . Take ( 4 ) . Select ( k = > k . state ) ,
"State mismatch on front" ) ;
Assert . AreEqual ( args . expectedTopLeft . x , t . keypoints [ 0 ] . x , k_Delta ) ;
Assert . AreEqual ( args . expectedBottomRight . y , t . keypoints [ 0 ] . y , k_Delta ) ;
Assert . AreEqual ( args . expectedBottomRight . x , t . keypoints [ 3 ] . x , k_Delta ) ;
Assert . AreEqual ( args . expectedBottomRight . y , t . keypoints [ 3 ] . y , k_Delta ) ;
}
public enum CheckDistanceType
{
Global ,
JointLabel
}
public enum ProjectionKind
{
Orthographic ,
Projection
}
public static IEnumerable < ( CheckDistanceType checkDistanceType , Vector3 origin , Vector3 objectScale , Quaternion rotation ,
float checkDistance , float pointDistance , float cameraFieldOfView , bool expectOccluded ) >
Keypoint_InsideBox_RespectsThreshold_TestCases ( )
{
foreach ( var checkDistanceType in new [ ] { CheckDistanceType . Global , CheckDistanceType . JointLabel } )
{
yield return (
checkDistanceType ,
Vector3 . zero ,
Vector3 . one ,
Quaternion . identity ,
0.1f ,
0.2f ,
6 0f ,
true ) ;
yield return (
checkDistanceType ,
Vector3 . zero ,
Vector3 . one ,
Quaternion . identity ,
0.2f ,
0.005f ,
6 0f ,
false ) ;
yield return (
checkDistanceType ,
Vector3 . zero ,
Vector3 . one ,
Quaternion . identity ,
0.1f ,
0.05f ,
6 0f ,
false ) ;
yield return (
checkDistanceType ,
new Vector3 ( 0 , 0 , 8 8 ) ,
Vector3 . one ,
Quaternion . identity ,
0.1f ,
0.05f ,
1f ,
false ) ;
//larger value here for the occluded check due to lack of depth precision close to far plane.
//We choose to mark points not occluded when the point depth and geometry depth are the same in the depth buffer
yield return (
checkDistanceType ,
new Vector3 ( 0 , 0 , 8 8 ) ,
Vector3 . one ,
Quaternion . identity ,
1f ,
2f ,
1f ,
true ) ;
}
yield return (
CheckDistanceType . Global ,
Vector3 . zero ,
Vector3 . one * . 5f ,
Quaternion . identity ,
0.2f ,
0.3f ,
6 0f ,
true ) ;
yield return (
CheckDistanceType . Global ,
Vector3 . zero ,
new Vector3 ( 1f , 1f , . 5f ) ,
Quaternion . identity ,
0.2f ,
0.3f ,
6 0f ,
true ) ;
yield return (
CheckDistanceType . JointLabel ,
Vector3 . zero ,
new Vector3 ( 1f , 1f , . 5f ) ,
Quaternion . identity ,
0.2f ,
0.3f ,
6 0f ,
true ) ;
yield return (
CheckDistanceType . JointLabel ,
Vector3 . zero ,
Vector3 . one * . 5f ,
Quaternion . identity ,
0.2f ,
0.3f ,
6 0f ,
true ) ;
yield return (
CheckDistanceType . JointLabel ,
Vector3 . zero ,
new Vector3 ( 1f , 1f , . 0 5f ) ,
Quaternion . AngleAxis ( 4 5 , Vector3 . right ) ,
0.2f ,
0.21f ,
6 0f ,
true ) ;
}
[UnityTest]
public IEnumerator Keypoint_InsideBox_RespectsThreshold (
[ValueSource(nameof(Keypoint_InsideBox_RespectsThreshold_TestCases))]
( CheckDistanceType checkDistanceType , Vector3 origin , Vector3 objectScale , Quaternion rotation ,
float checkDistance , float pointDistance , float cameraFieldOfView , bool expectOccluded ) args ,
[Values(ProjectionKind.Orthographic, ProjectionKind.Projection)] ProjectionKind projectionKind )
{
var incoming = new List < List < KeypointLabeler . KeypointEntry > > ( ) ;
var labelerSelfOcclusionDistance =
args . checkDistanceType = = CheckDistanceType . Global ? args . checkDistance : 0.5f ;
var template = CreateTestTemplate ( Guid . NewGuid ( ) , "TestTemplate" , selfOcclusionDistance : labelerSelfOcclusionDistance ) ;
var frameSize = 1 0 2 4 ;
var texture = new RenderTexture ( frameSize , frameSize , 1 6 ) ;
var cam = SetupCamera ( SetUpLabelConfig ( ) , template , ( frame , data ) = >
{
incoming . Add ( data ) ;
} , texture ) ;
var camComponent = cam . GetComponent < Camera > ( ) ;
camComponent . fieldOfView = args . cameraFieldOfView ;
camComponent . farClipPlane = 1 0 0f ;
if ( projectionKind = = ProjectionKind . Orthographic )
{
camComponent . orthographic = true ;
camComponent . orthographicSize = . 5f ;
}
var cube = GameObject . Find ( "Cube" ) ;
TestHelper . SetupLabeledCube ( cube , scale : 1f , x : args . origin . x , y : args . origin . y , z : args . origin . z ) ;
cube . transform . localScale = args . objectScale ;
cube . transform . localRotation = args . rotation ;
var localSelfOcclusionDistance = args . checkDistanceType = = CheckDistanceType . JointLabel ? ( float? ) args . checkDistance : null ;
SetupCubeJoint ( cube , "Center" , 0f , 0f , - . 5f + args . pointDistance , localSelfOcclusionDistance ) ;
cube . SetActive ( true ) ;
cam . SetActive ( true ) ;
AddTestObjectForCleanup ( cam ) ;
AddTestObjectForCleanup ( cube ) ;
//for (int i = 0; i < 10000; i++)
yield return null ;
//force all async readbacks to complete
DestroyTestObject ( cam ) ;
texture . Release ( ) ;
var testCase = incoming . Last ( ) ;
Assert . AreEqual ( 1 , testCase . Count ) ;
var t = testCase . First ( ) ;
Assert . AreEqual ( args . expectOccluded ? 1 : 2 , t . keypoints [ 8 ] . state ) ;
}
private IEnumerable LoadCubeScene ( )
{
SceneManager . LoadScene ( "CubeScene" , LoadSceneMode . Additive ) ;
AddSceneForCleanup ( "CubeScene" ) ;
yield return null ;
}
public static IEnumerable < ( Vector3 objectScale , Quaternion rotation , float checkDistance , Vector3 pointLocalPosition , bool expectOccluded ) >
Keypoint_OnCorner_OfRotatedScaledBox_RespectsThreshold_TestCases ( )
{
yield return (
new Vector3 ( 9 0f , 9 0f , 1 0f ) ,
Quaternion . identity ,
. 1 1f ,
new Vector3 ( - . 4f , - . 4f , - . 4f ) ,
false ) ;
yield return (
new Vector3 ( 9 0f , 9 0f , 1f ) ,
Quaternion . identity ,
. 5f ,
new Vector3 ( - . 4f , - . 4f , . 4f ) ,
true ) ;
yield return (
new Vector3 ( 9 0 , 9 0 , 9 ) ,
Quaternion . AngleAxis ( 9 0 , Vector3 . right ) ,
. 1 1f ,
new Vector3 ( - . 4f , - . 4f , - . 4f ) ,
false ) ;
yield return (
new Vector3 ( 9 0 , 9 0 , 9 0 ) ,
Quaternion . AngleAxis ( 9 0 , Vector3 . right ) ,
. 1 1f ,
new Vector3 ( - . 4f , - . 4f , - . 4f ) ,
false ) ;
yield return (
new Vector3 ( 9 0 , 6 0 , 9 0 ) ,
Quaternion . AngleAxis ( 4 5 , Vector3 . right ) ,
. 1 1f ,
new Vector3 ( - . 4f , - . 4f , - . 4f ) ,
true ) ;
}
[UnityTest]
public IEnumerator Keypoint_OnCorner_OfRotatedScaledBox_RespectsThreshold (
[ValueSource(nameof(Keypoint_OnCorner_OfRotatedScaledBox_RespectsThreshold_TestCases))]
( Vector3 objectScale , Quaternion rotation , float checkDistance , Vector3 pointLocalPosition , bool expectOccluded ) args )
{
var incoming = new List < List < KeypointLabeler . KeypointEntry > > ( ) ;
var labelerSelfOcclusionDistance = 0.5f ;
var template = CreateTestTemplate ( Guid . NewGuid ( ) , "TestTemplate" , labelerSelfOcclusionDistance ) ;
var frameSize = 1 0 2 4 ;
var texture = new RenderTexture ( frameSize , frameSize , 1 6 ) ;
var cam = SetupCamera ( SetUpLabelConfig ( ) , template , ( frame , data ) = >
{
incoming . Add ( data ) ;
} , texture ) ;
var camComponent = cam . GetComponent < Camera > ( ) ;
camComponent . orthographic = true ;
camComponent . orthographicSize = 1 0 0f ;
cam . transform . localPosition = new Vector3 ( 0 , 0 , - 9 5f ) ;
var cube = GameObject . Find ( "Cube" ) ;
TestHelper . SetupLabeledCube ( cube , scale : 1f ) ;
cube . transform . localScale = args . objectScale ;
cube . transform . localRotation = args . rotation ;
SetupCubeJoint ( cube , "Center" , args . pointLocalPosition . x , args . pointLocalPosition . y , args . pointLocalPosition . z , args . checkDistance ) ;
cube . SetActive ( true ) ;
cam . SetActive ( true ) ;
AddTestObjectForCleanup ( cam ) ;
AddTestObjectForCleanup ( cube ) ;
//for (int i = 0; i < 10000; i++)
yield return null ;
//force all async readbacks to complete
DestroyTestObject ( cam ) ;
texture . Release ( ) ;
var testCase = incoming . Last ( ) ;
Assert . AreEqual ( 1 , testCase . Count ) ;
var t = testCase . First ( ) ;
Assert . AreEqual ( args . expectOccluded ? 1 : 2 , t . keypoints [ 8 ] . state ) ;
}
public static IEnumerable < ( Vector3 objectScale , Quaternion rotation , float checkDistance , Vector3 pointLocalPosition , float overrideScalar , bool expectOccluded ) >
Keypoint_OnCorner_OfRotatedScaledBox_RespectsModelOverrideThreshold_TestCases ( )
{
yield return (
new Vector3 ( 9 0f , 9 0f , 1 0f ) ,
Quaternion . identity ,
. 1 1f ,
new Vector3 ( - . 4f , - . 4f , - . 4f ) ,
1f ,
false ) ;
yield return (
new Vector3 ( 9 0f , 9 0f , 1f ) ,
Quaternion . identity ,
. 5f ,
new Vector3 ( - . 4f , - . 4f , . 4f ) ,
. 5f ,
true ) ;
yield return (
new Vector3 ( 9 0 , 9 0 , 9 ) ,
Quaternion . AngleAxis ( 9 0 , Vector3 . right ) ,
. 1 1f ,
new Vector3 ( - . 4f , - . 4f , - . 4f ) ,
1f ,
false ) ;
yield return (
new Vector3 ( 9 0 , 9 0 , 9 0 ) ,
Quaternion . AngleAxis ( 9 0 , Vector3 . right ) ,
. 1 1f ,
new Vector3 ( - . 4f , - . 4f , - . 4f ) ,
. 5f ,
true ) ;
yield return (
new Vector3 ( 9 0 , 9 0 , 9 0 ) ,
Quaternion . AngleAxis ( 9 0 , Vector3 . right ) ,
. 0 5 5f ,
new Vector3 ( - . 4f , - . 4f , - . 4f ) ,
1f ,
true ) ;
yield return (
new Vector3 ( 9 0 , 9 0 , 9 0 ) ,
Quaternion . AngleAxis ( 9 0 , Vector3 . right ) ,
. 0 5 5f ,
new Vector3 ( - . 4f , - . 4f , - . 4f ) ,
2f ,
false ) ;
}
[UnityTest]
public IEnumerator Keypoint_OnCorner_OfRotatedScaledBox_RespectsModelOverrideThreshold (
[ValueSource(nameof(Keypoint_OnCorner_OfRotatedScaledBox_RespectsModelOverrideThreshold_TestCases))]
( Vector3 objectScale , Quaternion rotation , float checkDistance , Vector3 pointLocalPosition , float overrideScalar , bool expectOccluded ) args )
{
var incoming = new List < List < KeypointLabeler . KeypointEntry > > ( ) ;
var labelerSelfOcclusionDistance = 0.5f ;
var template = CreateTestTemplate ( Guid . NewGuid ( ) , "TestTemplate" , labelerSelfOcclusionDistance ) ;
var frameSize = 1 0 2 4 ;
var texture = new RenderTexture ( frameSize , frameSize , 1 6 ) ;
var cam = SetupCamera ( SetUpLabelConfig ( ) , template , ( frame , data ) = >
{
incoming . Add ( data ) ;
} , texture ) ;
var camComponent = cam . GetComponent < Camera > ( ) ;
camComponent . orthographic = true ;
camComponent . orthographicSize = 1 0 0f ;
cam . transform . localPosition = new Vector3 ( 0 , 0 , - 9 5f ) ;
var cube = SetupLabeledCube ( scale : 1f ) ;
cube . transform . localScale = args . objectScale ;
cube . transform . localRotation = args . rotation ;
SetupCubeJoint ( cube , "Center" , args . pointLocalPosition . x , args . pointLocalPosition . y , args . pointLocalPosition . z , args . checkDistance ) ;
var kpOc = cube . AddComponent < KeypointOcclusionOverrides > ( ) ;
kpOc . distanceScale = args . overrideScalar ;
cube . SetActive ( true ) ;
cam . SetActive ( true ) ;
AddTestObjectForCleanup ( cam ) ;
AddTestObjectForCleanup ( cube ) ;
//for (int i = 0; i < 10000; i++)
yield return null ;
//force all async readbacks to complete
DestroyTestObject ( cam ) ;
texture . Release ( ) ;
var testCase = incoming . Last ( ) ;
Assert . AreEqual ( 1 , testCase . Count ) ;
var t = testCase . First ( ) ;
Assert . AreEqual ( args . expectOccluded ? 1 : 2 , t . keypoints [ 8 ] . state ) ;
}
public static GameObject SetupLabeledCube ( float scale = 1 0 , string label = "label" , float x = 0 , float y = 0 ,
float z = 0 , float roll = 0 , float pitch = 0 , float yaw = 0 )
{
return TestHelper . SetupLabeledCube ( GameObject . Find ( "Cube" ) , scale , label , x , y , z , roll , pitch , yaw ) ;
}
[UnityTest]
public IEnumerator ManyObjects_LabelsCorrectly ( )
{
var incoming = new List < List < KeypointLabeler . KeypointEntry > > ( ) ;
var labelerSelfOcclusionDistance = 0.5f ;
var template = CreateTestTemplate ( Guid . NewGuid ( ) , "TestTemplate" , selfOcclusionDistance : labelerSelfOcclusionDistance ) ;
var frameSize = 1 0 2 4 ;
var texture = new RenderTexture ( frameSize , frameSize , 1 6 ) ;
var cam = SetupCamera ( SetUpLabelConfig ( ) , template , ( frame , data ) = >
{
incoming . Add ( new List < KeypointLabeler . KeypointEntry > ( data ) ) ;
} , texture ) ;
void PlaceObjects ( Rect rect , float z , Vector2Int count )
{
var cubeBase = GameObject . Find ( "Cube" ) ;
for ( int x = 0 ; x < count . x ; x + + )
{
for ( int y = 0 ; y < count . y ; y + + )
{
var cube = GameObject . Instantiate ( cubeBase ) ;
TestHelper . SetupLabeledCube (
cube ,
scale : rect . width / count . x - . 0 0 1f ,
x : rect . width / count . x * x + rect . xMin ,
y : rect . height / count . y * y + rect . yMin ,
z : z ) ;
SetupCubeJoints ( cube , template , . 1f ) ;
cube . SetActive ( true ) ;
AddTestObjectForCleanup ( cube ) ;
}
}
}
PlaceObjects ( new Rect ( - 2 , - 2 , 2 , 2 ) , 0 , new Vector2Int ( 1 0 , 1 0 ) ) ;
cam . SetActive ( true ) ;
AddTestObjectForCleanup ( cam ) ;
//TestHelper.LoadAndStartRenderDocCapture();
yield return null ;
PlaceObjects ( new Rect ( 0 , 0 , 4 , 4 ) , 0 , new Vector2Int ( 2 5 , 2 5 ) ) ;
yield return null ;
//force all async readbacks to complete
DestroyTestObject ( cam ) ;
texture . Release ( ) ;
//TestHelper.EndCaptureRenderDoc();
Assert . AreEqual ( 2 , incoming . Count ) ;
Assert . AreEqual ( 1 0 * 1 0 , incoming [ 0 ] . Count ) ;
Assert . AreEqual ( 1 0 * 1 0 + 2 5 * 2 5 , incoming [ 1 ] . Count ) ;
var idx = 0 ;
foreach ( var entry in incoming [ 0 ] . Concat ( incoming [ 1 ] ) )
{
Assert . AreEqual ( 9 , entry . keypoints . Length ) ;
CollectionAssert . AreEqual ( Enumerable . Repeat ( 2 , 4 ) ,
entry . keypoints . Take ( 4 ) . Select ( k = > k . state ) ,
$"State mismatch on front in entry {idx}" ) ;
CollectionAssert . AreEqual ( Enumerable . Repeat ( 1 , 4 ) ,
entry . keypoints . Skip ( 4 ) . Take ( 4 ) . Select ( k = > k . state ) ,
$"State mismatch on back in entry {idx}" ) ;
idx + + ;
}
}
}
}