- ホーム /
WebCamTexture, get correct resolution and RATIO.
After searching for a while, I've seen different solutions to get this right. Most of them suggesting first instantiating the WebCamTexture to a high resoulution. This does not work at all.
How do you, correctly, get the actual camera aspect ratio and the actual pixels??
Note
at this point 2016 the only real solution is to use "NatCam" on the asset store.
you can avoid 4-10 weeks of work, it is the only realistic solution until Unity fix their shit
Fattie による 回答 · 02月29日 00:16
note
Thes days just use
NatCam
on the asset store. It saves 4-10 man-weeks of work.
Jonny Roy's answer is partially correct. This is a huge know bug / disaster in Unity. For years they have not fixed, mentioned or addressed the issue.
(1) The solution is this: the reported size only becomes correct after some time (1/2 sec or so).
(2) Before that the width is reported as a small number under 100. it sounds bizarre but you have to watch each frame for a number over 100. It works 100% reliably.
Note these days you would never use a WebCamTexture on anything but UI, here is a post to save some typing: http://answers.unity3d.com/questions/909967/getting-a-web-cam-to-play-on-ui-texture-image.html
And nowm how to spin the image!
Here is the state of the art, 2016, for fixing the ratio, spin, and mirror of WebCamTexture. Works on both Android and iOS:
private void Update()
{
if ( wct.width < 100 )
{
Debug.Log("Still waiting another frame for correct info...");
return;
}
// change as user rotates iPhone or Android:
int cwNeeded = wct.videoRotationAngle;
// Unity helpfully returns the _clockwise_ twist needed
// guess nobody at Unity noticed their product works in counterclockwise:
int ccwNeeded = -cwNeeded;
// IF the image needs to be mirrored, it seems that it
// ALSO needs to be spun. Strange: but true.
if ( wct.videoVerticallyMirrored ) ccwNeeded += 180;
// you'll be using a UI RawImage, so simply spin the RectTransform
rawImageRT.localEulerAngles = new Vector3(0f,0f,ccwNeeded);
float videoRatio = (float)wct.width/(float)wct.height;
// you'll be using an AspectRatioFitter on the Image, so simply set it
rawImageARF.aspectRatio = videoRatio;
// alert, the ONLY way to mirror a RAW image, is, the uvRect.
// changing the scale is completely broken.
if ( wct.videoVerticallyMirrored )
rawImage.uvRect = new Rect(1,0,-1,1); // means flip on vertical axis
else
rawImage.uvRect = new Rect(0,0,1,1); // means no flip
// devText.text =
// videoRotationAngle+"/"+ratio+"/"+wct.videoVerticallyMirrored;
}
Hope it saves someone a LOT of time.
However see George's critical notes in the other answer!!!!!!!
Thanks for this answer. I have a question about:
if ( wct.videoVerticallyMirrored )
rawImage.uvRect = new Rect(1,0,-1,1); // means flip on vertical axis
Why Rect(1,0,-1,1), i.e. horizontal flip and not Rect(0, 1, 1, -1), i.e. vertical flip?
Shouldn't a vertical flip be required for a "videoVerticallyMirrored" WebCamTexture?
Also, I can't seem to be able to mirror the RawImage for front-facing cameras without making it also flip vertically for some reason...
Hi George - I m absolutely not sure, and you may be perfectly correct about what Unity means ........... (also, their doco is often plain wrong, so I don't know) ...
A great point. Let me know what you find out from experimentation!!
Thanks for this.
This has been really useful for me too, so thanks, however I have something to add. I was trying to get the camera image as large on the screen as possible. However it was appearing quite small. It turned out that in my case the code was having to rotate the image 90 degrees, which was confusing the aspect ratio fitter, so that the final image I saw on screen was only as tall as my screen was wide.
I'm solving this by checking whether the imaging is being rotated and scaling the object containing my raw image by the aspect ratio if it is.
In your code it would look something like this;
if (ccwNeeded != 0 &&
ccwNeeded % 90)
{
parentTransform.localScale = new Vector3(videoRatio, videoRatio, 1);
}
else
{
parentTransform.localScale = new Vector3(1, 1, 1);
}
I don't know if there's something I missed which caused this but it seems to fix it for so I though I would mention it in case anyone runs into the same issue.
NatCam's developer here. I often wish that Unity would offer a way to pay for assets by implementing a plan. We would have jumped on creating a lite version of NatCam but the nature of the API does not permit it--it's either all or nothing. You could email me at olokobayusuf@gmail.com and we'll see if we can work something out for you. I honestly don't want the price to be a difficulty for developers, but I have specific instructions when it comes to pricing.
georgehbr による 回答 · 03月15日 13:31
Update:
Here's the full script I'm using for displaying the device camera feed on a UI image with correct orientation and ratio, front and back cameras, and mirroring the front camera to make it look more natural, along with a screenshot of my hierarchy and RawImage game object. It's based on this answer by @Fattie, this other answer by Max Bot, reading the Unity documentation on WebCamTexture and WebCamDevice, and trial and error on a Nexus 5 running Android 6 and an iPhone 5S running iOS 9.
Hierarchy:
DeviceCameraController.cs:
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
using System.Collections;
public class DeviceCameraController : MonoBehaviour
{
public RawImage image;
public RectTransform imageParent;
public AspectRatioFitter imageFitter;
// Device cameras
WebCamDevice frontCameraDevice;
WebCamDevice backCameraDevice;
WebCamDevice activeCameraDevice;
WebCamTexture frontCameraTexture;
WebCamTexture backCameraTexture;
WebCamTexture activeCameraTexture;
// Image rotation
Vector3 rotationVector = new Vector3(0f, 0f, 0f);
// Image uvRect
Rect defaultRect = new Rect(0f, 0f, 1f, 1f);
Rect fixedRect = new Rect(0f, 1f, 1f, -1f);
// Image Parent's scale
Vector3 defaultScale = new Vector3(1f, 1f, 1f);
Vector3 fixedScale = new Vector3(-1f, 1f, 1f);
void Start()
{
// Check for device cameras
if (WebCamTexture.devices.Length == 0)
{
Debug.Log("No devices cameras found");
return;
}
// Get the device's cameras and create WebCamTextures with them
frontCameraDevice = WebCamTexture.devices.Last();
backCameraDevice = WebCamTexture.devices.First();
frontCameraTexture = new WebCamTexture(frontCameraDevice.name);
backCameraTexture = new WebCamTexture(backCameraDevice.name);
// Set camera filter modes for a smoother looking image
frontCameraTexture.filterMode = FilterMode.Trilinear;
backCameraTexture.filterMode = FilterMode.Trilinear;
// Set the camera to use by default
SetActiveCamera(frontCameraTexture);
}
// Set the device camera to use and start it
public void SetActiveCamera(WebCamTexture cameraToUse)
{
if (activeCameraTexture != null)
{
activeCameraTexture.Stop();
}
activeCameraTexture = cameraToUse;
activeCameraDevice = WebCamTexture.devices.FirstOrDefault(device =>
device.name == cameraToUse.deviceName);
image.texture = activeCameraTexture;
image.material.mainTexture = activeCameraTexture;
activeCameraTexture.Play();
}
// Switch between the device's front and back camera
public void SwitchCamera()
{
SetActiveCamera(activeCameraTexture.Equals(frontCameraTexture) ?
backCameraTexture : frontCameraTexture);
}
// Make adjustments to image every frame to be safe, since Unity isn't
// guaranteed to report correct data as soon as device camera is started
void Update()
{
// Skip making adjustment for incorrect camera data
if (activeCameraTexture.width < 100)
{
Debug.Log("Still waiting another frame for correct info...");
return;
}
// Rotate image to show correct orientation
rotationVector.z = -activeCameraTexture.videoRotationAngle;
image.rectTransform.localEulerAngles = rotationVector;
// Set AspectRatioFitter's ratio
float videoRatio =
(float)activeCameraTexture.width / (float)activeCameraTexture.height;
imageFitter.aspectRatio = videoRatio;
// Unflip if vertically flipped
image.uvRect =
activeCameraTexture.videoVerticallyMirrored ? fixedRect : defaultRect;
// Mirror front-facing camera's image horizontally to look more natural
imageParent.localScale =
activeCameraDevice.isFrontFacing ? fixedScale : defaultScale;
}
}
Comments on Fattie's Answer:
So I'm pretty sure at this point that "verticallyMirrored" means that a rotation about the horizontal axis is needed. So I've modified the code in Fattie's answer to:
int ccwNeeded = -wct.videoRotationAngle;
rawImageRT.localEulerAngles = new Vector3(0f,0f,ccwNeeded);
float videoRatio = (float)wct.width/(float)wct.height;
rawImageARF.aspectRatio = videoRatio;
if ( wct.videoVerticallyMirrored )
rawImage.uvRect = new Rect(0,1,1,-1); // flip on HORIZONTAL axis
else
rawImage.uvRect = new Rect(0,0,1,1); // no flip
i.e. I removed "if ( wct.videoVerticallyMirrored ) ccwNeeded += 180;" and changed the flipped uvRect values. I'll post a new answer here or somewhere on this site with my full script once I iron it out which includes using both front and back cameras and mirroring the front camera's texture to make it more natural.
I converted your comment to an answer since it is so important, good one
I also sent 100 "reward points" ! :) Am waiting with bated breath to see your further info, be sure to post it here please!!!! Cheers...
That's really helpful!
I don't suppose you could share what's in the aspect filter?
Thank , that totaly worked. but i have litte problem about resolution . after i build in my phone 13 MP camera the image saved in my phoe blurry :( .
How to get the best resolution and not blurry
really suggest you just get NatCam .... save you weeks of time!
suggest you email the NatCam dudes they are very helpful. Even if you are not a customer they will solve your problem. it is very "specialized" field, you have to work on it all day every day.
enjoy!
Lanre による 回答 · 03月17日 18:01
Have you tried NatCam? It works wonders and has a lot more features.
Fantastic, I'm glad you told us about it. I will test it.
I sent you 50 "reward points" for bringing this to our attention :)
I would like to see a video of that plugin working, that would be reassuring. Does it replace WebCamTexture
?
Hi Fattie. It does! I am the publisher and my email address is olokobayusuf@gmail.com. Sorry for the inconvenience.
The email is in "Support Email" right next to "Publisher Website". Will be more clear when I upload package v1.1
回答を投稿
Welcome to Unity Answers
The best place to ask and answer questions about development with Unity.
To help users navigate the site we have posted a user guide.
If you are a new user, check out our FAQ for more information.
If you are a moderator, see our Moderator Guidelines page.
We are making improvements to UA, see the list of changes.
For troubleshooting common problems with Unity 5.x Editor (including Win 10).