locked
Guy seeks matrix convolution RRS feed

  • Question

  • User1240398938 posted

    Hi Guys.

    As a newbie to the world of dotNet and GDI, I was wondering if there's a class in the 1.1 framework that does matrix convolutions? Say what? Nope, it's nothing to do with 'that' movie franchise. What I need is a way of performing image manipulation; sharpening, bluring,  embossing (like you find in photoshop), that uses the sexy but code intensive technique of matrix convolution. And I do not want to go creating my own convolution component if there's one already out there. Any of you code bandits heard of anything like that? One that's free?

    Andy

    Monday, August 8, 2005 2:09 PM

All replies

  • User-1750044441 posted
    There's nothing built into the GDI+ libraries for what you're talking about.  They do have a Matrix class, but that only deals with pixel manipulations such as rotating or resizing an image.

    However, a lot of folks have written their own homegrown versions, most of which are fairly flexible.  I based mine off of the information contained in this guy's articles over on CodeProject.  Here's the link: http://www.thecodeproject.com/script/articles/list_articles.asp?userid=6556.

    In particular, check out his Image Processing for Dummies with C# article series.  The third article talks about what you're looking for ...

    Jason

    Tuesday, August 9, 2005 2:30 PM
  • User1240398938 posted

    Jason, thanks for the reply and the link!

    There's some interesting background stuff in those articles,  and it's always nice to get someone elses perspective on the solution. GDI seems to do everything that you don't need it to do.

    Time to dust off the coding books!!!

    Thanks again,

    AJB

    Wednesday, August 10, 2005 10:31 AM
  • User-1750044441 posted
    I agree, there is a lot of useful information in those articles (and actually all over CodeProject).  The actual solutions and code provided were not quite what I was looking for, I wanted something a little more re-usable, and I didn't want to use unmanaged code.

    I used that as a base and made it a little more modular and rewrote most of it, but the general principle is the same.  Also, the matrices provided for the different convolutions were very helpful, as I have little experience in that aspect of the graphics world!

    I ended up with a separate Matrix class of my own that did calculations for me.  I simply extend the class with the filter type I'd like (i.e., GuassianBlurMatrix) and run that "filter" through my image utility class.  The utility class reads the image into it's own matrix and feeds that to the GuassianBlurMatrix, which performs the calculation and returns the new value back out.

    Works okay for the most part.  The speed seems comparible to what is in the articles, but it is still slow.  Photoshop is much faster ... when I get some more time I'm going to look into optimizing the whole process some more.

    Anyway, I'm rambling ... good luck!

    Wednesday, August 10, 2005 12:10 PM
  • User1240398938 posted
    There's certainly some good first principles in those articles - and I thank the author for that.

    I agree with your point about the slowness. Reverse engineering this guys code reveals an awesome number of multiplications - per pixel, per RGB layer! Oooch. He must have a dual-Pentium server ;-)

    Thinks... if the numbers to multiply are integers and they are working on bytes capped to a maximum of #FF, then maybe some bitwise processing would be more efficient. Maybe?

    Thanks for your input.

    AJB
    Wednesday, August 10, 2005 2:17 PM
  • User-1750044441 posted
    I used bitwise shifting to grab and set my RGB values from the pixel.

    //This isn't a code snippet, just a bit I typed off the top of my head ...
    uint color = matrix[0, 0]; //Top left pixel
    byte r = color >> 16;
    byte g = (color >> 8) & 255;
    byte b = color & 255;

    I also have code to handle colors with more than 32bpp which involve a little more shifting around, but they're the same principle in essence ...

    Since I wanted to avoid the unsafe code, I used the System.Runtime.InteropServices.Marshal.Copy() method to move the data into an array (versus using pointers in an unsafe block).

    I've been meaning to go through and do some performance tests to see just how inefficient this is versus the unsafe block, but haven't really gotten around to it.  I know there's definitely a performance hit, though ...

    Friday, August 12, 2005 1:01 PM
  • User1240398938 posted

    Thanks for sharing the code snippet and the tip about MarshalCopy. I'd never heard of that class member before!!! There's bound to be one, or two, or a dozen...

    The kind of thing that I'm pondering is replacing the standard multiplications (*) in the convultion routine with some 'hard core' bit multiplication. You know, the kind of thing that you would have learned on day two in computer science at school, and then promptly forgot because it was easier just to say
    10 let A = A * 2

    Bit multiply is just the same as an ordinary multiply...

    10101x
      1001
    =
    00010101+
    10101000
    =
    10111101

    In VB, for 'divide' there's the floating point version, the forward slash / and an integer divide, the back slash \. But what about multiply? Is there a very simply byte-times-byte version? I guess it's all down to the compiler.

    How, for example, is 10 * 12 enumerated at byte-code/machine level? Does the 'multiply' assume only integers (short/long/byte) or, does it handle the whole thing like two floating point numbers? And therefore, encure the processing overhead that-that entails. Not a problem with 10 multiplier operations, but with hundreds of thousands? 

    If a convultion matrix looks like this

    0 -9 0
    -9 8 -9
    0 -9 0

    and each pixel is a value from 0 to 255, then there is no point in doing some processor intensive maths if the whole thing can be made to run faster-cheaper using a 'bit' of school binary?

    AJB

    Saturday, August 13, 2005 11:32 AM