Tags

, , , , , , , , , , , , ,

Arkwood was plucking petals off a stalk. ‘She loves me, she loves me not. She loves me…’

‘You are so destructive with nature,’ I scolded him, ‘What has the poor plant ever done to you?’

Anyways, I continued, Did you know that Peters put his size 13 boot through my TV screen? So I built a TV for my Oculus Rift virtual reality headset instead. It’s cool. The virtual TV uses OpenCV computer vision to display images from my webcam, letting me see the real world whilst sitting in a virtual world!

‘She loves me, she loves me not,’ my paper-thin Belgian buddy chanted, still pulling petals off the stalk and rudely ignoring me.

Never mind. Next I will add a second channel to my virtual TV set. I will update my C++ code, so that the Oculus SDK for Windows and OpenGL can render a video file also.

Here’s the code:

Mat CapturedImage;

class CaptureClient
{

private:
	VideoCapture Capture;
	int ActiveChannel;
	const int MaxChannels;

public:
	bool ThreadEnabled;

	CaptureClient() : ActiveChannel(0), MaxChannels(2), ThreadEnabled(true) {}

	void SwitchChannel() {

		// switch to next active channel
		if (ActiveChannel >= MaxChannels) {
			ActiveChannel = 1;
		}
		else {
			ActiveChannel++;
		}
	}

	void CaptureThread() {
		int CurrentChannel = 0;

		while (ThreadEnabled) {

			// if active channel has switched
			if (ActiveChannel != CurrentChannel) {

				// broadcast active channel
				switch (ActiveChannel)
				{
					case 1:
						// channel one is broadcast from webcam
						Capture.open(0);
						break;
					case 2:
						// channel two is broadcast from video file
						Capture.open("channel_two.mp4");
						break;
					default:
						Capture.release();
				}

				// set current channel to active channel
				CurrentChannel = ActiveChannel;
			}

			// obtain frame from channel
			if (Capture.isOpened()) {
				Capture >> CapturedImage;
			}
		}

		// release capture
		if (Capture.isOpened()) {
			Capture.release();
		}

	}
};

As you can see, the CaptureClient class has a maximum of 2 channels, and is also able to keep track of the active channel.

The class’s CaptureThread() method will be, as the name implies, run in a thread – so as not to block our main program from rendering to the Rift headset.

The thread will first check if we have switched channels on the TV set – if so, it will switch channel content. For now, we have a channel that will display a stream of images from our webcam and a channel that will display a stream of images from an MP4 video file.

Notice how the thread is updating the CapturedImage variable, making the next frame of our webcam or video stream available to the wider application.

Here’s how we start the thread running:

CaptureClient * captureClient = new CaptureClient();
std::thread ct(&CaptureClient::CaptureThread, captureClient);

How we bind our next frame, ready for our program shader to render to our Rift headset:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);

glUniform1i(glGetUniformLocation(Fill->program, "Texture0"), 0);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, CapturedImage.cols, CapturedImage.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, CapturedImage.ptr());

How we switch channels (I’m switching channels twice, to get to the channel handling our video file stream):

captureClient->SwitchChannel(); 
captureClient->SwitchChannel();

And finally how we dispose of our CaptureClient class when the app is shut down (we need to stop the thread before deleting the class):

captureClient->ThreadEnabled = false;
ct.join();
delete captureClient;

Splendid. Now I have my video displaying on the TV set in the virtual world:

oculusrift_virtualtv_videofile

The video is entitled My Surgeon. You should meet him. But then again, he is a recluse.

I told Arkwood the good news.

‘She loves me, she loves me not. She loves me…’

SHE FUCKIN DOES NOT LOVE YOU! I barked at him.

He was swooning over Daphne – the plump spotty girl who works down the chippy. Alas, truth be she will never love him. Her heart is sealed on Wayne, the deep fat frier. He has greasy hair, some muscle and a plentiful supply of battered fish.

But love, it has made Arkwood blind. No use he has for a TV set.

Ciao!