r3dux.org

A number-pimping side project from the valleys in *NEW* upside-down flavour.

  • Home
  • ABOUT
  • OLD SITE
  • SEARCH
  • FEEDBACK

How to: Convert an OpenCV cv::Mat to an OpenGL texture

r3dux | January 14, 2012

I’m working on using OpenCV to get Kinect sensor data via OpenNI, and needed a way to get a matrix (cv::Mat) into an OpenGL texture – so I wrote a function to do just that – woo! Apologies in advance for the terrible juggling ;-)

YouTube Preview Image

The function used to perform the sensor data to texture conversion is:

// Function turn a cv::Mat into a texture, and return the texture ID as a GLuint for use
GLuint matToTexture(cv::Mat &mat, GLenum minFilter, GLenum magFilter, GLenum wrapFilter)
{
	// Generate a number for our textureID's unique handle
	GLuint textureID;
	glGenTextures(1, &textureID);
 
	// Bind to our texture handle
	glBindTexture(GL_TEXTURE_2D, textureID);
 
	// Catch silly-mistake texture interpolation method for magnification
	if (magFilter == GL_LINEAR_MIPMAP_LINEAR  ||
	    magFilter == GL_LINEAR_MIPMAP_NEAREST ||
	    magFilter == GL_NEAREST_MIPMAP_LINEAR ||
	    magFilter == GL_NEAREST_MIPMAP_NEAREST)
	{
		cout < < "You can't use MIPMAPs for magnification - setting filter to GL_LINEAR" << endl;
		magFilter = GL_LINEAR;
	}
 
	// Set texture interpolation methods for minification and magnification
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
 
	// Set texture clamping method
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapFilter);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapFilter);
 
	// Set incoming texture format to:
	// GL_BGR       for CV_CAP_OPENNI_BGR_IMAGE,
	// GL_LUMINANCE for CV_CAP_OPENNI_DISPARITY_MAP,
	// Work out other mappings as required ( there's a list in comments in main() )
	GLenum inputColourFormat = GL_BGR;
	if (mat.channels() == 1)
	{
		inputColourFormat = GL_LUMINANCE;
	}
 
	// Create the texture
	glTexImage2D(GL_TEXTURE_2D,     // Type of texture
	             0,                 // Pyramid level (for mip-mapping) - 0 is the top level
	             GL_RGB,            // Internal colour format to convert to
	             mat.cols,          // Image width  i.e. 640 for Kinect in standard mode
	             mat.rows,          // Image height i.e. 480 for Kinect in standard mode
	             0,                 // Border width in pixels (can either be 1 or 0)
	             inputColourFormat, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
	             GL_UNSIGNED_BYTE,  // Image data type
	             mat.ptr());        // The actual image data itself
 
	// If we're using mipmaps then generate them. Note: This requires OpenGL 3.0 or higher
	if (minFilter == GL_LINEAR_MIPMAP_LINEAR  ||
	    minFilter == GL_LINEAR_MIPMAP_NEAREST ||
	    minFilter == GL_NEAREST_MIPMAP_LINEAR ||
	    minFilter == GL_NEAREST_MIPMAP_NEAREST)
	{
		glGenerateMipmap(GL_TEXTURE_2D);
	}
 
	return textureID;
}

You can then use the above function like this:

// Create our capture object
cv::VideoCapture capture( CV_CAP_OPENNI );
 
// Check that we have actually opened a connection to the sensor
if( !capture.isOpened() )
{
	cout < < "Cannot open capture object." << endl;
	exit(-1);
}
 
// Create our cv::Mat object
cv::Mat camFrame;
 
	// *** loop ***
 
	// Grab the device
	capture.grab();
 
	// Retrieve desired sensor data (in this case the standard camera image)
	capture.retrieve(camFrame, CV_CAP_OPENNI_BGR_IMAGE);
 
	// Convert to texture
	GLuint tex = matToTexture(camFrame, GL_NEAREST, GL_NEAREST, GL_CLAMP);
 
	// Bind texture
	glBindTexture(GL_TEXTURE_2D, tex);
 
	// Do whatever you want with the texture here...
 
	// Free the texture memory
	glDeleteTextures(1, &tex);
 
	// *** End of loop ***
 
// Release the device
capture.release();

There's one very important issue to watch out for when using OpenCV and OpenNI together which I've commented in the code, but I'll place here as well as it can be a real deal breaker:

There appears to be a threading issue with the OpenCV grab() function where if you try to grab the device before it's ready to provide the next frame it takes up to 2 seconds to provide the frame, which it might do for a little while before crashing the XnSensorServer process & then you can't get any more frames without restarting the application. This results in horrible, stuttery framerates and garbled sensor data.

I've found that this can be worked around by playing an mp3 in the background. No, really. I'm guessing the threading of the mp3 player introduces some kind of latency which prevents the grab() function being called too soon. Try it if you don't believe me!

So just be aware that if you're using a Kinect you have to be careful with the grab() function... The source code used to create the above video is provided in full after the jump, if you're interested.

Cheers!

Read the rest of this entry »

Comments
No Comments »
Categories
Coding, Linux
Tags
Capture, Conversion, Convert, cv::Mat, Kinect, Linux, NITE, OpenCV, OpenGL, OpenNI, Texture
Comments rss Comments rss
Trackback Trackback

How to: Create an ISO image of directories in Linux

r3dux | July 29, 2011

I ripped some DVDs I own the other day as I wanted to create a back-up for the kids travel DVD players (so the originals don’t get scratched and trashed on the road), only the DVDs themselves were DVD-9′s (so single-sided dual-layer with a capacity of up to 8.54GB) while I can only write DVD-5′s (single-sided single layer with a capacity of up to 4.7GB) – this isn’t a big problem as I compressed them down to fit using Handbrake and elements of Shetboy’s meticulously crafted AVI to DVD technique. However, both Brasero and GnomeBaker would flat out refuse to burn Video projects – they’d just choke on the folder containing the AUDIO_TS and VIDEO_TS folders – so why not covert the directory including the *_TS folders to an ISO and burn that? No reason why not! Let’s get it done! =P

Making the ISO

Once you’ve got a folder structure containing the AUDIO_TS folder (which is empty) and the VIDEO_TS folder (which contains your .BUP, .IFO and .VOB files), just run the following command to generate your ISO:

mkisofs -o ISO_FILENAME -V LABEL -r SOURCE_DIRECTORY

So, for example, you might use the following command to create an ISO of the directory containing the *_TS folders for the film Avatar:

mkisofs -o ~/AvatarDVD.iso -V Avatar -r ~/dvdprep/Avatar/

Once you hit return, you’ll see something like the following output:

I: -input-charset not specified, using utf-8 (detected in locale settings)
  0.22% done, estimate finish Wed Jul 27 12:30:27 2011
 
..... all the rest ......
 
 99.96% done, estimate finish Wed Jul 27 12:27:58 2011
Total translation table size: 0
Total rockridge attributes bytes: 1353
Total directory bytes: 4096
Path table size(bytes): 42
Max brk space used 21000
2275896 extents written (4445 MB)

Measure Twice, Cut Once

If you wanted to make sure you got it right, as in, you ONLY have the *_TS folders in the iso, not the top level folder containing those two folders also, then just open the created iso file with Archive Manager and take a look, or mount it to a folder with:

mkdir test
sudo mount -o loop -t iso9660 ./AvatarDVD.iso ./test
ls test
 
[ which should show "AUDIO_TS  VIDEO_TS" ]
 
sudo umount ./test

When you’re happy with the iso, burn it with your burning software of choice and you’re all sorted!

Cheers!

Comments
1 Comment »
Categories
How-To, Imagery, Linux
Tags
Burn, Convert, Directories, DVD, Folders, Image, ISO, mkisofs, mount, Rip
Comments rss Comments rss
Trackback Trackback

How To: Convert VirtualPC .vhd hard drives to VirtualBox .vdi hard drives (or vice-versa)

r3dux | February 9, 2011

Don’t bother – VirtualBox now natively supports .vhd drives – how handy is that? =D

But if you really wanted to, just use:

VBoxManage clonehd source.vhd target.vdi --format vdi

This will place the .vdi version of your drive in your current users VirtualBox folder, which is: ~/.VirtualBox

Relatedly, to go the other way (.vdi to .vhd) you could use:

VBoxManage clonehd source.vdi target.vhd --format vhd

Note: For this to work, you must not have the drive attached to any virtual machine, so if you already have it connected to a virtual machine, detach it first, mkay?

Comments
7 Comments »
Categories
How-To
Tags
.vdi, .vhd, Conversion, Convert, VirtualBox, VirtualPC
Comments rss Comments rss
Trackback Trackback

How To: Convert .WBFS Image Files to .ISO Images

r3dux | April 17, 2010

Update: You can convert compressed ISO images (.ciso files) using this method, too…

If you need to translate a Wii DVD image from the newer .WBFS format (which has lovely sparce-file support) to an old-school .ISO image, well you can jolly well do so with Wii Backup Manager! Now, WBM is a really useful program so congrats to the author (xzxero) – but it uses non-standard GUI elements in that it uses what looks like the category list as a second main-menu, and this makes it a little non-intuitive to use. But in fairness to the author, the download page has a tutorial (which I didn’t find until after completing this post!). Still, it’s easy enough once you’ve figured that out. The entire conversion process goes like this:

1.) Grab yourself a copy of Wii Backup Manager. Version v0.3.5 beta 1 is the most recent version available at the time of writing, and although it’s Win32 only, it works fine in VirtualBox…

2.) Extract and launch it

Wii Backup Manager

3.) From the Files tab, click on what looks like the Add category title, select Files and go pick a .WBFS image from the navigation dialogue box

Wii Backup Manager - Add Files

4.) Still in the Files tab, tick the checkbox to the left of your .wbfs image, and then click on what looks like the Transfer category title and select ISO..

Wii Backup Manager - Transfer Files

5.) Pick where you want the converted .ISO file to be created and click the [OK] button

Wii Backup Manager - Place ISO

That’s it – job done! Transfer your ISO to your WBFS formatted USB drive and launch it as you normally would via USBLoaderGX or whatever your poison is… :)
Flattr this

Comments
57 Comments »
Categories
Gaming, How-To
Tags
Conversion, Convert, Image, ISO, WBFS, Wii
Comments rss Comments rss
Trackback Trackback

How To: Transcode AVI Videos to Video DVDs in Linux

r3dux | February 22, 2010

It’s easy enough to rip DVDs to .AVIs or .MKVs – you can just use nice, GUI-enabled tools like HandBrake. But what about when you want to transfer an AVI back to DVD format so it can be played on a standalone DVD player? Well, the Shetboy sent me his command-line technique a while back (which we can automate to some extent) – and I’ve got to say it works flawlessly.

1.) Get the Right Tools for the Job

If you’ve ever had a look at a video DVD on your PC, you’ll notice is has a bunch of .VOB files broken up into roughly 1GB sections which contain the pieces of your movie (if it’s a DVD of TV episodes you’re more likely to have a greater number of VOBs split up into one per episode on the disc). To deal with all the transcoding we’re going to do, we need the right tools. Some of these you’re likely to already have, others maybe not.

Package pre-requisites for transcoding:
mencoder, mplayer, libxvidcore, libxvidcore4, xvid4conf, xvidtune, ffmpeg, libavcodec0d, libmpeg*, w32codecs, transcode, mjpegtools, dvdauthor

You can install them all via the following command (where any you already have will just be skipped):

sudo apt-get install mencoder mplayer libxvidcore libxvidcore4 xvid4conf xvidtune ffmpeg libavcodec0d  w32codecs transcode mjpegtools dvdauthor libmpeg*

2.) Find Out Your .AVI’s Crop Area

To do a nice transcode, best results are gained by not transcoding any black bars in the avi. This step also helps in getting a perfect re-size every time without messing up the aspect ratio.

To do this run:

mplayer -vf cropdetect <file.avi>

An mplayer window will open and the avi will play. Press the right arrow about 10 times and leave it running for a few seconds. The reason for this is that different resolutions can sometimes be used for the intro to TV shows, or company logos and things, and we want the main feature being played. After it has been showing the body of the show for a few seconds kill the mplayer window.

Output from the above command will be shown in your console window, and should look something like this:


mplayer -vf cropdetect Star.Wars.The.Clone.Wars.S01E01.HDTV.XviD-0TV.avi
MPlayer 2:0.99+1.0pre8-0ubuntu8.3 (C) 2000-2006 MPlayer Team

— A whole bunch of other stuff we don’t care about here —

Opening video filter: [cropdetect]
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg’s libavcodec codec family
Selected video codec: [ffodivx] vfm: ffmpeg (FFmpeg MPEG-4)
==========================================================================
alsa-init: using device default
alsa: 48000 Hz/2 channels/4 bpf/65536 bytes buffer/Signed 16 bit Little Endian
AO: [alsa] 48000Hz 2ch s16le (2 bytes per sample)
Starting playback…
VDec: vo config request – 624 x 352 (preferred colorspace: Planar YV12)
VDec: using Planar YV12 as output csp (no 0)
Movie-Aspect is 1.77:1 – prescaling to correct movie aspect.
VO: [xv] 624×352 => 624×352 Planar YV12
[CROP] Crop area: X: 623..0 Y: 351..0 (-vf crop=-608:-336:618:346).
[CROP] Crop area: X: 623..0 Y: 351..0 (-vf crop=-608:-336:618:346). *** This is the crop-area of the pre-show company logos etc. – don’t use it! ***
[CROP] Crop area: X: 623..0 Y: 351..0 (-vf crop=-608:-336:618:346).
…
[CROP] Crop area: X: 0..623 Y: 0..351 (-vf crop=624:352:0:0).7 0
[CROP] Crop area: X: 0..623 Y: 0..351 (-vf crop=624:352:0:0).7 0
[CROP] Crop area: X: 0..623 Y: 0..351 (-vf crop=624:352:0:0).7 0 *** This is the crop-area of the main presentation which we’re going to use! ***
[CROP] Crop area: X: 0..623 Y: 0..351 (-vf crop=624:352:0:0).7 0
[CROP] Crop area: X: 0..623 Y: 0..351 (-vf crop=624:352:0:0).7 0
…


The last bunch of lines showing the crop area for the main presentation are what’s important here. We’ll use this info shortly.

3.) Transcode the Video File

We’ll be doing the transcoding using mencoder, which takes an un-holy number of parameters to do a great job.

An example of a command in the proper format is …

mencoder -oac lavc -ovc lavc -of mpeg -mpegopts format=dvd:tsaf -srate 48000 -ofps 25 \
-lavcopts vcodec=mpeg2video:vrc_buf_size=1835:keyint=15:vrc_maxrate=9800:vbitrate=4900:aspect=16/9:acodec=ac3:abitrate=192 \
-af lavcresample=48000 \
-vf crop=624:352:0:0,scale=720:576,expand=720:576,harddup \
-o ~/transcoded/ep01.mpg \ 
Star.Wars.The.Clone.Wars.S01E01.HDTV.XviD-0TV.avi

To figure out what’s going on so you can tweak the numbers appropriately, I’ve separated out the switches into a table to best explain how it works:

Unholy Amount of Command Line Switches and Parameters Needed To Transcode .AVIs to DVDs
Switch Should I Tweak It? Explanation
mencoder Haha, No. Fire up mencoder to do our bidding
-oac lavc No. Output audio using libavcodec’s audio codecs
-ovc lavc No. Output video using libavcodec’s video codecs
-of mpeg No. Output our file in MPEG format – expect large file sizes!
-mpegopts No. Tell mencoder that from now on all switches are to control the MPEG output
format=dvd:tsaf No. Create our output with timestamps on every frame to keep everything in sync.
Note that we don’t put a dash before this option because it’s the first option after specifying -mpegopts
-srate 48000 No. Output our MPEG audio at 48Khz so it’s as high quality as we can make it
-ofps 25 Up to you. Output our MPEG video at 25fps for a PAL DVD. Change this to 23.97fps for a NTSC DVD.
-lavcopts No. Start our section where we specify libavcodec’s options
vcodec=mpeg2video No. Specify we want to create MPEG2 video. Note the lack of a prefix dash and the colon on the end to specify all further options will be specifying the details of our MPEG2 video output
vrc_buf_size=1835: No. Specify our buffer size. Note the colon at the end which is necessary to combine multiple parameters to our -lavcopts switch.
keyint=15: No. Specify our keyframe interval as 15 i.e. One frame in every 15 will be a keyframe which is encoded at high quality. Note the colon.
vrc_maxrate=9800: Yes. Specify the maximum data rate for our video. Note the colon.

It’s best to use a bitrate calculator to get this value as outlined in the row below on vbitrate…

vbitrate=4900: Yes The average bitrate for our variable bitrate for the video. Note the colon.

If you’re planning to burn the video you’re transcoding to a DVD (i.e. a standard, single-layer DVD5) then it’s worthwhile using a bitrate calculator to get the best number to plug in here. The bitrate calculator will just ask you for the length of the video, the audio bitrate (as specified below), and it’ll give you values to plug in for the average and maximum (see above) video bit-rates.

aspect=16/9: Up to you. The aspect ratio of our output video. Options are 16/9 for widescreen and 4/3 for old-school anamorphic. Note the colon.
acodec=ac3: No. Set the audio codec to use to AC3 (also known as Dolby Digital). Note the colon.
abitrate=192 No. Set our auto bitrate to 192 kbit/sec. Note – No colon this time as we’re at the end of our -lavcopts section! Finally!
-af lavcresample=48000 No. Resample our audio to 48Khz for maximum quality
-vf crop=624:352:0:0, Yes! Set our crop ratio to be what we retrieved from our mplayer -vf cropdetect command [eg. 624:352:0:0]. Note the comma.
scale=720:576, Yes! Set our scaling: x-scale (horizontal) is set to 720 pixels, and the y-scale (vertical is set to 576 pixels. 720×576 is the resolution of a PAL DVD, pick.

This is the important part: We set the x-scale to be the full width of our screen, and then we use the following formula to generate what our y-scale should be: yscale = (y-resolution * aspect ratio * y-crop-area) / x-crop-area [So for this example it's (576 * (16/9) * 352) / 624 = 578 ==> If more than 576, set it to 576! Or if it's more than 480 set it to 480 for a NTSC DVD]. Note the comma!

expand=720:576,harddup Up to you. Set our video expansion to be the resolution we finally want to use: For PAL it’s 720:576, for NTSC you’ll want to use 720:480. This might be the same as the scale details above, but they don’t have to be. The harddup video filter is used to keep the audio and video in sync when changing frame rates. Note the comma between the expanded resolution and calling the harddup filter!
-frames 7500 Use only to test. OPTIONAL: Only encode first 5 minutes to test. 7500 = 60 seconds per minute * 5 minutes * 25 frames per second.
-o <output-MPEG-filename.mpg> Yes. Your MPEG output path and filename, in this example I’m using: ~/transcoded/ep01.mpg
<input-file-name> Yes. The avi we’re using for input, in this example I’m using: ./Star.Wars.The.Clone.Wars.S01E01.HDTV.XviD-0TV.avi

So, even though it looks like a bit of a nightmare, you only need to change a few things in the entire command:

1.) Choose your output fps by setting -ofps 25 for PAL or -ofps 23.95 for NTSC.
2.) Set whether we want to output in widescreen 16/9 or old-school 4/3 by setting -aspect=16/9 or -aspect=4/3
3.) Feed in the result of running our mplayer cropdetect so we end up with something like -vf crop 624:352:0:0,
4.) Feed in the result of running our scale calculation so we end up with something like scale=720:576,
5.) Give it an input source AVI and an output file to dump the transcoded MPEG to
6.) Optionally, only transcode a couple of minutes to make sure it’s all running alright. Once you’re happy with the transcode take out the -frames line and it’ll transcode the whole video file for you.

If you really want to dig into the switches more, you could always take a look at this page which shows how to use mencoder in significantly more detail.

4.) Generate the DVD

Now we’ve done the hard part and we’ve got a big ‘ol .mpg file of our avi, it’s time to generate the DVD structure. If you’re putting multiple mpegs to a DVD, keep the file limit to about 4.2GB otherwise it won’t fit on a single-sided DVD5. If you’ve got a DVD9 writer you might be alright up to about 8GB, but I don’t have one so I haven’t tested this.

Word of Warning: When you’re generating large MPEG files for DVDs do NOT work on a FAT32 file system – FAT32 has a 4GB file limit, and if you end up with a 4GB+ file, things are going to fail.

You need to run two commands to generate a DVD:

dvdauthor -t -o newfolder file1.mpg [file2.mpg] [file3.mpg] ...
dvdauthor -o newfolder -T

The first command instructs dvdauthor to make a title out of each file (think chapter so we can skip through them easily), and can take a while to run. The second command generates our table of contents and completes near instantly. Read more via the mighty man dvdauthor if you’re that way inclined…

So, an example of the command usage, assuming I’d created the dvdprep folder in my home folder, might be:

dvdauthor -t -o ~/dvdprep/starwars1 ~/transcoded/ep01.mpg ~/transcoded/ep02.mpg ~/transcoded/ep03.mpg ~/transcoded/ep04.mpg
dvdauthor -o ~/dvdprep/starwars1 -T

Important: In the above example ~/dvdprep MUST exist but the directory starwars1 MUST NOT!

With this done, the start of each new file can be jumped to within the DVD by hitting chapter next or previous on your DVD software or player. Before burning to disc you should check that it works ok by checking with a video player like VLC and select ‘Play DVD from Directory’ or similar.

Workaround for ERR: no video format specified for VMGM error: If you get the error just mentioned, then it’s an issue with the DVDauthor v0.7.0 package. To fix things, run the command export VIDEO_FORMAT=PAL or export VIDEO_FORMAT=NTSC then run the second line (ending with -T) again and you should be fine.

5.) Burn the DVD!

That’s it! We’re done! Burn the DVD directory (i.e. the contents of ~/dvdprop/starwars1 now containing the AUDIO_TS and VIDEO_TS folders in his example) using Brasero, K3b or your burning software o’ choice. Whatever you use, make sure you burn the disc as a New Video DVD though!!

Happy transcoding!


An extra-special shout-out to the Shetboy for sending me this how-to ages back – apols. for not getting around to posting it sooner! I just knew it’d be a bugger to nail perfectly (i.e. unholy table of doom!) so I was kind putting it off =P

Comments
3 Comments »
Categories
How-To, Linux
Tags
AVI, Convert, DVD, dvdauthor, mencoder, That's a lot of switches..., Transcode, Video
Comments rss Comments rss
Trackback Trackback

« Previous Entries

Translate

Categories

Archives

Tags

3D ActionScript ActionScript 3.0 Adobe AI Ballarat Bash C++ Class Convert CS4 Effect Error Film Flash GLSL Gnome Hack How-To install Jaunty Java Kinect Linkage Linux Mash-Up Microsoft Motion OpenGL Particle Problem PS3 Remix Retro script Slides Sound Systems Texture Ubuntu Video VirtualBox Wii Windows XBox

Gamercard

OpenR3dux

Misc.

Flattr this

RSS Feed

r3dux twitter feed



“It's easy to make a buck. It's a lot tougher to make a difference.”

 - Tom Brokaw

rss Comments rss valid xhtml 1.1 design by jide powered by Wordpress get firefox