Dylan Siegler
Dylan Siegler

Reputation: 742

WebCamTexture Coming Up With All 0s in the First Second or Two

I am using a WebCamTexture and I start it in my Start method, then I run another method. I get the pixels using GetPixels(), however, they all come up as (0, 0, 0). Is there any fix to this or way I can wait (Unity seems to crash using while loops and WaitForSeconds). Here is my current Start method:

void Start () {

    rawImage = gameObject.GetComponent<RawImage> ();
    rawImageRect = rawImage.GetComponent<RectTransform> ();

    webcamTexture = new WebCamTexture();
    rawImage.texture = webcamTexture;
    rawImage.material.mainTexture = webcamTexture;

    webcamTexture.Play();

    Method ();

    loadingTextObject.SetActive (false);
    gameObject.SetActive (true);

}

void Method(){

    print (webcamTexture.GetPixels [0]);

}

And this prints a (0, 0, 0) color every time.

Upvotes: 3

Views: 1573

Answers (3)

Chris
Chris

Reputation: 508

Two seconds might be quite alot of time spend waiting when you're grapping the size of the requested image.

The WebCamTexture has a requsted width/height that you can access and it will save the "real" width/height of the texture after calling GetPixels once. We've used the asset called CameraCaptureKit (https://www.assetstore.unity3d.com/en/#!/content/56673 ) in two projects where we share photos with the users.

The codes used there takes the WebCamTexture and Graps the frames every frame until it returns a width and height of the texture.

In an update function TryDummySnapshot was called until the size was returned properly.

// ANDREAS added this: In some cases we apparently don't get correct width and height until we have tried to read pixels
    // from the buffer.
    void TryDummySnapshot( ) {
        if(!gotAspect) {
            if( webCamTexture.width>16 ) {
                if( Application.platform == RuntimePlatform.IPhonePlayer ) {
                    if(verbose)Debug.Log("Already got width height of WebCamTexture.");
                } else { 
                }
                gotAspect = true;
            } else {
                if(verbose)Debug.Log ("Taking dummy snapshot");
                if( tmpImg == null ) {}
                Color32[] c = webCamTexture.GetPixels32();
            }
        }
    }

Upvotes: 0

Chris
Chris

Reputation: 508

If you don't want to wait until a size is reported or allocate and the target platform is iOS (iPhone/iPad) it's also possible to write a plugin that gets the size directly from the Camera code in Unity by extending CameraCapture.mm :

- (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection
{
intptr_t tex = (intptr_t)CMVideoSampling_SampleBuffer(&self->_cmVideoSampling, sampleBuffer, &self->_width, &self->_height);

_staticWebCamTexWidth = self->_width;
_staticWebCamTexWidth = self->_height;

UnityDidCaptureVideoFrame(tex, self->_userData);

if( self.firstFrameCallback!=nil ) {
    [self fireFirstFrame];
}
}

self->width / height can be returned in a method added as a plugin method like :

[DllImport("__Internal")]
private static extern int GetWebCamTextureWidth ();

[DllImport("__Internal")]
private static extern int GetWebCamTextureHeight ();

and then in the objc code

extern "C" int GetWebCamTextureWidth() { return _staticWebCamTexWidth;  }
extern "C" int GetWebCamTextureHeight() { return _staticWebCamTexHeight;  }

This is the solution i came up with for one of iOS social games that uses unity. On Android we fell back on the previously described approach.

Upvotes: 0

Programmer
Programmer

Reputation: 125245

Do your webcam stuff in a coroutine then wait for 2 seconds with yield return new WaitForSeconds(2); before calling webcamTexture.GetPixels.

void Start () {

    rawImage = gameObject.GetComponent<RawImage> ();
    rawImageRect = rawImage.GetComponent<RectTransform> ();

    StartCoroutine(startWebCam());

    loadingTextObject.SetActive (false);
    gameObject.SetActive (true);

}

private IEnumerator startWebCam()
{
    webcamTexture = new WebCamTexture();
    rawImage.texture = webcamTexture;
    rawImage.material.mainTexture = webcamTexture;

    webcamTexture.Play();

    //Wait for 2 seconds
    yield return new WaitForSeconds(2);

    //Now call GetPixels
    Method();

}

void Method(){
    print (webcamTexture.GetPixels [0]);
}

Or like Joe said in the comment section. Waiting for seconds is not reliable. You can just wait for the width to have something before reading it.Just replace the

yield return new WaitForSeconds(2);

with

while (webcamTexture.width < 100)
{
    yield return null;
}

Upvotes: 3

Related Questions