Continuous QR-Code scanning in Unity - unity3d

Question asked just to give solution :)
Main idea is to recognize QR-code on Unity without ANY additional action like tapping on the screen or sth like this.

(For me it's not necessary that "vuforia free" have watermark, so here is my solution)
(Also Vuforia works with camera much faster and no need to realize manually autofocus)
Continious QR code recognition using Vuforia as webcam source and ZXing Library as QR recognizer
using UnityEngine;
using Vuforia;
using ZXing;
public class QRCodeReader : MonoBehaviour {
private bool _isFrameFormatSet;
IBarcodeReader _barcodeReader = new BarcodeReader();
void Start () {
InvokeRepeating("Autofocus", 2f, 2f);
}
void Autofocus () {
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_TRIGGERAUTO);
RegognizeQR();
}
private Vuforia.Image GetCurrFrame()
{
return CameraDevice.Instance.GetCameraImage(Vuforia.Image.PIXEL_FORMAT.GRAYSCALE);
}
void RegognizeQR()
{
if (!_isFrameFormatSet == _isFrameFormatSet)
{
_isFrameFormatSet = CameraDevice.Instance.SetFrameFormat(Vuforia.Image.PIXEL_FORMAT.GRAYSCALE, true);
}
var currFrame = GetCurrFrame();
if (currFrame == null)
{
Debug.Log("Camera image capture failure;");
}
else
{
var imgSource = new RGBLuminanceSource(currFrame.Pixels, currFrame.BufferWidth, currFrame.BufferHeight, true);
var result = _barcodeReader.Decode(imgSource);
if (result != null)
{
Debug.Log("RECOGNIZED: " + result.Text);
}
}
}
}
Its possible to realize also without Vuforia, ofc. Unity provides the possibility to get a camera and show it’s input on a webcamtexture. It's possible to find more documentation here.
ZXing lib you can find here, or build it by your own hands using sourse code located on github.
Both libs is cross-platform, so must be no issues on different devices.

Related

TryGetFeatureValue always 0 for Unity XR Input's CommonUsages.trigger

I am developing a VR game in Unity (2020.3.15f2) using the XR Interaction Toolkit package (1.0.0-pre.5) for my Oculus Quest 2. At this stage in my development, I am trying to recognize presses to the trigger and grip buttons on the controllers respectively in order to animate some 3D hand models. Here's the script I've written to accomplish this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
public class HandPresence : MonoBehaviour {
public InputDeviceCharacteristics controllerCharacteristics;
public GameObject handModelPrefab;
private InputDevice targetDevice;
private GameObject spawnedHandModel;
private Animator handAnimator;
void Start() {
TryInitialize();
}
void TryInitialize() {
List<InputDevice> devices = new List<InputDevice>();
InputDevices.GetDevicesWithCharacteristics(controllerCharacteristics, devices);
if (devices.Count > 0) {
targetDevice = devices[0];
spawnedHandModel = Instantiate(handModelPrefab, transform);
handAnimator = spawnedHandModel.GetComponent<Animator>();
}
}
void UpdateHandAnimation() {
if (targetDevice.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue)) {
handAnimator.SetFloat("Trigger", triggerValue);
} else {
handAnimator.SetFloat("Trigger", 0);
}
if (targetDevice.TryGetFeatureValue(CommonUsages.grip, out float gripValue)) {
handAnimator.SetFloat("Grip", gripValue);
} else {
handAnimator.SetFloat("Grip", 0);
}
}
void Update()
{
if (!targetDevice.isValid) {
TryInitialize();
} else {
spawnedHandModel.SetActive(true);
UpdateHandAnimation();
}
}
}
The issue I'm experiencing is that the values of both triggerValue and gripValue are always 0. The value of targetDevice looks fine. I also tried using triggerButton, gripButton, primaryButton, etc. and they are always 0/false as well. The hand models show up just fine and their movement is in sync with the movement of the controllers, but they just don't seem to want to register any button presses.
I've been stuck on this one for hours and would very much appreciate any insight, thank you!
Is your project setup with the (new) Input System? I have no problem detecting there trigger and grip values.
Also make sure the targetDevice actually uses trigger and grip features, maybe it is another device such as the HMD.

UnityWebRequest does not complete [duplicate]

I'm trying to use a cloud TTS within my Unity game.
With the newer versions (I am using 2019.1), they have deprecated WWW in favour of UnityWebRequest(s) within the API.
I have tried the Unity Documentation, but that didn't work for me.
I have also tried other threads and they use WWW which is deprecated for my Unity version.
void Start()
{
StartCoroutine(PlayTTS());
}
IEnumerator PlayTTS()
{
using (UnityWebRequestMultimedia wr = new UnityWebRequestMultimedia.GetAudioClip(
"https://example.com/tts?text=Sample%20Text&voice=Male",
AudioType.OGGVORBIS)
)
{
yield return wr.Send();
if (wr.isNetworkError)
{
Debug.LogWarning(wr.error);
}
else
{
//AudioClip ttsClip = DownloadHandlerAudioClip.GetContent(wr);
}
}
}
The URL in a browser (I used Firefox) successfully loaded the audio clip allowing me to play it.
What I want it to do is play the TTS when something happens in the game, it has been done within the "void Start" for testing purposes.
Where am I going wrong?
Thanks in advance
Josh
UnityWebRequestMultimedia.GetAudioClip automatically adds a default DownloadHandlerAudioClip which has a property streamAudio.
Set this to true and add a check for UnityWebRequest.downloadedBytes in order to delay the playback before starting.
Something like
public AudioSource source;
IEnumerator PlayTTS()
{
using (var wr = new UnityWebRequestMultimedia.GetAudioClip(
"https://example.com/tts?text=Sample%20Text&voice=Male",
AudioType.OGGVORBIS)
)
{
((DownloadHandlerAudioClip)wr.downloadHandler).streamAudio = true;
wr.Send();
while(!wr.isNetworkError && wr.downloadedBytes <= someThreshold)
{
yield return null;
}
if (wr.isNetworkError)
{
Debug.LogWarning(wr.error);
}
else
{
// Here I'm not sure if you would use
source.PlayOneShot(DownloadHandlerAudioClip.GetContent(wr));
// or rather
source.PlayOneShot((DownloadHandlerAudioClip)wr.downloadHandler).audioClip);
}
}
}
Typed on smartphone so no warranty but I hope you get the idea

LocatableCamera (PhotoCapture) on the Hololens 2

I have 2 issues when using PhotoCapture on the Hololens 2, which are probably connected. They did not occur on the Hololens 1.
The only obtainable resolution is 3904x2196
Getting the CameraToWorldMatrix always fails
As can be seen in the docs, this resolution has no framerate associated with it.
My presumption is that the CameraToWorldMatrix is only obtainable for camera profiles with a lower resolution.
How can i change the resolution and get the matrix within Unity?
Minimal Reproducible Example
I am using Unity 2019.2.19f1 and Visual Studio 2019 Community (16.4.5)
Create a new Unity Project following the steps here, except using IL2CPP as the scripting backend instead of .NET
In Player Settings: Capabilities enable InternetClient, InternetClientServer, PrivateNetworkClientServer, Webcam, Microphone and SpatialPerception, in Player Settings: Supported Device Families select Holographic
Create a new empty gameobject and add the following script:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Windows.WebCam;
public class PhotoCaptureController : MonoBehaviour
{
PhotoCapture photoCaptureObject = null;
bool isRunning = false;
void Start()
{
StartCoroutine(StartCameraCapture());
}
private IEnumerator StartCameraCapture()
{
if (!Application.HasUserAuthorization(UserAuthorization.WebCam))
{
yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
}
if (Application.HasUserAuthorization(UserAuthorization.WebCam))
{
Debug.Log("Creating PhotoCapture");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}
else
{
Debug.Log("Webcam Permission not granted");
}
}
private void Update()
{
if (isRunning)
{
photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
}
}
void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
photoCaptureObject = captureObject;
IEnumerable<Resolution> availableResolutions = PhotoCapture.SupportedResolutions;
foreach (var res in availableResolutions)
{
Debug.Log("PhotoCapture Resolution: " + res.width + "x" + res.height);
}
Resolution cameraResolution = availableResolutions.OrderByDescending((res) => res.width * res.height).First();
CameraParameters c = new CameraParameters();
c.hologramOpacity = 0.0f;
c.cameraResolutionWidth = cameraResolution.width;
c.cameraResolutionHeight = cameraResolution.height;
c.pixelFormat = CapturePixelFormat.BGRA32;
captureObject.StartPhotoModeAsync(c, OnPhotoModeStarted);
}
private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
isRunning = true;
photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
}
}
void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame frame)
{
if (result.success)
{
if (frame.TryGetCameraToWorldMatrix(out Matrix4x4 cameraToWorldMatrix))
{
Debug.Log("Successfully obtained CameraToWorldMatrix: " + cameraToWorldMatrix.ToString());
}
else
{
Debug.Log("Failed to obtain CameraToWorldMatrix");
}
}
frame.Dispose();
}
}
Change Build Settings:
Build, open VS solution, set build target to ARM64, Debug and deploy to Device
This CameraCapture plugin may work for you. It's a native plugin for Unity. The readme.txt contains information on building it. Basically, you need to build the native plugin variants before trying to open up the Unity sample. If you haven’t built C++/WinRT components, you may need to go through the setup steps here. The SpatialCameraTracker.cs file shows how to receive the camera matrices.
There is minimal support on this but all the code is in the repo

JavaFx set volume on MediaPlayer not working

This question has been asked before but to date there is no answer. I have just struck the same problem. I traced into the mediaplayer source and all is well until I get to gstSetVolume in GSTMediaPlayer for which I don't have the source.
At that point the volume value is still correct.
After setting the volume System.out.println(player.getVolume()); reports the correct value (0.0 - 1.0) BUT the volume has not changed. If the slider is set to 0, the audio is muted. Any other value is full volume.
Platform is Netbeans 8.1 on Windows 7 with JavaFX-8 and JDK-8 and the media source is a standard mp4 which works on all tested players (Windows, VLC etc).
Here is the code attached to a MediaView (which works well):
Runnable videoLoop;
PlayListViewController playListViewController;
// Videos are looped here
public void startVideoLoop() {
playerIndex = 0;
videoLoop = () -> {
// Previous player MUST be stopped otherwise it is left
// in the PLAYING state and the next video will not PLAY
if (player != null) {
player.stop();
}
// Point to the next player
if (++playerIndex == videoPlayersList.size()) {
playerIndex = 0;
}
playVideoSequence();
};
playVideoSequence();
}
public void playVideoSequence() {
// If the video options are shown we can update the listview
if (playListViewController != null) {
playListViewController.setListViewItem(playerIndex);
}
player = videoPlayersList.get(playerIndex);
mediaView.setMediaPlayer(player);
player.setOnEndOfMedia(videoLoop);
player.play();
}
A right mouse button press then invokes a 'settings' option. This is a View Controller which is attached to an FXML view. The controller receives a reference to the videoField when it is invoked. Here is the relevant snippet:
private void setHandlers() {
idVolumeSlider.valueProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue arg0, Object arg1, Object arg2) {
// videoField is a separate class
videoField.setVolume(idVolumeSlider.getValue());
}
});
I'm sorry I cannot supply a 'cut and paste' example, because that would mean a lot of pruning and simplifying of classes to achieve that with the risk of introducing additional problems.

Project Tango won't relocalize

I am trying out Area Recognition using Area Learning with predefined ADF files using Project Tango in Unity3d. I use the script from this tutorial as the basis, but for some reason it won't relocalize.
using UnityEngine;
using System.Collections;
using Tango;
public class TestADFFile : MonoBehaviour, ITangoLifecycle
{
private TangoApplication m_tangoApplication;
public UnityEngine.UI.Text statusText;
public string adfName;
public void Start()
{
m_tangoApplication = FindObjectOfType<TangoApplication>();
if (m_tangoApplication != null)
{
m_tangoApplication.Register(this);
m_tangoApplication.RequestPermissions();
}
}
public void OnTangoPermissions(bool permissionsGranted)
{
if (permissionsGranted)
{
if(AreaDescription.ImportFromFile(System.IO.Path.Combine(Application.streamingAssetsPath, "adfs/" + adfName))){
statusText.text = "success!";
}
else{
statusText.text = "fail!";
}
AreaDescription[] list = AreaDescription.GetList();
AreaDescription mostRecent = null;
AreaDescription.Metadata mostRecentMetadata = null;
if (list.Length > 0)
{
// Find and load the most recent Area Description
mostRecent = list[0];
mostRecentMetadata = mostRecent.GetMetadata();
foreach (AreaDescription areaDescription in list)
{
AreaDescription.Metadata metadata = areaDescription.GetMetadata();
if (metadata.m_dateTime > mostRecentMetadata.m_dateTime)
{
mostRecent = areaDescription;
mostRecentMetadata = metadata;
}
}
m_tangoApplication.Startup(mostRecent);
}
else
{
// No Area Descriptions available.
Debug.Log("No area descriptions available.");
}
}
}
public void OnTangoServiceConnected()
{
}
public void OnTangoServiceDisconnected()
{
}
}
The statusText is set to "success" so apparently the ADF is successfully loaded, right?
You're doing it right. Relocalization with area learning mode off works very quick. But relocalization with area learning mode on takes quite a while. You have to walk around up to 3-5 minutes until the relocalization works. Don't give up. I had the same problem. But in the end, it works!
Is not an answer I think, but just a checklist of things I would check.
Check that the ADF to relocalize is the right one, you may be loading an ADF from a different area.
On the TangoManager component check if Enable Area Descriptions is set to true.
Also check if the scene is set up correctly with all tango components required like: RelocalizingOverlay.cs, TangoApplication.cs
Also as a personal note I have noticed that ADF sometimes take quite a while to relocalized and sometimes they don't relocalize at all.
I think the reasons are that the room has change in someway or the lighting is very different, by different I mean maybe the day you recorded that ADF was a very sunny day and the day you are trying to relocalize is cloudy.(Again this are just theories of mine, I got from my testing)