Showing posts with label video. Show all posts
Showing posts with label video. Show all posts

Sunday, December 28, 2014

Fun with Pixel Shaders

One of the things that saved my ass for MIT Mini Maker Faire was SlimDX, a modern (.NET 4.0) replacement for Microsoft's obsolete Managed DirectX framework. I was only using it to replace the managed DirectInput wrapper I had for interfacing to USB HID joysticks for controlling Twitch and 4pcb. For that it was almost a drop-in replacement. But the SlimDX framework also allows for accessing almost all of DirectX from managed .NET code.

I've never really messed with DirectX, even though at one point long ago I wanted to program video games and 3D stuff. The setup always seemed daunting. But with a managed .NET wrapper for it, I decided to give it a go. This time I'm not using it to make video games, though. I'm using it to access GPU horsepower for simple image processing.

The task is as follows:

The most efficient way to capture and save images from my USB3.0 camera is as raw images. The file is a binary stream of 8-bit or 12-bit pixel brightnesses straight from the Bayer-masked sensor. If one were to convert these raw pixel values to a grayscale image, it would look like this:

Zoom in to see the checkerboard Bayer pattern...it's lost a bit in translation to a grayscale JPEG, but you can still see it on the car and in the sky.


The Bayer filter encodes color not on a per-pixel basis, but in the average brightness of nearby pixels dedicated to each color (red, green, and blue). This always seemed like cheating to me; to arrive at a full color, full resolution image, 200% more information is generated by interpolation than was originally captured by the sensor. But the eye is more sensitive to brightness than to color, so it's a way to sense and encode the information more efficiently.

Anyway, deriving the full color image from the raw Bayer-masked data is a bit of a computationally-intensive process. In the most serial implementation, it would involve four nested for loops to scan through each pixel looking at the color information from its neighboring pixels in each direction. In pseudo-code:

// Scan all pixels.
for y = 0 to (height - 1)
 for x = 0 to (width - 1)
  
  Reset weighted averages.  

  // Scan a local window of pixels.
  for dx = -N to +N
   for dy = -N to +N
    
    brightness = GetBrightness(x+dx, y+dy)
    Add brightness to weighted averages.
   
   next
  next

  Set colors of output (x, y) by weighted averages.

 next
next

The window size (2N+1)x(2N+1) could be 3x3 or 5x5, depending on the algorithm used. More complex algorithms might also have conditionals or derivatives inside the nested for loop. But the real computational burden comes from serially scanning through x and y. For a 1920x1080 pixel image, that's 2,073,600 iterations. Nest a 5x5 for loop inside of that and you have 51,840,000 times through. This is a disaster for a CPU. (And by disaster, I mean it would take a second or two...)

But the GPU is ideally-suited for this task since it can break up the outermost for loops and put them onto a crapload of miniature parallel processors with nothing better to do. This works because each pixel's color output is independent - it depends only on the raw input image. The little piece of software that handles each pixel's calculations is called a pixel shader, and they're probably the most exciting new software tool I've learned in a long time.

For my very first pixel shader, I've written a simple raw image processor. I know good solutions for this already exist, and previously I would use IrfanView's Formats plug-in to do it. But it's much more fun to build it from scratch. I'm sure I'm doing most of the processing incorrectly or inefficiently, but at least I know what's going on under the hood.

The shader I wrote has two passes. The first pass takes as its input the raw Bayer-masked image and calculates R, G, and B values for each pixel based on the technique presented in this excellent Microsoft Research technical article. It then does simple brightness, color correction, contrast, and saturation adjustment on each pixel. This step is a work-in-progress as I figure out how to define the order of operations and what techniques work best. But the framework is there for any amount of per-pixel color processing. One nice thing is that the pixel shader works natively in single-precision floating point, so there's no need to worry about bit depth of the intermediate data for a small number of processing steps.


The second pass implements an arbitrary 5x5 convolution kernel, which can be used for any number of effects, including sharpening. The reason this is done as a second pass is because it requires the full-color output image of the first pass as its input. It can't be done as part of a single per-pixel operation with only the raw input image. So, the first pass renders its result to a texture (the storage type for a 2D image), and the second pass references this texture for its 5x5 window. The output of the second pass can either be rendered to the screen, or to another texture to be saved as a processed image file, or both.

What a lovely Seattle winter day.
Even though the pixel shader does all of the exciting work, there's still the matter of wrapping the whole thing in a .NET project with SlimDX providing the interface to DirectX. I did this with a simple VB program that has a viewport, folder browser, and some numeric inputs. For my purposes, a folder full of raw images goes together as a video clip. So being able to enumerate the files, scan through them in the viewer, and batch convert them to JPEGs was the goal.

Hrm, looks kinda like all my other GUIs...

As it turns out, the pixel shader itself is more than fast enough for real-time (30fps) processing. The time consuming parts are loading and saving files. Buffering into RAM would help if the only goal was real-time playback, but outputting to JPEGs is never going to be fast. As it is, for a 1920x1200 image on my laptop, the timing is roughly 30ms to load the file, an immeasurably short amount of time to actually run both pixel shader passes, and then 60ms to save the file. To batch convert an entire folder of 1000 raw images to JPEG, including all image processing steps, took 93s (10.75fps), compared to 264s (3.79fps) in IrfanView.

Real-time scrubbing on the MS Surface Pro 2, including file load and image processing, but not including saving JPEGs.

There are probably ways to speed up file loading and saving a bit, but even as-is it's a good tool for setting up JPEG image sequences to go into a video editor. The opportunity to do some image processing in floating point, before compression, is also useful, and it takes some of the load off the video editor's color correction.

I'm mostly excited about the ability to write GPU code in general. It's a programming skill that still feels like a superpower to me. Maybe I'll get back into 3D, or use it for simulation purposes, or vision processing. Modern GPUs have more methods available for using memory that make the cores more useful for general computing, not just graphics. As usual with new tools, I don't really know what I'll use it for, I just know I'll use it.

If you're interested in the VB project and the shader source (both very much works-in-progress), they are here:

VB 2012 Project: RawView_v0_1.zip
Built for .NET 4.0 64-bit. Requires the SlimDX SDK.

HLSL Source: debayercolor.fx

P.S. I chose DirectX because it's what I have the most experience with. (I know somebody will say, "You should use OpenGL.") I'm sure all of this could be done in OpenGL / GLSL as well.

Wednesday, April 24, 2013

NAB 2013: Where are the gyros? / New video editing software.

A couple weeks ago I was at the NAB Show with Freefly for the MōVI launch, the first product I've helped work on at the new job. That meant spending a lot of time doing the chicken head dance and explaining to people that there aren't actually spinning flywheel gyros on things anymore...


It's a camera gimbal, similar to what would be mounted to a helicopter or multirotor, that you can also carry around in your hands while it stabilizes the camera. (If you read this blog, I'm sure you know all about control systems and active stabilization so this probably doesn't amaze you as much as it still amazes the non-technical public...)

Since I spent nine hours a day at the booth talking to people about gyros (Wait, is this Maker Faire all over again?), I didn't get as much time as I would have liked to wander around this expansive tradeshow, which covered three whole buildings. (It's about 10x the size of the EVER Monaco Expo / car show I've been to a couple times.) There were definitely a lot of camera-carrying multirotors this year.

Here is just one of many....
I was mostly impressed by how it folded up.
There was also a giant two-story indoor flying tube where DJI showed off some of their products. And several outdoor booths with all manner of flying cameras ranging from GoPros up to big-budget cinema cameras like the RED Epic. Speaking of RED, they had a clean room installed on the show floor where they were doing live sensor upgrades to their new 6K / 100fps sensor. (So to watch the video it produces, you need nine HD screens in a 3x3 grid and it has to play in 4x slow motion...)

Most of the camera stuff at NAB is way outside my budget, but one thing that excited me was the Blackmagic Pocket Cinema Camera, which was also just announced at the show. It shoots raw or high bit-rate compressed 1080p video onto normal (but expensive/fast) SD cards. If I were planning to upgrade from my Panasonic HD camcorder in the near future, the $995 price is not that bad. The only real problem for me is that it weighs 355g, (maybe less than 500g with a small lens?), so I would be instantly tempted to put it on a multirotor, and then I would be at risk of crashing it all the time. I doubt it's as durable as my GoPro...

I think of all the NAB Show things I saw later read about on the internet, the one that caught my attention most was new, free-ish video editing software called Lightworks, by EditShare. I was pretty disappointed that the new Windows 7 edition of Windows Live Movie Maker is a stripped-down piece of crap, even compared to the at least somewhat functional WMM from the Windows XP era. (The old WMM had an active user community with lots of third-party add-ons for people who wanted to use it as an actual tool.) So a new piece of editing software that doesn't cost hundreds or thousands of dollars was definitely something I wanted to try out. And it looks like a very nice tool.

Maybe I was attracted to Lightworks because the desktop layout is almost indistinguishable from that of a CAD program:



Which of these is the video editing software and which makes 3D models?
Despite being a relatively new program (I'm using the Windows beta version), the interface feels very smartly developed and intuitive. Combined with a set of quick-start video tutorials, I didn't have to spend much time at all to learn how to do simple things like make clips, arrange a timeline, trim ins and outs, work with audio tracks, and add simple effects like fades and dissolves. The options for moving a cut are particularly nice: you can make clips on either side of the cut longer or shorter independently or have one get longer and the other get shorter at the same time (to keep sync). Maybe this is a pretty standard feature in professional editing software, but it's my first time using it and I can't imagine how to ever work without it now.

The only part of the workflow that was not quick and easy was exporting video. Importing from various formats works great, but exporting to something other than a hardcore (and huge) editing format was a challenge for me. H.264 support is through Quicktime, maybe? The new beta version may support native H.264 without Quicktime but I failed to make that work. So in addition to buying the Pro version of the software, you have to also have Quicktime Pro to create H.264 files? And then after all that the H.264 output had no audio (a known bug). Luckily, you can export the audio track as a .WAV, so after fooling around for a few hours to get the H.264 export to work, I still had to use my trusty all-purpose MEncoder shell program to reattach the audio.

I'm sure the export quirks will be worked out in newer versions of Lightworks, though. If the software stays the same price ($60 for the Pro version with full codec support, including H.264?), then it's an amazing deal for a real editing tool.

To test out the software, I've finally gotten around to collecting up all my random GoPro clips from around MIT, flying with my Talon quad. No fancy stabilized 3-axis gimbal for me (well, no gimbal at all...just taped to the bottom of the quad), so get ready for a rough ride:

Wednesday, November 26, 2008

Camera Purge

One of the benefits of having a video camera with a 30GB hard drive is that you can store 7 hours of video, but that also means that people leave a lot of raw video on it. (I say "people" because it's been a while since I've actually shot video with my own camera.) So to test my video converter and new computer, I took some of the left over clips from the Cap Kart project and clipped them together.

If you were wondering what NASA-like engineering procedures are employed in my summer projects, these should clear things up. Happy Thanksgiving!





Tuesday, November 11, 2008

30,000 Words per Second

If a picture is worth 1,000 words, it follows that video is worth roughly 30,000 words per second, right? (Which means that my S.B. thesis could have been summarized with approximately 7/10ths of a second of well-thought-out video.) I have been capturing my projects on video since I got my first DV camera in 11th grade. Short of a live demonstration, it's really the best way to show somebody what I've been working on. In fact, contrary to the rumors that I have turned into an Apple fanatic, the main reason I bought an iPod Touch is because I can now show people my pictures and video without taking out my laptop. That, and episodes of House look better on it than on TV.

But there are so many video formats: MPEG-2 from my camera, MOV and MPEG4 for iTunes, H.264, WMV for editing and showing my Windows friends. And occassionally I like to edit frame-by-frame with my own software. I have fought with codecs for years and previously used at least three different third-party tools to do video conversion. No more! The long weekend inspired me to take on one of my rare pure-software projects. (Last time this happened, I wrote a program to create photomosaics.) I think there is still a CS person hiding in the back of my head. Anyway, I present SCV, which, if you want, stands for "Shane Converts Video."


It's an MPlayer/MEncoder front-end. MEncoder is a great piece of software that was suggested to me for my video editing needs since it can convert between virtually any format. The one downside, for me anyway, was that it is made for/by Linux losers with nothing better to do than run things from the command line. Hear me out: In the 21st century, we have GUIs. So this simple VB (yes, VB) program takes care of all the command line switching and lets me get on with my life.

Ooooooh, code. It can handle the formats I work with most often (WMV, MPEG) in different flavors (AVI, MP4). It can actually make video that works on an iPod. It can both extract frames to JPEGs and recombine JPEG folders into video. It can trim clips. And it can strip/merge audio. I'm sure there's tons more I could do with it, but that's all I need and my software projects are pretty much driven by necessity. If you want to play around with the source or somehow think the executable will actually run on your machine (needs .NET Framwork 2.0 and a working version of MPlayer, at least), here they are:

http://web.mit.edu/scolton/www/scv.zip
http://web.mit.edu/scolton/www/scv.exe

And if you want to see why I spent part of a four day weekend coding, check out my TechTV collection:

http://scolton.techtv.mit.edu

Monday, October 13, 2008

Time Warp

Time Warp, the new Discovery Channel show that was partially filmed in the Edgerton Center (where I work often) at MIT, premiers this week. Their cameras are very nice, but a while back I wondered what kind of high speed work you could do on a budget. Turns out there are now a few consumer-level cameras that can shoot at relatively high speeds. One is the Casio EX-F1 (and its newer, cheaper cousin the EX-FH20). Here is a compilation of random things shot with a borrowed EX-F1 and finger in one day: