numStackedVectorObservations: 1 | numStackedVectorObservations: 1 | ||||
vectorActionSize: 04000000 | vectorActionSize: 04000000 | ||||
cameraResolutions: | cameraResolutions: | ||||
- width: 320 | |||||
height: 120 | |||||
- width: 80 | |||||
height: 30 | |||||
blackAndWhite: 0 | blackAndWhite: 0 | ||||
vectorActionDescriptions: | vectorActionDescriptions: | ||||
- | - |
m_EditorClassIdentifier: | m_EditorClassIdentifier: | ||||
renderTextureCropped: {fileID: 8400000, guid: 8bf12f4401860c043a77209428e97b29, | renderTextureCropped: {fileID: 8400000, guid: 8bf12f4401860c043a77209428e97b29, | ||||
type: 2} | type: 2} | ||||
processedImageRenderer: {fileID: 1863707383} | |||||
processedImageRendererCropped: {fileID: 712179489} | processedImageRendererCropped: {fileID: 712179489} | ||||
--- !u!1 &918537782 | --- !u!1 &918537782 | ||||
GameObject: | GameObject: | ||||
- {fileID: 11400000, guid: 0d9d5ce547064a648b466ad7f208cf3d, type: 2} | - {fileID: 11400000, guid: 0d9d5ce547064a648b466ad7f208cf3d, type: 2} | ||||
maxSteps: 1000 | maxSteps: 1000 | ||||
trainingConfiguration: | trainingConfiguration: | ||||
width: 84 | |||||
height: 84 | |||||
width: 80 | |||||
height: 30 | |||||
qualityLevel: 1 | qualityLevel: 1 | ||||
timeScale: 10 | timeScale: 10 | ||||
targetFrameRate: -1 | targetFrameRate: -1 | ||||
inferenceConfiguration: | inferenceConfiguration: | ||||
width: 84 | |||||
height: 84 | |||||
width: 320 | |||||
height: 120 | |||||
qualityLevel: 5 | qualityLevel: 5 | ||||
timeScale: 1 | timeScale: 1 | ||||
targetFrameRate: 60 | targetFrameRate: 60 | ||||
m_PrefabAsset: {fileID: 0} | m_PrefabAsset: {fileID: 0} | ||||
m_GameObject: {fileID: 1863707380} | m_GameObject: {fileID: 1863707380} | ||||
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} | m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} | ||||
--- !u!1 &1957393249 | |||||
GameObject: | |||||
m_ObjectHideFlags: 0 | |||||
m_CorrespondingSourceObject: {fileID: 0} | |||||
m_PrefabInstance: {fileID: 0} | |||||
m_PrefabAsset: {fileID: 0} | |||||
serializedVersion: 6 | |||||
m_Component: | |||||
- component: {fileID: 1957393252} | |||||
- component: {fileID: 1957393251} | |||||
- component: {fileID: 1957393250} | |||||
m_Layer: 0 | |||||
m_Name: EventSystem | |||||
m_TagString: Untagged | |||||
m_Icon: {fileID: 0} | |||||
m_NavMeshLayer: 0 | |||||
m_StaticEditorFlags: 0 | |||||
m_IsActive: 1 | |||||
--- !u!114 &1957393250 | |||||
MonoBehaviour: | |||||
m_ObjectHideFlags: 0 | |||||
m_CorrespondingSourceObject: {fileID: 0} | |||||
m_PrefabInstance: {fileID: 0} | |||||
m_PrefabAsset: {fileID: 0} | |||||
m_GameObject: {fileID: 1957393249} | |||||
m_Enabled: 1 | |||||
m_EditorHideFlags: 0 | |||||
m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3} | |||||
m_Name: | |||||
m_EditorClassIdentifier: | |||||
m_HorizontalAxis: Horizontal | |||||
m_VerticalAxis: Vertical | |||||
m_SubmitButton: Submit | |||||
m_CancelButton: Cancel | |||||
m_InputActionsPerSecond: 10 | |||||
m_RepeatDelay: 0.5 | |||||
m_ForceModuleActive: 0 | |||||
--- !u!114 &1957393251 | |||||
MonoBehaviour: | |||||
m_ObjectHideFlags: 0 | |||||
m_CorrespondingSourceObject: {fileID: 0} | |||||
m_PrefabInstance: {fileID: 0} | |||||
m_PrefabAsset: {fileID: 0} | |||||
m_GameObject: {fileID: 1957393249} | |||||
m_Enabled: 1 | |||||
m_EditorHideFlags: 0 | |||||
m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} | |||||
m_Name: | |||||
m_EditorClassIdentifier: | |||||
m_FirstSelected: {fileID: 0} | |||||
m_sendNavigationEvents: 1 | |||||
m_DragThreshold: 10 | |||||
--- !u!4 &1957393252 | |||||
Transform: | |||||
m_ObjectHideFlags: 0 | |||||
m_CorrespondingSourceObject: {fileID: 0} | |||||
m_PrefabInstance: {fileID: 0} | |||||
m_PrefabAsset: {fileID: 0} | |||||
m_GameObject: {fileID: 1957393249} | |||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | |||||
m_LocalPosition: {x: 0, y: 0, z: 0} | |||||
m_LocalScale: {x: 1, y: 1, z: 1} | |||||
m_Children: [] | |||||
m_Father: {fileID: 0} | |||||
m_RootOrder: 5 | |||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | |||||
--- !u!1 &2078653367 | --- !u!1 &2078653367 | ||||
GameObject: | GameObject: | ||||
m_ObjectHideFlags: 0 | m_ObjectHideFlags: 0 | ||||
agentCameras: [] | agentCameras: [] | ||||
agentRenderTextures: | agentRenderTextures: | ||||
- {fileID: 8400000, guid: 8bf12f4401860c043a77209428e97b29, type: 2} | - {fileID: 8400000, guid: 8bf12f4401860c043a77209428e97b29, type: 2} | ||||
maxStep: 1000 | |||||
maxStep: 5000 | |||||
resetOnDone: 1 | resetOnDone: 1 | ||||
onDemandDecision: 1 | onDemandDecision: 1 | ||||
numberOfActionsBetweenDecisions: 1 | numberOfActionsBetweenDecisions: 1 |
public RenderTexture renderTextureCropped; | public RenderTexture renderTextureCropped; | ||||
[Header("Debug Helper")] | [Header("Debug Helper")] | ||||
//[Tooltip("Reference to the MeshRenderer that will show the processed Image from Cozmo")] | |||||
//public MeshRenderer processedImageRenderer; | |||||
[Tooltip("Reference to the MeshRenderer that will show the processed Image from Cozmo")] | |||||
public MeshRenderer processedImageRenderer; | |||||
[Tooltip("Reference to the MeshRenderer that will show the processed and cropped Image from Cozmo")] | [Tooltip("Reference to the MeshRenderer that will show the processed and cropped Image from Cozmo")] | ||||
public MeshRenderer processedImageRendererCropped; | public MeshRenderer processedImageRendererCropped; | ||||
private int croppedImHeight = 120; // Height of the cropped camera image from the virtual cozmo | private int croppedImHeight = 120; // Height of the cropped camera image from the virtual cozmo | ||||
private Camera textureCamera; // Virtual Cozmo camera | private Camera textureCamera; // Virtual Cozmo camera | ||||
private Texture2D firstTexture; | |||||
private void Start() | private void Start() | ||||
{ | { | ||||
// Get reference to the cozmo camera | // Get reference to the cozmo camera | ||||
// Set image widths and heights based on the given RenderTextures | // Set image widths and heights based on the given RenderTextures | ||||
imWidth = textureCamera.targetTexture.width; | imWidth = textureCamera.targetTexture.width; | ||||
imHeight = textureCamera.targetTexture.height; | imHeight = textureCamera.targetTexture.height; | ||||
croppedImHeight = renderTextureCropped.height; | |||||
//croppedImHeight = renderTextureCropped.height; | |||||
//assign the processed targetTexture to the renderer to display the image | //assign the processed targetTexture to the renderer to display the image | ||||
//processedImageRenderer.material.mainTexture = textureCamera.targetTexture; | |||||
processedImageRenderer.material.mainTexture = textureCamera.targetTexture; | |||||
processedImageRendererCropped.material.mainTexture = renderTextureCropped; | processedImageRendererCropped.material.mainTexture = renderTextureCropped; | ||||
// initialize video / image with given size | // initialize video / image with given size | ||||
videoSourceImageData = new Vec3b[imHeight * imWidth]; | videoSourceImageData = new Vec3b[imHeight * imWidth]; | ||||
cannyImage = new Mat(imHeight, imWidth, MatType.CV_8UC1); | cannyImage = new Mat(imHeight, imWidth, MatType.CV_8UC1); | ||||
cannyImageData = new byte[croppedImHeight * imWidth]; | cannyImageData = new byte[croppedImHeight * imWidth]; | ||||
firstTexture = new Texture2D(imWidth, imHeight, TextureFormat.RGBA32, true, true); | |||||
processedTexture = new Texture2D(imWidth, croppedImHeight, TextureFormat.RGBA32, true, true); | |||||
} | } | ||||
/// <summary> | |||||
/// Gets called when a new image arrives from the camera this script lies on | |||||
/// </summary> | |||||
/// <param name="source"></param> | |||||
/// <param name="destination"></param> | |||||
private void OnRenderImage(RenderTexture source, RenderTexture destination) | |||||
///// <summary> | |||||
///// Gets called when a new image arrives from the camera this script lies on | |||||
///// </summary> | |||||
///// <param name="source"></param> | |||||
///// <param name="destination"></param> | |||||
//private void OnRenderImage(RenderTexture source, RenderTexture destination) | |||||
//{ | |||||
// Texture2D tex = RenderTextureToTexture2D(source); | |||||
// videoSourceImage = TextureToMat(tex); | |||||
// cannyImage = ProcessImage(videoSourceImage); | |||||
// cannyImage = CropImage(cannyImage); | |||||
// CenterOfGravityTest(cannyImage); | |||||
// processedTexture = MatToTexture(cannyImage); | |||||
// //processedTexture.Resize(80, 30); | |||||
// //processedTexture.Apply(); | |||||
// //Graphics.Blit(processedTexture, destination); | |||||
// Graphics.Blit(processedTexture, renderTextureCropped); | |||||
//} | |||||
public void ProcessRenderTexture(RenderTexture source) | |||||
{ | |||||
ProcessRenderTexture(source, source); | |||||
} | |||||
public void ProcessRenderTexture(RenderTexture source, RenderTexture target) | |||||
{ | { | ||||
Texture2D tex = RenderTextureToTexture2D(source); | Texture2D tex = RenderTextureToTexture2D(source); | ||||
videoSourceImage = TextureToMat(tex); | videoSourceImage = TextureToMat(tex); | ||||
cannyImage = CropImage(cannyImage); | cannyImage = CropImage(cannyImage); | ||||
CenterOfGravityTest(cannyImage); | CenterOfGravityTest(cannyImage); | ||||
processedTexture = MatToTexture(cannyImage); | processedTexture = MatToTexture(cannyImage); | ||||
//processedTexture.Resize(80, 30); | |||||
//processedTexture.Apply(); | |||||
//Graphics.Blit(processedTexture, destination); | //Graphics.Blit(processedTexture, destination); | ||||
Graphics.Blit(processedTexture, target); | |||||
} | |||||
//public void ProcessRenderTexture_NEW(RenderTexture source, RenderTexture target) | |||||
//{ | |||||
// RenderTextureToTexture2D_NEW(source); | |||||
// TextureToMat_NEW(firstTexture); | |||||
// ProcessImage_NEW(videoSourceImage); | |||||
// cannyImage = CropImage(cannyImage); | |||||
// CenterOfGravityTest(cannyImage); | |||||
// MatToTexture_NEW(cannyImage); | |||||
// //processedTexture.Resize(80, 30); | |||||
// //processedTexture.Apply(); | |||||
// //Graphics.Blit(processedTexture, destination); | |||||
// Graphics.Blit(processedTexture, target); | |||||
//} | |||||
public void OnRenderImage(RenderTexture source, RenderTexture destination) | |||||
{ | |||||
RenderTextureToTexture2D_NEW(source); | |||||
TextureToMat_NEW(firstTexture); | |||||
ProcessImage_NEW(videoSourceImage); | |||||
cannyImage = CropImage(cannyImage); | |||||
CenterOfGravityTest(cannyImage); | |||||
MatToTexture_NEW(cannyImage); | |||||
Graphics.Blit(processedTexture, destination); | |||||
Graphics.Blit(processedTexture, renderTextureCropped); | Graphics.Blit(processedTexture, renderTextureCropped); | ||||
} | } | ||||
return croppedImage; | return croppedImage; | ||||
} | } | ||||
//// Crop image to just see the middle of the original image | |||||
//private Mat CropImage_NEW(Mat image) | |||||
//{ | |||||
// //cut a fourth out of the top and bottom of the image | |||||
// OpenCvSharp.Rect rectCroped = new OpenCvSharp.Rect(0, image.Height / 4, image.Width, image.Height / 2); | |||||
// Mat croppedImage = new Mat(image, rectCroped); | |||||
// return croppedImage; | |||||
//} | |||||
private Texture2D RenderTextureToTexture2D(RenderTexture rTex) | private Texture2D RenderTextureToTexture2D(RenderTexture rTex) | ||||
{ | { | ||||
Texture2D tex = new Texture2D(imWidth, imHeight, TextureFormat.RGBA32, true, true); | Texture2D tex = new Texture2D(imWidth, imHeight, TextureFormat.RGBA32, true, true); | ||||
return tex; | return tex; | ||||
} | } | ||||
private void RenderTextureToTexture2D_NEW(RenderTexture rTex) | |||||
{ | |||||
RenderTexture.active = rTex; | |||||
firstTexture.ReadPixels(new UnityEngine.Rect(0, 0, rTex.width, rTex.height), 0, 0); | |||||
firstTexture.Apply(); | |||||
} | |||||
// Convert Unity Texture2D object to OpenCVSharp Mat object | // Convert Unity Texture2D object to OpenCVSharp Mat object | ||||
private Mat TextureToMat(Texture2D source) | private Mat TextureToMat(Texture2D source) | ||||
{ | { | ||||
return tmpMat; | return tmpMat; | ||||
} | } | ||||
// Convert Unity Texture2D object to OpenCVSharp Mat object | |||||
private void TextureToMat_NEW(Texture2D source) | |||||
{ | |||||
// Color32 array : r, g, b, a | |||||
Color32[] c = source.GetPixels32(); | |||||
// Parallel for loop | |||||
// convert Color32 object to Vec3b object | |||||
// Vec3b is the representation of pixel for Mat | |||||
Parallel.For(0, imHeight, i => | |||||
{ | |||||
for (var j = 0; j < imWidth; j++) | |||||
{ | |||||
var col = c[j + i * imWidth]; | |||||
var vec3 = new Vec3b | |||||
{ | |||||
Item0 = col.b, | |||||
Item1 = col.g, | |||||
Item2 = col.r | |||||
}; | |||||
// set pixel to an array | |||||
videoSourceImageData[j + i * imWidth] = vec3; | |||||
} | |||||
}); | |||||
// assign the Vec3b array to Mat | |||||
videoSourceImage.SetArray(0, 0, videoSourceImageData); | |||||
} | |||||
// Simple example of canny edge detect | // Simple example of canny edge detect | ||||
private Mat ProcessImage(Mat _image) | private Mat ProcessImage(Mat _image) | ||||
{ | { | ||||
return cannyImg; | return cannyImg; | ||||
} | } | ||||
// Simple example of canny edge detect | |||||
private void ProcessImage_NEW(Mat _image) | |||||
{ | |||||
Cv2.Canny(_image, cannyImage, 100, 100); | |||||
} | |||||
// Convert OpenCVSharp Mat object to Unity Texture2D object | // Convert OpenCVSharp Mat object to Unity Texture2D object | ||||
private Texture2D MatToTexture(Mat mat) | private Texture2D MatToTexture(Mat mat) | ||||
{ | { | ||||
return texture; | return texture; | ||||
} | } | ||||
// Convert OpenCVSharp Mat object to Unity Texture2D object | |||||
private void MatToTexture_NEW(Mat mat) | |||||
{ | |||||
// cannyImageData is byte array, because canny image is grayscale | |||||
mat.GetArray(0, 0, cannyImageData); | |||||
// create Color32 array that can be assigned to Texture2D directly | |||||
Color32[] c = new Color32[croppedImHeight * imWidth]; | |||||
// parallel for loop | |||||
Parallel.For(0, croppedImHeight, i => | |||||
{ | |||||
for (var j = 0; j < imWidth; j++) | |||||
{ | |||||
byte vec = cannyImageData[j + i * imWidth]; | |||||
var color32 = new Color32 | |||||
{ | |||||
r = vec, | |||||
g = vec, | |||||
b = vec, | |||||
a = 0 | |||||
}; | |||||
c[j + i * imWidth] = color32; | |||||
} | |||||
}); | |||||
processedTexture.SetPixels32(c); | |||||
// to update the texture, OpenGL manner | |||||
processedTexture.Apply(); | |||||
} | |||||
private void CenterOfGravityTest(Mat processedImage) | private void CenterOfGravityTest(Mat processedImage) | ||||
{ | { |
public override void AcademyReset() | public override void AcademyReset() | ||||
{ | { | ||||
cozmo.transform.position = startPoint.position; | cozmo.transform.position = startPoint.position; | ||||
cozmo.transform.rotation = startPoint.rotation; | |||||
} | } | ||||
//private void Update() | //private void Update() |
if (renderCamera != null) | if (renderCamera != null) | ||||
{ | { | ||||
renderCamera.Render(); | renderCamera.Render(); | ||||
//onRenderImageTest.ProcessRenderTexture_NEW(renderCamera.targetTexture, onRenderImageTest.renderTextureCropped); | |||||
} | } | ||||
SetReward(-1); | SetReward(-1); | ||||
print("Reward: -1"); | print("Reward: -1"); | ||||
} | } | ||||
onRenderImageTest.enabled = false; | |||||
} | } | ||||
// to be implemented by the developer | // to be implemented by the developer | ||||
if (!academy.GetIsInference()) | if (!academy.GetIsInference()) | ||||
{ | { | ||||
//onRenderImageTest.ProcessRenderTexture_NEW(renderCamera.targetTexture, onRenderImageTest.renderTextureCropped); | |||||
RequestDecision(); | RequestDecision(); | ||||
} | } | ||||
else | else | ||||
if (timeSinceDecision >= timeBetweenDecisionsAtInference) | if (timeSinceDecision >= timeBetweenDecisionsAtInference) | ||||
{ | { | ||||
timeSinceDecision = 0f; | timeSinceDecision = 0f; | ||||
//onRenderImageTest.ProcessRenderTexture_NEW(renderCamera.targetTexture, onRenderImageTest.renderTextureCropped); | |||||
RequestDecision(); | RequestDecision(); | ||||
} | } | ||||
else | else |
Hash: 00000000000000000000000000000000 | Hash: 00000000000000000000000000000000 | ||||
m_ForcedFallbackFormat: 4 | m_ForcedFallbackFormat: 4 | ||||
m_DownscaleFallback: 0 | m_DownscaleFallback: 0 | ||||
m_Width: 320 | |||||
m_Height: 120 | |||||
m_Width: 80 | |||||
m_Height: 30 | |||||
m_AntiAliasing: 1 | m_AntiAliasing: 1 | ||||
m_DepthFormat: 2 | m_DepthFormat: 2 | ||||
m_ColorFormat: 0 | m_ColorFormat: 0 |
}, | }, | ||||
{ | { | ||||
"data": { | "data": { | ||||
"image/png": "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\n", | |||||
"image/png": "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\n", | |||||
"text/plain": [ | "text/plain": [ | ||||
"<Figure size 432x288 with 1 Axes>" | "<Figure size 432x288 with 1 Axes>" | ||||
] | ] | ||||
"name": "stdout", | "name": "stdout", | ||||
"output_type": "stream", | "output_type": "stream", | ||||
"text": [ | "text": [ | ||||
"Total reward this episode: -699.7999988794327\n" | |||||
"Total reward this episode: -366.90000158548355\n" | |||||
] | ] | ||||
}, | }, | ||||
{ | { |