Holographic Photo Blending with PhotoCapture

@BrandonFogerty - yeah, I tried to use a projector component on the main camera - thinking it was a way to add UVs to the spatial mesh - I only got a single color and not the whole texture mapped to the mesh. (I guess the projector component doesn’t add UV??)

Another question - I also tried to use your photo blend with the new HolotoolKit that includes the Asobo spatial understanding - the issue is that when I try to take a photo while the new green mesh is active, I only get a white box - no photo. However when I deactivate the new spatial mesh, then everything works again. Any idea why it wouldn’t work with the new spatial understanding module in holotoolkit?

Thanks for your time!

@BrandonFogerty ,

With Unity 5.6.0b3, your Shader code is throwing following error:
‘vert’: output parameter ‘o’ not completely initialized

I added following code right after the line of declaring v2f o; in the vert().
UNITY_INITIALIZE_OUTPUT(v2f,o)

Thank you for sharing your code.

Hi @BrandonFogerty

As I said earlier, I am using Unity 5.6.0b3 and trying to using your script and shader for my learning.
Somehow, I can’t make it to work.
Here is what I did and I would like for you to let me know what I did wrong:

  1. New Unity 3D project.
  2. In the project, I created a new script, HoloLensSnapshotTest and copied your code there.
  3. I created a shader, HolographicImage and copied your shard code here.
  4. Add component in the Main Camera and select HoloLensSnapshotTest.
  5. Changed build settings: Windows Store, Universal 10, Hololens, D3D, Local Machine and Unity C# Project checked.
  6. Update player settings for : InternetClient, WebCam, VideosLibrary, PicturesLibrary, Microphone, and SpatialPerception checked.
  7. save a scene.
  8. Created App folder and build.
  9. Switched to Visual Studio with the solution file in the app folder.
  10. Changed to “Release”, “x86”, and “Remote Machine” with my hololens IP.
  11. Ctrl+F5 to run.

I observed that tapped event never trigged with the app.

If you can help me what I did wrong, I would appreciate it.

Thanks!

I’m attempting to follow your code above and i get a null reference on your line:

 m_CanvasRenderer.material = new Material(Shader.Find("AR/HolographicImageBlend"));

This happens when i deploy to hololens and air tap.
In my solution I don’t see the shader I created which is weird. When in the Unity Editor i see the folder and shader in that solution. But it does not show up anywhere once i build from unity. Any ideas what might the issue be?

Shaders won’t be included in a build if nothing directly references them in the scenes used for the build. To get around this, use the “Always-included Shaders” section of the Graphics Settings (Unity - Manual: Graphics).

1 Like

Is it possible to use the Webcam Photo Capturing feature with the remote connection app, without building, deploying and running the app on the hololens?

//edit: nvm, found the answer here: Holographic Remoting a real time saver - Unity Engine - Unity Discussions

Hello Everyone,

the code posted by @anon_5245516 is very interesting and helpful. I’ve been trying to do the same thing as @yjlin5210 described, that is translating some x,y coordinates from frame passed onto quad, to x,y coordinates in the holographic world, with some fixed z. I tried some approaches: 1) calculations based on ScreenToWorldPoint, 2) Pixel to Application-specified Coordinate System as described here Locatable camera overview - Mixed Reality | Microsoft Learn. Unfortunately no result was precise. In fact every time my holograms that I wanted to project on the specific pixel x,y coordinates were positioned on the left or on the right of the taken blended photo.

Any help would be highly appreciated.

Hi Mlotek -

I’m afraid I’m unable to puzzle out what exactly you’re trying to do, and don’t understand the problem you’re running into either. Would you mind going into more detail, possibly pasting in some code and screen captures?

Hi @unity_andrewc ,

let’s say that I’m reading a frame from Hololens locatable camera, with size of 896x504. On a captured frame there is a point or many points of interest, be it a person’s face, edge of an object or anything else I’m trying to detect, let’s say it will be a tip of a person’s nose, that have some x,y coordinates on my frame. What I want to do is to take those x,y coordinates, process them and display a hologram in a world space, but in a way that this hologram position corresponds with real object - a person’s tip of a nose - in a real world environment.

Since on hololens the Screen size and frame size are the same, I’ve been trying to do this:

sphere.transform.position = Camera.main.ScreenToWorldPoint(new Vector3(known_x_from_frame,known_y_from_frame,fixed_z));

When I pass a frame onto canvas the result is OK and the sphere displays on my object of interest. But on Hololens the result is not precise.

After that I tried methods described at already quoted Microsoft website:

Vector2 ImagePosZeroToOne = new Vector2((1.0F * known_x_from_frame / (1.0F * frameWidth), 1.0F - ((1.0F * known_y_from_frame / (1.0F * frameHeight)));
Vector2 ImagePosProjected = ((ImagePosZeroToOne * 2.0F) - new Vector2(1.0F, 1.0F)); // -1 to 1 space
Vector3 CameraSpacePos = UnProjectVector(projectionMatrix, new Vector3(ImagePosProjected.x, ImagePosProjected.y, 15));
Vector3 WorldSpaceRayPoint2 = cameraToWorldMatrix * CameraSpacePos; // ray point in world space

I’ve been experimenting with every calculated measure, but with no precise result. I know that the depth parameter is difficult to achieve, so for now I would be more than happy only with having x,y coordinates of hologram precise enough, with some fixed z.

I hope the provided description is better, but if you or anyone else needs more details I will be happy to provide. At the time of writing this message I can’t post any screen shots, but if they are still needed, I will post them tomorrow.

I don’t think that’s an assumption you can make in the context of photo capture. The PhotoCapture API exposes a set of resolutions supported by the photo camera - you basically just pick one of them and fill out the cameraResolutionWidth and cameraResolutionHeight on the CameraParameters object you pass to StartPhotoModeAsync (see https://docs.unity3d.com/ScriptReference/VR.WSA.WebCam.PhotoCapture.html). Hope that helps.

Hey everyone,

We wrote an open source project (with lots of documentation!) called HoloLensCameraStream that allows you to do exactly what everyone here wants. It even has Brandon’s shader in it (thanks!). I hope it helps.

It only runs in Unity 5.6 right now. I’d like to upgrade it to Unity 2017/2018.x, but there is some math issue that has emerged. From what I can see, the problem is with this line:

Vector3 position = cameraToWorldMatrix.GetColumn(3) - cameraToWorldMatrix.GetColumn(2);

I don’t know enough about what exactly is happening in this line, or why the functionality would change in Unity 2017. If anyone can give insight, I’ll make the upgrade.

3349494–261963–HoloLensCameraStream.unitypackage (53.9 KB)

Okay, now I think that there’s something with the shader that doesn’t work in 2017.x, but I don’t know what it is.

@BrandonFogerty Hi, I know this is some old post but I have a question. I am doing some project with this code, and I want to get a texture from the quad after blended so it is applied by two matrices. I used code from this picture, but it caused null exception.
Does anyone know how to get the texture2D image from the quad?

Thank you

3404408--268076--질문1.PNG

Hi @erics_vulcan and @BrandonFogerty

How would you reverse the process to get (in hololens!) the Pixel Coordinates of a 3d object?

Please help me, I’m using

Camera.main.WorldToScreenPoint(go.transform.postion)

But it isn’t working for me…

I would like to be able to use in C# something like the Application-specified Coordinate System to Pixel Coordinates process described by microsoft.

// Usual 3d math:
float4x4 WorldToCamera = inverse( CameraToWorld );
float4 CameraSpacePos = mul( WorldToCamera, float4( WorldSpacePos.xyz, 1 ) ); // use 1 as the W component
// Projection math:
float4 ImagePosUnnormalized = mul( CameraProjection, float4( CameraSpacePos.xyz, 1 ) ); // use 1 as the W component
float2 ImagePosProjected = ImagePosUnnormalized.xy / ImagePosUnnormalized.w; // normalize by W, gives -1 to 1 space
float2 ImagePosZeroToOne = ( ImagePosProjected * 0.5 ) + float2( 0.5, 0.5 ); // good for GPU textures
int2 PixelPos = int2( ImagePosZeroToOne.x * ImageWidth, ( 1 - ImagePosZeroToOne.y ) * ImageHeight ); // good for CPU textures

Thank you very much!

I have the same problem.Like this:
InvalidOperationException: Operation is not valid due to the current state of the object
System.Linq.Enumerable.First[Resolution] (IEnumerable`1 source)

How can i deal with it?

Are you running on the HoloLens or in the editor?

Running on the HoloLens.

This is a great tutorial! works like a charm. Thank you!

Hi, is there a way to show only a frame of area and somehow only capture that part from the HoloLens camera?

Great tutorial! Thank you