Wednesday, August 29, 2007

Pointers in C#

Because i need conversions from and to pointers for arrays and structures, i made a little class that can to the job for me.

The most common problem is that all examples that I've found, copies arrays, or fills them up. But no examples of getting a pointer back into an array, without giving the startindex and count of the elements.

I made it possible to convert an array to pointer and visa versa, without those boundaries. You will have to use this class however to convert to and from the pointers. Because I add a 'delimiter' to the end of the data in the pointer.

I hope some of you can use the snippet(s) below. If so, let me know ;)

Regards


1: public static unsafe class Pointers

   2: {
   3:     #region To Pointer
   4:  
   5:     /// <summary>
   6:     /// Converts an array to a pointer.
   7:     /// Ex. int[] to int*
   8:     /// </summary>
   9:     /// <param name="array">Array to convert.</param>
  10:     /// <returns>Pointer to array</returns>
  11:     public static int* ConvertArrayToPointer(int[] array)
  12:     {
  13:         fixed (int* pArray = array)
  14:         {
  15:             int* reference = pArray;
  16:             *(reference + array.Length) = int.MinValue;
  17:             return pArray;
  18:         }
  19:     }
  20:  
  21:     /// <summary>
  22:     /// Converts an array to a pointer.
  23:     /// Ex. uint[] to uint*
  24:     /// </summary>
  25:     /// <param name="array">Array to convert.</param>
  26:     /// <returns>Pointer to array</returns>
  27:     public static uint* ConvertArrayToPointer(uint[] array)
  28:     {
  29:         fixed (uint* pArray = array)
  30:         {
  31:             uint* reference = pArray;
  32:             *(reference + array.Length) = uint.MaxValue;
  33:             return pArray;
  34:         }
  35:     }
  36:  
  37:     /// <summary>
  38:     /// Converts an array to a pointer.
  39:     /// Ex. char[] to char*
  40:     /// </summary>
  41:     /// <param name="array">Array to convert.</param>
  42:     /// <returns>Pointer to array</returns>
  43:     public static char* ConvertArrayToPointer(char[] array)
  44:     {
  45:         fixed (char* pArray = array)
  46:         {
  47:             char* reference = pArray;
  48:             *(reference + array.Length) = char.MinValue;
  49:             return pArray;
  50:         }
  51:     }
  52:  
  53:     #endregion
  54:  
  55:     #region FromPointer
  56:  
  57:     /// <summary>
  58:     /// Converts a pointer to an array to a managed array.
  59:     /// Ex. int* to int[]
  60:     /// </summary>
  61:     /// <param name="array">Pointer to an array to convert</param>
  62:     /// <param name="startIndex">StartIndex from where to convert</param>
  63:     /// <param name="count">Number of elements to include in result-array</param>
  64:     /// <returns>Requested array of elements.</returns>
  65:     public static int[] ConvertPointerToArray(int* array, int startIndex, int count)
  66:     {
  67:         int[] data = new int[count -startIndex];
  68:  
  69:         for (int i = startIndex; i < count; i++)
  70:         {
  71:             int tempVal = *(array + i);
  72:             data[i] = tempVal;
  73:         }
  74:         return data;
  75:     }
  76:  
  77:     /// <summary>
  78:     /// Converts a pointer to an array to an array.
  79:     /// This array has an delimitor at the end to know when to stop converting.
  80:     /// </summary>
  81:     /// <param name="array">Pointer to an array</param>
  82:     /// <returns>Requested array</returns>
  83:     public static int[] ConvertPointerToArray(int* array)
  84:     {
  85:         List<int> data = new List<int>();
  86:  
  87:         int index = 0;
  88:         int tempVal = *(array + index++);
  89:         data.Add(tempVal);
  90:  
  91:         while (tempVal != int.MinValue)
  92:         {
  93:             tempVal = *(array + index++);
  94:             if(tempVal != int.MinValue)
  95:                 data.Add(tempVal);
  96:         }
  97:  
  98:         return data.ToArray();
  99:     }
 100:  
 101:     /// <summary>
 102:     /// Converts a pointer to an array to a managed array.
 103:     /// Ex. char* to char[]
 104:     /// </summary>
 105:     /// <param name="array">Pointer to an array to convert</param>
 106:     /// <param name="startIndex">StartIndex from where to convert</param>
 107:     /// <param name="count">Number of elements to include in result-array</param>
 108:     /// <returns>Requested array of elements.</returns>
 109:     public static char[] ConvertPointerToArray(char* array, int startIndex, int count)
 110:     {
 111:         char[] data = new char[count - startIndex];
 112:  
 113:         for (int i = startIndex; i < count; i++)
 114:         {
 115:             char tempVal = *(array + i);
 116:             data[i] = tempVal;
 117:         }
 118:         return data;
 119:     }
 120:  
 121:     /// <summary>
 122:     /// Converts a pointer to an array to an array.
 123:     /// This array has an delimitor at the end to know when to stop converting.
 124:     /// </summary>
 125:     /// <param name="array">Pointer to an array</param>
 126:     /// <returns>Requested array</returns>
 127:     public static char[] ConvertPointerToArray(char* array)
 128:     {
 129:         List<char> data = new List<char>();
 130:  
 131:         int index = 0;
 132:         char tempVal = *(array + index++);
 133:         data.Add(tempVal);
 134:  
 135:         while (tempVal != char.MinValue)
 136:         {
 137:             tempVal = *(array + index++);
 138:             if (tempVal != char.MinValue)
 139:                 data.Add(tempVal);
 140:         }
 141:  
 142:         return data.ToArray();
 143:     }
 144:  
 145:     /// <summary>
 146:     /// Converts a pointer to an array to a managed array.
 147:     /// Ex. uint* to uint[]
 148:     /// </summary>
 149:     /// <param name="array">Pointer to an array to convert</param>
 150:     /// <param name="startIndex">StartIndex from where to convert</param>
 151:     /// <param name="count">Number of elements to include in result-array</param>
 152:     /// <returns>Requested array of elements.</returns>
 153:     public static uint[] ConvertPointerToArray(uint* array, int startIndex, int count)
 154:     {
 155:         uint[] data = new uint[count - startIndex];
 156:  
 157:         for (int i = startIndex; i < count; i++)
 158:         {
 159:             uint tempVal = *(array + i);
 160:             data[i] = tempVal;
 161:         }
 162:         return data;
 163:     }
 164:  
 165:     /// <summary>
 166:     /// Converts a pointer to an array to an array.
 167:     /// This array has an delimitor at the end to know when to stop converting.
 168:     /// </summary>
 169:     /// <param name="array">Pointer to an array</param>
 170:     /// <returns>Requested array</returns>
 171:     public static uint[] ConvertPointerToArray(uint* array)
 172:     {
 173:         List<uint> data = new List<uint>();
 174:  
 175:         int index = 0;
 176:         uint tempVal = *(array + index++);
 177:         data.Add(tempVal);
 178:  
 179:         while (tempVal != uint.MaxValue)
 180:         {
 181:             tempVal = *(array + index++);
 182:             if (tempVal != uint.MaxValue)
 183:                 data.Add(tempVal);
 184:         }
 185:  
 186:         return data.ToArray();
 187:     }
 188:  
 189:     #endregion
 190:  
 191:     #region Internal Pointers
 192:  
 193:     /// <summary>
 194:     /// Converts a structure to a IntPtr
 195:     /// </summary>
 196:     /// <typeparam name="T">Type of structure</typeparam>
 197:     /// <param name="value">Struct to convert</param>
 198:     /// <returns>IntPtr of the struct</returns>
 199:     public static IntPtr ToIntPtr<T>(T value)
 200:         where T : struct
 201:     {
 202:         IntPtr pointer = Marshal.AllocHGlobal(Marshal.SizeOf(value));
 203:         Marshal.StructureToPtr(value, pointer, true);
 204:         return pointer;
 205:     }
 206:  
 207:     /// <summary>
 208:     /// Converts an IntPtr to a struct
 209:     /// </summary>
 210:     /// <typeparam name="T">Type of structure</typeparam>
 211:     /// <param name="pointer">Internal Pointer of structure</param>
 212:     /// <returns>Requested struct</returns>
 213:     public static T FromIntPtr<T>(IntPtr pointer, bool destruct)
 214:         where T : struct
 215:     {
 216:         T structure = (T)Marshal.PtrToStructure(pointer, typeof(T));
 217:         if (destruct)
 218:         {
 219:             Marshal.Release(pointer);
 220:         }
 221:         return structure;
 222:     }
 223:  
 224:     #endregion
 225:  
 226:  
 227:     public static void DoTest(int[] array)
 228:     {
 229:         // Make a pointer of the array
 230:         int* pointer = Pointers.ConvertArrayToPointer(array);
 231:         // Make an array of the pointer-data
 232:         int[] data = Pointers.ConvertPointerToArray(pointer, 0, array.Length);
 233:         // Same as above, but without bounderies.
 234:         data = Pointers.ConvertPointerToArray(pointer);
 235:  
 236:         // Make us a testing structure
 237:         TestStruct ts = new TestStruct("This is my teststruct");
 238:         // Convert the struct to an IntPtr
 239:         IntPtr ptr = ToIntPtr<TestStruct>(ts);
 240:         // Convert IntPtr back to a struct.
 241:         // Don't forget the destruction, for memory leak prevention!
 242:         TestStruct test = FromIntPtr<TestStruct>(ptr, true);
 243:     }
 244:  
 245:     internal struct TestStruct
 246:     {
 247:         private string _msg;
 248:  
 249:         public TestStruct(string message)
 250:         {
 251:             _msg = message;
 252:         }
 253:  
 254:         public string Msg
 255:         {
 256:             get { return _msg; }
 257:             set { _msg = value; }
 258:         }
 259:     }
 260: }

Friday, August 17, 2007

Picture SOM

Howdy,

This article is about the use of SOM's, I've made an interesting application to demonstrate the use of this self organizing maps.

This program loads pictures and groups them with each other.
So that matching or simular pictures are put together.
I saw this once on a longhorn demo, and I wanted to know how this stuff worked.

Step 1:

So the first step of this project was to download hot women, not nude, otherwise I get in trouble with my girlfriend ;), I found a site (trough another article also) fobpro where you can download thumbnails of woman in simular positions, and with simular backgrounds etc. Which is excellent to test on.

Step 2:

Step 2 was getting data from pictures.
I began with getting the histogram of an image. (greyscale and hsl), an histogram is actually a series of buckets where you put values in, meaning, you look at every pixel and calculate a value from it, say from 0 to 255, then you take for example 16 buckets, with range 255 / 16 and you put the pixel-values in the right bucket, at the end we have the counts of the ammount of values that are in each bucket, and we have our histogram. These 'buckets' will be our inputs for a neural network later on.

Second thing I did was taking Color and Texture area's from the image, in this case, we devide the image (thumbnailed to a size of 50x50) in 9 pieces. (Note that overlapping areas would be better) For each area, we calculate the average color, and texture value ( high value = noisy area, low value is not-noisy area )
This results in 9 values / picture. So 9 input vectors.



On the pic you see on the left the histogram of the image, and the red lines are the area's where i can take the texture or color values from.

I made a library that can fetch these values or combination of, and put them in an input vector. So if we take a histogram and an area, then we have 16 + 9 inputs.

Step 3:

Here I made loaded and thumbnailed the images into memory, and made input vectors for each image, so that at the end I have a list of input vectors to train the neural SOM network with.

As feature map i took a matrix of 10 by 10, and i trained the network with a series of 200 pictures from fobpro.
This way we have only an average of 2 pictures / mapnode.

Step 4:

In step 4 i made the GUI, providing possibilities to manage which types of histograms or area's we would like to train on, also the map-size, and a few buttons to select the input directory, to train the network and to provide an image that's not in the trained collection.

Step 5:

Testing the application :)

First i selected an input directory, and trained the network.
For the thumbnails, it took a few minutes.



After the training has been done, we get the pictures distributed over the mapnodes, is the matrix of buttons on the right.
The number on the buttons tells me how many pictures are under each node.

I've selected the top-left node, and you see the simular pictures found under this node (3 pictures):



Now we take a look the the top-right node, which has 4 nice pictures below it:



If we look at the bottom-left node with 4 pixtures, then we see that the pictures
are of the same model in the same clothes, but in other positions, so it works!



This is the bottom-right node of 3 pictures:



Now let's test that the network really can group the pictures together!
I fed the network an image that was not in the collection of the training data,
and look, it has found the right picture-set! In the first set, there is another girl with the same clothes on, with different hair, the network looks at color and texture, histograms and areas, in this case the histogram had 64 buckets, and the area's 9 divisions. So the input vector for this network was 64 + 64 + 9 + 9 nodes.

The other girl matched the texture area's and texture histogram pretty closely, also the color histogram is almost the same, and the color area's which are averages will be almost the same, so it's correct that the girl is in this collection.



Let's feed another one:



Conclusion:

The SOM network can do amazing stuff, there are tons of other applications where you can use it for. The training did not take very long, because all thumbs are resized before getting the data from it.

The next step would be face recognition, and edge detection, so that I can actually filter persons out of the collection, that would be really cool ;)

I also found some information about hierachically growing SOM networks, that way the network has a granularity for the spreading of the nodes.
For example if we take the color som, and we get different shades of red, then the shades of red would come under a node which is also a som network, that way we have toplevel red, green, etc, and sublevel under the red, the shades of red, this way we can group even better.

The next thing i'm going to try is to finetune this application and make it a WCF service (.NET 3.0) and feed it my entire picture collection, so that I can make a kind of picasa form grouping pictures :)

Now, it's just therapy to learn about A.I and make some pretty cool thing with it, in a pretty-learning environment. Not that the pictures supplied here are only for educational purposes :)

I hope you got somewhat wiser about neural networks, and the possibilies... I will come back later with more fun stuff :)

Regards,

Whizzo

Color SOM

With this article i would like to demostrate the Color SOM (Self Organizing Map)

The basics of this application comes to creating and training a neural network that groups colors with eachother.

The neural network itself is a SOM (Self Organizing Map) or SON (Self Organizing Network) map. It has 3 input nodes, and in this example a 40 by 40 matrix of output nodes. In this network there are no 'hidden' layers.

The architecture looks like this:



We have our input values, (RGB color), in this case 3 inputs, so the input vector is R,G,B (values from 0 to 255)
We also have a feature map of size X and Y, (40 x 40 in my examples)
Every node of this feature map has a feature vector to an input-node.
This is called the feature vector, and every vector has a weight (Wij)

Now if we look to what I fabricated, then we have to initialize the weights of the vectors connecting each input-node to each output-node with gradient values (left pic) or with random values (right pic).



Then I made a data-set where I trained the network with.
In my example i have trained a network with 9 colors, and a one with random colors ( with 1600 unique colors in it).
While the network is training, it is going to adjust the weights of the feature vectors so that a 'grouping' is brought to life (using epoch- and sigmoid functions etc, look in "my links" to find a tutorial on ai-junkie, which is pretty good).

If I initialize the "feature vector-weights" with gradient values
((0,0,0) on the top-left and (255,255,255) on the bottom-right)
then we get, with the same map-size and color inputs offcourse, always the same end-result if the network is fully trained.

Example of training a gradient colormap with 9 colors as input dataset:



Example of training a gradient colormap (40x40) with 1600 unique colors:



If I train the map with random initialization and random colors as inputs,
then I get a simular result.
When I do it with 9 colors and random initialization, then the 9 colors will be on another place each time we (re)train the network.

Now, think about what for use this could have?
The network groups simular colors in the case, bottomline is, that it can group values with each other, I will show you later on a nice example where I used this technique to group pictures with each other in a nice learning environment ;)

I hope I could give you a little more information or insight about is topic, I will surely discuss this later with a little more depth.

If you don't know anything of A.I, then i strongly suggest to take a look at my links, and follow a couple of tutorials, you will be on your way pretty soon.

Regards,

Whizzo

Thursday, August 16, 2007

Artificial Intelligence Links

Because i don't go deep on the fundamentals of A.I., I want to give you a couple of handy links, where you can learn more about Artificial Intelligence and Neural Networks.

Here are the places where i've been to gather some information:

Artificial Intelligence

Howdy,

Since a while ago i gained interest in A.I., I'm interested in it since a long time, but never had the time to really get started with it.

But hippieyee, when it was my birthday, a bought a couple of books and actually read them also. Then the A.I vibes came really to life :)

After reading the book(s) i started to implement a framework for neural networks,
because the N.N. part of A.I interests me alot.
It's pretty cool how many simularities you can see in it, in relation with a human brain.

Now, i learned that there are many different kinds of neural nets, with the framework, based on explenation from a book, i think i managed to get the biggest kinds implemented, that's ADELINE, BackPropagation, BAM and SOM (or SON).

If you look at the working of those networks, you'll see that there are certain simularities in it. I'll go deeper on that later.

My Object Oriented Neural Network Framework looks like this:



Like you see i only show the classnames, because the complete content doesn't fit on the screen.

The thing that all N.N. have in common is a basenode, from there we make a feedforward-node, SON-Node (for self organizing maps), InputNode for giving input values and a baseNetwork, that actually consists of BaseNodes.



Then we have the BaseLink, it's a link between the Neuron-nodes (a neuron is an element of a Neural Network). We have the adeline links, Backprop links with the epochlink (for learning) and the BAM and SON links.



With this construction we can make all combinations of neural networks. Maybe you will have to inherit something to extend functionality.

The usual practices to learn something about neural networks (which i encountered the most) are:

  • Self Origanizing Nets

  • Color SOM

  • XOR problem

  • ... there are others also offcourse.


I also made a deviation, that i picked op on www.generation5.org, and that's detecting picture simularity with neural networks.

I'll post more on those subjects later.

Regards,

F.