Mladen Prajdić Blog

Blog about stuff and things and stuff. Mostly about SQL server and .Net

Watershed Image Segmentation in C#

Lately I've been doing some image processing work using the most amazing AForge.NET open source library written in C#.

This library contains a whole bunch of useful filters you can play with but unfortunately it doesn't contain any filter for segmentation.

This is my implementation of Grayscale Immersion Watershed Segmentation in C# based on the

Vincent-Soille watershed algorithm which can be found in The Watershed Transform: Defnitions, Algorithms and Parallelization Strategies

paper by Jos B.T.M. Roerdink and Arnold Meijster on page 15. For watershed to work properly the areas you're trying to segment

have to be darker than the background. Blurring is also an important part of the image pre-processing since the algorithm

over segments non-blurred images. An example picture of watershed segmentation:

testPic testPic_Watershed
Original picture Segmented picture

 

using System;
using System.Collections.Generic;
using System.Text;

namespace Segmentation { public class WatershedPixel { public int X; public int Y; public int Height; // labels the pixel as belonging to a unique basin or as a part of the watershed line public int Label; // Distance is a work image of distances public int Distance;

    <span class="kwrd">public</span> WatershedPixel()
    {
        <span class="kwrd">this</span>.X = -1;
        <span class="kwrd">this</span>.Y = -1;
        <span class="kwrd">this</span>.Height = -1000;
        <span class="kwrd">this</span>.Label = -1000;
        <span class="kwrd">this</span>.Distance = -1000;
    }

    <span class="kwrd">public</span> WatershedPixel(<span class="kwrd">int</span> x, <span class="kwrd">int</span> y)
    {
        <span class="kwrd">this</span>.X = x;
        <span class="kwrd">this</span>.Y = y;
        <span class="kwrd">this</span>.Height = -1000;
        <span class="kwrd">this</span>.Label = WatershedCommon.INIT;
        <span class="kwrd">this</span>.Distance = 0;
    }

    <span class="kwrd">public</span> WatershedPixel(<span class="kwrd">int</span> x, <span class="kwrd">int</span> y, <span class="kwrd">int</span> height)
    {
        <span class="kwrd">this</span>.X = x;
        <span class="kwrd">this</span>.Y = y;
        <span class="kwrd">this</span>.Height = height;
        <span class="kwrd">this</span>.Label = WatershedCommon.INIT;
        <span class="kwrd">this</span>.Distance = 0;
    }

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">bool</span> Equals(Object obj)
    {
        WatershedPixel p = (WatershedPixel)obj;
        <span class="kwrd">return</span> (X == p.X &amp;&amp; X == p.Y);
    }

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> GetHashCode()
    {
        <span class="kwrd">return</span> X;
    }
    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> ToString()
    {
        <span class="kwrd">return</span> <span class="str">&#34;Height = &#34;</span> + Height + <span class="str">&#34;; X = &#34;</span> + X.ToString() + <span class="str">&#34;, Y = &#34;</span> + Y.ToString() + 

"; Label = " + Label.ToString() + "; Distance = " + Distance.ToString(); } }

<span class="kwrd">public</span> <span class="kwrd">class</span> WatershedGrayscale : FilterGrayToGray
{
    <span class="preproc">#region</span> Variables
    <span class="kwrd">private</span> WatershedPixel FictitiousPixel = <span class="kwrd">new</span> WatershedPixel();
    <span class="kwrd">private</span> <span class="kwrd">int</span> _currentLabel = 0;
    <span class="kwrd">private</span> <span class="kwrd">int</span> _currentDistance = 0;
    <span class="kwrd">private</span> FifoQueue _fifoQueue = <span class="kwrd">new</span> FifoQueue();
    <span class="rem">// each pixel can be accesesd from 2 places: a dictionary for faster direct lookup of neighbouring pixels </span>
    <span class="rem">// or from a height ordered list</span>
    <span class="rem">// sorted array of pixels according to height</span>
    <span class="kwrd">private</span> List&lt;List&lt;WatershedPixel&gt;&gt; _heightSortedList;
    <span class="rem">// string in the form &#34;X,Y&#34; is used as a key for the dictionary lookup of a pixel</span>
    <span class="kwrd">private</span> Dictionary&lt;<span class="kwrd">string</span>, WatershedPixel&gt; _pixelMap;
    <span class="kwrd">private</span> <span class="kwrd">int</span> _watershedPixelCount = 0;
    <span class="kwrd">private</span> <span class="kwrd">int</span> _numberOfNeighbours = 8;
    <span class="kwrd">private</span> <span class="kwrd">bool</span> _borderInWhite;
    <span class="kwrd">private</span> <span class="kwrd">int</span> _pictureWidth = 0;
    <span class="kwrd">private</span> <span class="kwrd">int</span> _pictureHeight = 0;
    <span class="preproc">#endregion</span>

    <span class="preproc">#region</span> Constructors
    <span class="kwrd">public</span> WatershedGrayscale()
        : <span class="kwrd">this</span>(8)
    {}

    <span class="kwrd">public</span> WatershedGrayscale(<span class="kwrd">int</span> numberOfNeighbours)
    {
        <span class="kwrd">if</span> (numberOfNeighbours != 8 &amp;&amp; numberOfNeighbours != 4)
            <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">&#34;Invalid number of neighbour pixels to check. Valid values are 4 and 8.&#34;</span>);
        _borderInWhite = <span class="kwrd">true</span>;
        _numberOfNeighbours = numberOfNeighbours;
        _heightSortedList = <span class="kwrd">new</span> List&lt;List&lt;WatershedPixel&gt;&gt;(256);
        <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; 256; i++)
            _heightSortedList.Add(<span class="kwrd">new</span> List&lt;WatershedPixel&gt;());
    }
    <span class="preproc">#endregion</span>

    <span class="preproc">#region</span> Properties
    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// number of neighbours to check for each pixel. valid values are 8 and 4</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">int</span> NumberOfNeighbours
    {
        get { <span class="kwrd">return</span> _numberOfNeighbours; }
        set
        {
            <span class="kwrd">if</span> (<span class="kwrd">value</span> != 8 &amp;&amp; <span class="kwrd">value</span> != 4)
                <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">&#34;Invalid number of neighbour pixels to check. Valid values are 4 and 8.&#34;</span>);
            _numberOfNeighbours = <span class="kwrd">value</span>;
        }
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Number of labels/basins found</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">int</span> LabelCount
    {
        get { <span class="kwrd">return</span> _currentLabel; }
        set { _currentLabel = <span class="kwrd">value</span>; }
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// True: border is drawn in white. False: border is drawn in black</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="rem">/// &lt;value&gt;&lt;/value&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">bool</span> BorderInWhite
    {
        get { <span class="kwrd">return</span> _borderInWhite; }
        set { _borderInWhite = <span class="kwrd">value</span>; }
    }
    <span class="preproc">#endregion</span>

    <span class="kwrd">private</span> <span class="kwrd">void</span> CreatePixelMapAndHeightSortedArray(BitmapData data)
    {
        _pictureWidth = data.Width;
        _pictureHeight = data.Height;
        <span class="rem">// pixel map holds every pixel thus size of (_pictureWidth * _pictureHeight)</span>
        _pixelMap = <span class="kwrd">new</span> Dictionary&lt;<span class="kwrd">string</span>, WatershedPixel&gt;(_pictureWidth * _pictureHeight);
        <span class="kwrd">unsafe</span>
        {                
            <span class="kwrd">int</span> offset = data.Stride - data.Width;
            <span class="kwrd">byte</span>* ptr = (<span class="kwrd">byte</span>*)(data.Scan0);

            <span class="rem">// get histogram of all values in grey = height</span>
            <span class="kwrd">for</span> (<span class="kwrd">int</span> y = 0; y &lt; data.Height; y++)
            {
                <span class="kwrd">for</span> (<span class="kwrd">int</span> x = 0; x &lt; data.Width; x++, ptr++)
                {
                    WatershedPixel p = <span class="kwrd">new</span> WatershedPixel(x, y, *ptr);
                    <span class="rem">// add every pixel to the pixel map</span>
                    _pixelMap.Add(p.X.ToString() + <span class="str">&#34;,&#34;</span> + p.Y.ToString(), p);
                    _heightSortedList[*ptr].Add(p);
                }
                ptr += offset;
            }
        }
        <span class="kwrd">this</span>._currentLabel = 0;
    }

    <span class="kwrd">private</span> <span class="kwrd">void</span> Segment()
    {            
        <span class="rem">// Geodesic SKIZ (skeleton by influence zones) of each level height</span>
        <span class="kwrd">for</span> (<span class="kwrd">int</span> h = 0; h &lt; _heightSortedList.Count; h++)
        {
            <span class="rem">// get all pixels for current height</span>
            <span class="kwrd">foreach</span> (WatershedPixel heightSortedPixel <span class="kwrd">in</span> _heightSortedList[h])
            {
                heightSortedPixel.Label = WatershedCommon.MASK;                    
                <span class="rem">// for each pixel on current height get neighbouring pixels</span>
                List&lt;WatershedPixel&gt; neighbouringPixels = GetNeighbouringPixels(heightSortedPixel);
                <span class="rem">// initialize queue with neighbours at level h of current basins or watersheds</span>
                <span class="kwrd">foreach</span> (WatershedPixel neighbouringPixel <span class="kwrd">in</span> neighbouringPixels)
                {
                    <span class="kwrd">if</span> (neighbouringPixel.Label &gt; 0 || neighbouringPixel.Label == WatershedCommon.WSHED)
                    {
                        heightSortedPixel.Distance = 1;
                        _fifoQueue.AddToEnd(heightSortedPixel);
                        <span class="kwrd">break</span>;
                    }                        
                }
            }
            _currentDistance = 1;
            _fifoQueue.AddToEnd(FictitiousPixel);
            <span class="rem">// extend basins</span>
            <span class="kwrd">while</span> (<span class="kwrd">true</span>)
            {
                WatershedPixel p = _fifoQueue.RemoveAtFront();
                <span class="kwrd">if</span> (p.Equals(FictitiousPixel))
                {
                    <span class="kwrd">if</span> (_fifoQueue.IsEmpty)
                        <span class="kwrd">break</span>;
                    <span class="kwrd">else</span>
                    {
                        _fifoQueue.AddToEnd(FictitiousPixel);
                        _currentDistance++;
                        p = _fifoQueue.RemoveAtFront();
                    }
                }
                List&lt;WatershedPixel&gt; neighbouringPixels = GetNeighbouringPixels(p);
                <span class="rem">// labelling p by inspecting neighbours</span>
                <span class="kwrd">foreach</span> (WatershedPixel neighbouringPixel <span class="kwrd">in</span> neighbouringPixels)
                {
                    <span class="rem">// neighbouringPixel belongs to an existing basin or to watersheds</span>
                    <span class="rem">// in the original algorithm the condition is:</span>
                    <span class="rem">//   if (neighbouringPixel.Distance &lt; currentDistance &amp;&amp; </span>
                    <span class="rem">//      (neighbouringPixel.Label &gt; 0 || neighbouringPixel.Label == WatershedCommon.WSHED))</span>
                    <span class="rem">//   but this returns incomplete borders so the this one is used                        </span>
                    <span class="kwrd">if</span> (neighbouringPixel.Distance &lt;= _currentDistance &amp;&amp; 
                       (neighbouringPixel.Label &gt; 0 || neighbouringPixel.Label == WatershedCommon.WSHED))
                    {
                        <span class="kwrd">if</span> (neighbouringPixel.Label &gt; 0)
                        {
                            <span class="rem">// the commented condition is also in the original algorithm </span>
                            <span class="rem">// but it also gives incomplete borders</span>
                            <span class="kwrd">if</span> (p.Label == WatershedCommon.MASK <span class="rem">/*|| p.Label == WatershedCommon.WSHED*/</span>) 
                                p.Label = neighbouringPixel.Label;
                            <span class="kwrd">else</span> <span class="kwrd">if</span> (p.Label != neighbouringPixel.Label)
                            {
                                p.Label = WatershedCommon.WSHED;
                                _watershedPixelCount++;
                            }
                        }
                        <span class="kwrd">else</span> <span class="kwrd">if</span> (p.Label == WatershedCommon.MASK)
                        {
                            p.Label = WatershedCommon.WSHED;
                            _watershedPixelCount++;
                        }
                    }
                    <span class="rem">// neighbouringPixel is plateau pixel</span>
                    <span class="kwrd">else</span> <span class="kwrd">if</span> (neighbouringPixel.Label == WatershedCommon.MASK &amp;&amp; neighbouringPixel.Distance == 0)
                    {
                        neighbouringPixel.Distance = _currentDistance + 1;
                        _fifoQueue.AddToEnd(neighbouringPixel);
                    }
                }
            }
            <span class="rem">// detect and process new minima at height level h</span>
            <span class="kwrd">foreach</span> (WatershedPixel p <span class="kwrd">in</span> _heightSortedList[h])
            {
                <span class="rem">// reset distance to zero</span>
                p.Distance = 0;
                <span class="rem">// if true then p is inside a new minimum </span>
                <span class="kwrd">if</span> (p.Label == WatershedCommon.MASK)
                {
                    <span class="rem">// create new label</span>
                    _currentLabel++;
                    p.Label = _currentLabel;
                    _fifoQueue.AddToEnd(p);
                    <span class="kwrd">while</span> (!_fifoQueue.IsEmpty)
                    {
                        WatershedPixel q = _fifoQueue.RemoveAtFront();
                        <span class="rem">// check neighbours of q</span>
                        List&lt;WatershedPixel&gt; neighbouringPixels = GetNeighbouringPixels(q);
                        <span class="kwrd">foreach</span> (WatershedPixel neighbouringPixel <span class="kwrd">in</span> neighbouringPixels)
                        {
                            <span class="kwrd">if</span> (neighbouringPixel.Label == WatershedCommon.MASK)
                            {
                                neighbouringPixel.Label = _currentLabel;
                                _fifoQueue.AddToEnd(neighbouringPixel);
                            }
                        }
                    }
                }
            }
        }
    }

    <span class="kwrd">private</span> List&lt;WatershedPixel&gt; GetNeighbouringPixels(WatershedPixel centerPixel)
    {
        List&lt;WatershedPixel&gt; temp = <span class="kwrd">new</span> List&lt;WatershedPixel&gt;();
        <span class="kwrd">if</span> (_numberOfNeighbours == 8)
        {
            <span class="rem">/*</span>

CP = Center pixel (X,Y) – get all 8 connected |-1,-1|0,-1|1,-1| |-1, 0| CP |1, 0| |-1,+1|0,+1|1,+1| */
// -1, -1 if ((centerPixel.X - 1) >= 0 && (centerPixel.Y - 1) >= 0) temp.Add(_pixelMap[(centerPixel.X - 1).ToString() + "," + (centerPixel.Y - 1).ToString()]); // 0, -1 if ((centerPixel.Y - 1) >= 0) temp.Add(_pixelMap[centerPixel.X.ToString() + "," + (centerPixel.Y - 1).ToString()]); // 1, -1 if ((centerPixel.X + 1) < _pictureWidth && (centerPixel.Y - 1) >= 0) temp.Add(_pixelMap[(centerPixel.X + 1).ToString() + "," + (centerPixel.Y - 1).ToString()]); // -1, 0 if ((centerPixel.X - 1) >= 0) temp.Add(_pixelMap[(centerPixel.X - 1).ToString() + "," + centerPixel.Y.ToString()]); // 1, 0 if ((centerPixel.X + 1) < _pictureWidth) temp.Add(_pixelMap[(centerPixel.X + 1).ToString() + "," + centerPixel.Y.ToString()]); // -1, 1 if ((centerPixel.X - 1) >= 0 && (centerPixel.Y + 1) < _pictureHeight) temp.Add(_pixelMap[(centerPixel.X - 1).ToString() + "," + (centerPixel.Y + 1).ToString()]); // 0, 1 if ((centerPixel.Y + 1) < _pictureHeight) temp.Add(_pixelMap[centerPixel.X.ToString() + "," + (centerPixel.Y + 1).ToString()]); // 1, 1 if ((centerPixel.X + 1) < _pictureWidth && (centerPixel.Y + 1) < _pictureHeight) temp.Add(_pixelMap[(centerPixel.X + 1).ToString() + "," + (centerPixel.Y + 1).ToString()]); } else { /* CP = Center pixel, N/A = not used (X,Y) – get only 4 connected | N/A |0,-1| N/A | |-1, 0| CP |+1, 0| | N/A |0,+1| N/A | */ // -1, 0 if ((centerPixel.X - 1) >= 0) temp.Add(_pixelMap[(centerPixel.X - 1).ToString() + "," + centerPixel.Y.ToString()]); // 0, -1 if ((centerPixel.Y - 1) >= 0) temp.Add(_pixelMap[centerPixel.X.ToString() + "," + (centerPixel.Y - 1).ToString()]); // 1, 0 if ((centerPixel.X + 1) < _pictureWidth) temp.Add(_pixelMap[(centerPixel.X + 1).ToString() + "," + centerPixel.Y.ToString()]); // 0, 1 if ((centerPixel.Y + 1) < _pictureHeight) temp.Add(_pixelMap[centerPixel.X.ToString() + "," + (centerPixel.Y + 1).ToString()]); } return temp; }

    <span class="kwrd">private</span> <span class="kwrd">void</span> DrawWatershedLines(BitmapData data)
    {
        <span class="kwrd">if</span> (_watershedPixelCount == 0)
            <span class="kwrd">return</span>;

        <span class="kwrd">byte</span> watershedColor = 255;
        <span class="kwrd">if</span> (!_borderInWhite)
            watershedColor = 0;
        <span class="kwrd">unsafe</span>
        {
            <span class="kwrd">int</span> offset = data.Stride - data.Width;
            <span class="kwrd">byte</span>* ptr = (<span class="kwrd">byte</span>*)(data.Scan0);

            <span class="kwrd">for</span> (<span class="kwrd">int</span> y = 0; y &lt; data.Height; y++)
            {
                <span class="kwrd">for</span> (<span class="kwrd">int</span> x = 0; x &lt; data.Width; x++, ptr++)
                {
                    <span class="rem">// if the pixel in our map is watershed pixel then draw it</span>
                    <span class="kwrd">if</span> (_pixelMap[x.ToString() + <span class="str">&#34;,&#34;</span> + y.ToString()].Label == WatershedCommon.WSHED)
                        *ptr = watershedColor;
                }
                ptr += offset;
            }
        }
    }

    <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> ProcessFilter(BitmapData imageData)
    {
        CreatePixelMapAndHeightSortedArray(imageData);
        Segment();
        DrawWatershedLines(imageData);
    }
}

<span class="kwrd">public</span> <span class="kwrd">class</span> FifoQueue
{
    List&lt;WatershedPixel&gt; queue = <span class="kwrd">new</span> List&lt;WatershedPixel&gt;();

    <span class="kwrd">public</span> <span class="kwrd">int</span> Count
    {
        get { <span class="kwrd">return</span> queue.Count; }
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> AddToEnd(WatershedPixel p)
    {
        queue.Add(p);
    }

    <span class="kwrd">public</span> WatershedPixel RemoveAtFront()
    {
        WatershedPixel temp = queue[0];
        queue.RemoveAt(0);
        <span class="kwrd">return</span> temp;
    }

    <span class="kwrd">public</span> <span class="kwrd">bool</span> IsEmpty
    {
        get { <span class="kwrd">return</span> (queue.Count == 0); }
    }

    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> ToString()
    {
        <span class="kwrd">return</span> <span class="kwrd">base</span>.ToString() + <span class="str">&#34; Count = &#34;</span> + queue.Count.ToString();
    }
}

<span class="kwrd">public</span> <span class="kwrd">class</span> WatershedCommon
{
    <span class="preproc">#region</span> Constants
    <span class="kwrd">public</span> <span class="kwrd">const</span> <span class="kwrd">int</span> INIT = -1;
    <span class="kwrd">public</span> <span class="kwrd">const</span> <span class="kwrd">int</span> MASK = -2;
    <span class="kwrd">public</span> <span class="kwrd">const</span> <span class="kwrd">int</span> WSHED = 0;
    <span class="preproc">#endregion</span>
}

}

 

This filter will also become the part of the AForge.NET library in the future so to use this algorithm you have to have it installed.

The performance can be improved as I've gone for the readability factor since performance wasn't very important on my project.

 

kick it on DotNetKicks.com
 

Legacy Comments


To Quyen
2008-08-23
re: Watershed Image Segmentation in C#
Please send me full codeproject. I need it. Thanks you very much

zol
2008-10-14
re: Watershed Image Segmentation in C#
can you explain how to run your coding...i got problem to run this code...tq

Mladen
2008-10-14
re: Watershed Image Segmentation in C#
you need to install the aforge.net library and that's about it.

zol
2008-10-27
re: Watershed Image Segmentation in C#
Hi, Im new to the area of image processing especially MRI image.I have some image
and want to classify them in different categories. Please guide me how i can achieve this. Hope you will guide me..

Mladen
2008-10-27
re: Watershed Image Segmentation in C#
hehe that's a huge area and i'm not really working with it anymore. i guess there are better resources out there for it.

ruaxauxi
2008-11-18
re: Watershed Image Segmentation in C#
Can you share this project?

Thanks.

Mlade
2008-11-18
re: Watershed Image Segmentation in C#
which project?

Nhan
2008-11-30
re: Watershed Image Segmentation in C#
I have some problems when complie this! Can you share this project ???Thanks a lot!

NOR HIDAYAH
2008-11-30
re: Watershed Image Segmentation in BORLAND C++
can u send me a source code for watershed segmented include the preprocessing process such as histogram equalization, median and gaussian filter and then followed by watershed process.

Mladen
2008-11-30
re: Watershed Image Segmentation in C#
@Nhan: what kind of problems?

@NOR HIDAYAH: i'm sure you can find all this on the net.


don omar
2008-12-03
re: Watershed Image Segmentation in C#
I got it to work. You need to use Aforce version 1.6.2 since the newer versions are not backwards compatible. The source does not have a main method, so you will have to make your own, and run ProcessFilter(BitmapData imageData) in that method. You have to feed it a BitmapData file, which you can make out of a bitmap file like this:

Bitmap bmp = new Bitmap("image.jpg");
WatershedGrayscale b = new WatershedGrayscale(8);

// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
bmp.PixelFormat);

after the image has been segmented, you have to unlock the bits of the bitmapdata varable using:

bmp.UnlockBits(bmpData);

then you can display the bmp file.

Also make sure that the image you feed it is in single channel, 8-bit grayscale depth. Also, to get the results as advertised above, you need to sufficiently blur the image. Notice that the segmented result is far blurrier than the original.

Good luck.

wasif
2008-12-19
re: Watershed Image Segmentation in C#
require a full code for segmentation oef an image

Mladen
2008-12-19
re: Watershed Image Segmentation in C#
good for you.

pavan
2008-12-25
re: Watershed Image Segmentation in C#
can u send ur code to me?? and guide me how to run this code

Mladen
2008-12-29
re: Watershed Image Segmentation in C#
just follow the instructions in the article.

pavan
2009-01-06
re: Watershed Image Segmentation in C#
did we've to install Aforge.NET in the same folder of .NET or we've to specify any path in the program because i'm getting four errors while compiling the program

Mladen
2009-01-07
re: Watershed Image Segmentation in C#
no you don't. you have to install the aforge and then include it's imaging dll into your piojects

pavan
2009-01-14
re: Watershed Image Segmentation in C#
i solve all the compile time error. Now, its giving run time error on Bitmap bmp = new Bitmap("image.jpg"); line. I've included main function in the same code and written the same code given above. Can u help me.

Mladen
2009-01-15
re: Watershed Image Segmentation in C#
well you have to specify the full path to your image...

Diego Salinas
2009-02-05
re: Watershed Image Segmentation in C#
AForge.Net is a great free open source imaging library for .Net. However, you can still improve performance using multithreading.
If you are interested in learning how to exploit multicore processors to speed up image processing using AForge.Net, you will find a great example using AForge.Net and multithreading to improve the performance in working with images and with multicore CPUs, in the book " C# 2008 and 2005 Threaded Programming: Beginners Guide", by Gaston Hillar, Packt Publishing - www.packtpub.com
It includes many exercises related to image management with multicore support. Highly recommended if you want to improve performance and UI responsiveness.
You can download the code from Packt's website. http://www.packtpub.com/beginners-guide-for-C-sharp-2008-and-2005-threaded-programming/book

There is also an article in Packt's website: http://www.packtpub.com/article/simplifying-parallelism-complexity-c-sharp

I bought the book last week and it helped me a lot in my image processing needs. Now, I can split an image in many parts using the code from the book and I can make it exploit my Core 2 Quad. My boss is impressed!

jyotirmoy pathak
2009-02-05
re: Watershed Image Segmentation in C#
hi i ve gone through ur progrm.......... actually m working in matrox software can u help me doing some codding in this platform for watersheding.......

Mladen
2009-02-05
re: Watershed Image Segmentation in C#
@rmoy pathak: I have no clue what matrox software is or how to code anything in it,

@Diego Salinas: thanx for the links.

jyotirmoy
2009-02-06
re: Watershed Image Segmentation in C#
ok..... thanks 4 ur reply.....

barry
2009-03-28
re: Watershed Image Segmentation in C#
HI thanks for the code ..could u tell me how to invoke the processfilter function and display the sgmented image. I am new to C#..thanks a lot!


Mladen
2009-03-30
re: Watershed Image Segmentation in C#
you have to use the free aforge.net library

armor
2009-05-21
re: Watershed Image Segmentation in C#
Thank you for the code!!! As other programmers I am having four errors when I try to run the example.
First I installed AForge.NET 2.0, then I create a new console project in VisualStudio 2008, then copy&paste and finally I added AForge references which are in the Realese folder and I put some using AForge; using AForge.Imaging

When I try to run these errors happen:

Error 1 The type or namespace name 'FilterGrayToGray' could not be found (are you missing a using directive or an assembly reference?)

Error 2 The type or namespace name 'BitmapData' could not be found (are you missing a using directive or an assembly reference?)

Error 3 The type or namespace name 'BitmapData' could not be found (are you missing a using directive or an assembly reference?)

Error 4 The type or namespace name 'BitmapData' could not be found (are you missing a using directive or an assembly reference?)

Thank you very much,

Mladen
2009-05-21
re: Watershed Image Segmentation in C#
you also have to add the reference to the system.drawing assembly that holds BitmapData type.
same thing for Aforge's FilterGrayToGray.

armor
2009-05-21
re: Watershed Image Segmentation in C#
Thank you,

BitmapData was solved, but for FilterGrayToGray Iadded the references AForge; AForge.Imaging; AForge.Imagine.Format;

And

using AForge;
using AForge.Imaging;
using AForge.Fuzzy;
using AForge.Imaging.Filters;

But the error continue,

aarmor
2009-06-03
re: Watershed Image Segmentation in C#
I was looking for some information and when i open the search object in Visual Studioi start to search FilterGrayToGray but it does not appear it is not in the AForge.Imaging.Filters.

How can i add the FilterGrayToGray.cs because now it said to me "unsafe code" and if i put unsafe class it does not work.

Thank you,

Piggy
2009-06-04
re: Watershed Image Segmentation in C#
Thanks a lot!! It's very helpful to me. ~(^(oo)^)~

Prashanth
2009-11-25
re: Watershed Image Segmentation in C#
Hi, I tried to implement your code, but I got the following error :

Error 1 'Segmentation.Form1.Dispose(bool)': no suitable method found to override C:\Users\pashok\Documents\Visual Studio 2008\Projects\watershed\watershed\Form1.Designer.cs 14 33 watershed

what am i supposed to do? Kindly help me

Mladen
2009-11-25
re: Watershed Image Segmentation in C#
my guess is that either your namspaces or class names are wrong somewhere.

Prashanth
2009-11-26
re: Watershed Image Segmentation in C#
Hi, I tried to implement your code, but this is the warning I get:

Accessing a member on 'watershed1.Form1.X' may cause a runtime exception because it is a field of a marshal-by-reference class.

What does this mean?

Moreover, as suggested in a previous comment, I have created a bitmapdata object and called processfilter function etc. But how do I display the segmented image? Or is it saved anywhere? Kindly expl that

Mladen
2009-11-26
re: Watershed Image Segmentation in C#
maybe you should first get familiar with how the Aforge.NET works.
how Process works is all explained in Aforge documantation.
i haven't done anything differently.

as for your 'watershed1.Form1.X' error it's part of your code so i wouldn't know what it means. it looks like you have MarshalByRefObject on your class which probably isn't needed. google it up.

Prashanth
2009-11-26
re: Watershed Image Segmentation in C#
hi, this is the code i have written. can you tell me if it is correct

Bitmap bmp = (Bitmap)pictureBox1.Image;
WatershedGrayscale wg = new WatershedGrayscale(8);
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
wg.execute(bmpdata);
bmp.UnlockBits(bmpdata);
pictureBox2.Image = (System.Drawing.Image)bmp;
pictureBox1.Visible = true;

I have added a function called execute, because I am not able to access the filtertogray function directly.

I am sorry but I am entirely new to AForge.NET

Prashanth
2009-11-26
re: Watershed Image Segmentation in C#
ok, i am sorry i did a very stupid mistake. instead of picturebox2.visible = true, I had given picbox1. sorry.

now, the program is running fine, but even if I give ur image as test input, only half the image is getting segmented. The other half is not.

any suggestions??

Mladen
2009-11-26
re: Watershed Image Segmentation in C#
your image probably has the wrong PixelFormat for GrayToGray Filter.

Prashanth
2009-11-26
re: Watershed Image Segmentation in C#
working perfectly.. thanks a lot

Prashanth
2009-11-30
re: Watershed Image Segmentation in C#
Hi, I know that watershed algo has one problem - over segmentation. That is what I am facing. Are there any possibilities to reduce it

Mladen
2009-11-30
re: Watershed Image Segmentation in C#
yes you have to blur the image before you apply the segmentation.
then put the segmented lines on your original image.

Prashanth
2009-11-30
re: Watershed Image Segmentation in C#
can you just guide me as to how the image can be blurred. sorry to ask.. but i am new to image processing

Prashanth
2009-12-02
re: Watershed Image Segmentation in C#
are there any possibilities to convert this code to the HSL color model instead of the RGB

Mladen
2009-12-02
re: Watershed Image Segmentation in C#
i'm sure there is. you're welcome to do it.

Prashanth
2009-12-03
re: Watershed Image Segmentation in C#
any idea how to do it?

Mladen
2009-12-03
re: Watershed Image Segmentation in C#
none. if i had any i'd tell you :)

Prashanth
2009-12-03
re: Watershed Image Segmentation in C#
:) thanks!! if u can give me your mail id, i will send you the code I have written. if possible, can you go through it and tell me if the changes i have made are correct?

Prashanth
2009-12-15
re: Watershed Image Segmentation in C#
This code goes thru even white pixels rite?? how can we avoid tat in order to reduce running time

Prashanth
2009-12-18
re: Watershed Image Segmentation in C#
Just wanted to say thanks once again for this great code.. It helped me out greatly

Innayat
2009-12-27
re: Watershed Image Segmentation in C#
sir i am working on hand gesture recognition
can i use ur code for segmenting a human hand in a frame?
if it can be used then can u kindly dictate me how to use it?

thanking you in anticipation.

Mladen
2009-12-29
re: Watershed Image Segmentation in C#
i have no idea but it probably can in some way...

Prashanth
2010-01-21
re: Watershed Image Segmentation in C#
Is there a possibility to get a documentation for this code?

Mladen
2010-01-21
re: Watershed Image Segmentation in C#
what documentation?
that's it what you see there.

Prashanth
2010-01-21
re: Watershed Image Segmentation in C#
Yes I am sorry. Did not relize that.

Anil Rathod
2010-02-09
re: Watershed Image Segmentation in C#
Please send this code along with description. thnx

chitra
2010-02-16
re: Watershed Image Segmentation in C#
thank you for ur code
I worked with this code in new console application. but I have a following errors
Error 1 The type or namespace name 'FilterGrayToGray' could not be found (are you missing a using directive or an assembly reference?) E:\ConsoleApplication1\ConsoleApplication1\watershedPixel.cs 62 39 ConsoleApplication1
Error 2 The type or namespace name 'BitmapData' could not be found (are you missing a using directive or an assembly reference?) E:\ConsoleApplication1\ConsoleApplication1\watershedPixel.cs 134 57 ConsoleApplication1
Error 3 The type or namespace name 'BitmapData' could not be found (are you missing a using directive or an assembly reference?) E:\ConsoleApplication1\ConsoleApplication1\watershedPixel.cs 331 41 ConsoleApplication1
Error 4 The type or namespace name 'BitmapData' could not be found (are you missing a using directive or an assembly reference?) E:\ConsoleApplication1\ConsoleApplication1\watershedPixel.cs 357 47 ConsoleApplication1
Error 5 Inconsistent accessibility: parameter type 'ConsoleApplication1.watershedPixel' is less accessible than method 'ConsoleApplication1.FifoQueue.AddToEnd(ConsoleApplication1.watershedPixel)' E:\ConsoleApplication1\ConsoleApplication1\watershedPixel.cs 374 21 ConsoleApplication1
Error 6 Inconsistent accessibility: return type 'ConsoleApplication1.watershedPixel' is less accessible than method 'ConsoleApplication1.FifoQueue.RemoveAtFront()' E:\ConsoleApplication1\ConsoleApplication1\watershedPixel.cs 379 31 ConsoleApplication1


I am very new to AForge.net. Please can u help me

Mladen
2010-02-16
re: Watershed Image Segmentation in C#
you've most like forgotten to include the AForge Dll's to your app.

Rongu Sakan
2010-02-17
re: Watershed Image Segmentation in C#
I created a WatershedGrayscale object and used its Apply method with a BitmapData. But there was an error: "The filter can be applied to graysclae (8bpp indexed) image only". How to solve this (I tried to use your sample picture)?

Mladen
2010-02-17
re: Watershed Image Segmentation in C#
there's a method in AForge that converts the image to 8bpp. But i don't remember it's name.

Pem
2010-02-21
FilterGrayToGray ???
I included all of the AForge.NET dll's for the latest AForge.NET 2.1.1. But I get the FilterGrayToGray error that other comments mentioned. I opened the AForge.NET solution source code, and did a search for the string FilterGrayToGray, and nothing came up. I tried modifying your code from "public class WatershedGrayscale : FilterGrayToGray" to "public class WatershedGrayscale : Grayscale", but this doesn't work either. Maybe FilterGrayToGray is from an older version of AForge.NET? How to update this code sample?

Mladen
2010-02-22
re: Watershed Image Segmentation in C#
there were probably some changet with the classes in new aforge.
look at their change log to see to what they replaced the class with and derive from that.

renny
2010-05-14
re: Watershed Image Segmentation in C#
Please send me full codeproject. I really need it for my final task. Thank you very much

shekhar
2010-07-21
re: Watershed Image Segmentation in C#
please send me full codeproject. i really need it for my final task. Thank you very much

cartus
2010-08-20
re: Watershed Image Segmentation in C#
Hi i have problem with this project. Program segments the image only in part.I transformed code to visual applications, And i want to ask that only i have this problem, and how to solve it. I attach the picture where you can see my problem

cartus
2010-08-20
re: Watershed Image Segmentation in C#
http://www.image-share.com/ijpg-328-22.html sry i forgot add link.

reshma
2010-08-24
re: Watershed Image Segmentation in C#
i need code for uterine cervix image segmentation...can u help me????

gokul
2010-08-27
re: Watershed Image Segmentation in C#
hi

can i get code for compressing an using fractal image compression technique. where we use segmentation of an image.

Thank u

Gomathi
2010-08-30
re: Watershed Image Segmentation in C#
Hi

i need full code..in this coding am getting error as "Error 1 'ConsoleApplication1.WatershedGrayscale.ProcessFilter(System.Drawing.Imaging.BitmapData)': no suitable method found to override"

Begger
2010-10-12
re: Watershed Image Segmentation in C#
please sent me a demo to godjing1985@yahoo.com,thanks,i am a new in c#

Adam
2010-10-17
re: Watershed Image Segmentation in C#
Hello!

I tried to work with your code, but the algoortihm is not working correctly. I have the same problem as Karthus!

What is he problem??

Really thx 4 the your answer!

Adam