Jump to content


Need help in Image Processing by using Visual Studio 2005 c#


  • You cannot reply to this topic
6 replies to this topic

#1 Khadgar

    New Member

  • Members
  • PipPip
  • 14 posts

Posted 25 April 2008 - 04:03 PM

I understand the theory behind image processing but I am not fimiliar with c# or GDI+ , I do not know how to implement it at all. I hope I can get some help on programming side.

I read some articles about image processing in c#, the author did not give detail explaination and I really cannot figure out what are those mean. For example:

public static bool Invert(Bitmap b)
{
    BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), 
        ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); 
    int stride = bmData.Stride; 
    System.IntPtr Scan0 = bmData.Scan0; 
    unsafe 
    { 
        byte * p = (byte *)(void *)Scan0;
        int nOffset = stride - b.Width*3; 
        int nWidth = b.Width * 3;
        for(int y=0;y < b.Height;++y)
        {
            for(int x=0; x < nWidth; ++x )
            {
                p[0] = (byte)(255-p[0]);
                ++p;
            }
            p += nOffset;
        }
    }

    b.UnlockBits(bmData);

    return true;
}


From this example, I has few questions:
1) What is nOffset use for and why it is equal to stride - b.Width*3? From what I know stride is width of a line of a line of pixel, but why it use to minus 3 time of the width?

2)What is nWidth use for? why cannot use b.Width straight?

3)Why inside the inner for loop, the author use p[0] but not p[i] and then ++iinstead of ++p? And I also do not understand why after the inner for loop, there is p+=nOffset?

I want to do segmentation( connected component labeling ) on my image, but before I can implement I need to understand how to get the pixel and identify the position of the pixel.

Can anyone help me please?

#2 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 574 posts

Posted 25 April 2008 - 05:19 PM

In future please use the &[code&] tags

Khadgar said:

From this example, I has few questions:
1) What is nOffset use for and why it is equal to stride - b.Width*3? From what I know stride is width of a line of a line of pixel, but why it use to minus 3 time of the width?

nOffset is the difference between the "stride" of the texture and thw actual width of the texture. Width and stride are 99% of the time the same thing but not always. Some implementations can cache extra data on the edge of each line of the texture. Therefore when you get to the end of a row of pixels then you need to jump forward nOffset bytes to reach the next scan line.

Quote

2)What is nWidth use for? why cannot use b.Width straight?

Because this code is handling a 24-bit image. ie 3 bytes per pixel. The width maybe 64 pixels (for example) but for a 24-bit image that is 192 bytes.

Quote

3)Why inside the inner for loop, the author use p[0] but not p and then ++iinstead of ++p? And I also do not understand why after the inner for loop, there is p+=nOffset?

They use p[0] because they are advancing the pointer by a byte each time anyway. you could just as easily use *p. Both work the same way. Its just one way of iterating through the image that takes into account the problems of a different stride to width in bytes. There are many other way you could do it. For example


const int index = (y * stride) + x;

p[index] = 255 - p[index];


The original code is a [i]tiny
bit more optimal though. There is no multiply and only the one add (ie ++p).

#3 Khadgar

    New Member

  • Members
  • PipPip
  • 14 posts

Posted 26 April 2008 - 06:04 AM

This is the code which I try to use to implement connected components labeling segmentation, can anyone help me figure out what is the problem?


 public static bool Segmentation(Bitmap b)

        {

            BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmData.Stride;

            System.IntPtr Scan0 = bmData.Scan0;


            unsafe

            {

                byte* p = (byte*)(void*)Scan0;

                int nOffset = stride - b.Width * 3;

                int nWidth = b.Width * 3;

                


                for (int y = 0; y < b.Height; y++)

                {

                    for (int x = 0; x < b.Width; x++)

                    { 

                        int ccl = (y * stride) + x;

                        if( ccl < 0 )

                        {

                            ccl = 0;

                        }

                        byte newlabelvalue = 50;


                        //if both top and left value of the current pixel is 0, assign new label to current pixel

                        if ((byte)p[ccl - nOffset] == 0 && (byte)p[ccl - 3] == 0)

                        {

                            newlabelvalue += 50;

                            p[ccl] = newlabelvalue;

                        }


                        //either top or left value of current pixel is 1 and another is 0, keep the label value same as previous one

                        if ((byte)p[ccl - nOffset] == 0 && (byte)p[ccl - 3] == 1 ||

                            (byte)p[ccl - nOffset] == 1 && (byte)p[ccl - 3] == 0)

                        {

                            p[ccl] = newlabelvalue;

                        }


                        //if both top and left value of the current pixel is 0, assign the lesser label value to current pixel

                        if ((byte)p[ccl - nOffset] == 1 && (byte)p[ccl - 3] == 1)

                        {

                            if ((byte)p[ccl - nOffset] < (byte)p[ccl - 3])

                            {

                                p[ccl] = (byte)p[ccl - nOffset];

                            }

                            if ((byte)p[ccl - 3] < (byte)p[ccl - nOffset])

                            {

                                p[ccl] = (byte)p[ccl - 3];

                            }

                        }


                        //++p;

                    }

                    p += nOffset;

                }

            }

            b.UnlockBits(bmData);

            return true;

        }



#4 Reedbeta

    DevMaster Staff

  • Administrators
  • 4979 posts
  • LocationBellevue, WA

Posted 26 April 2008 - 09:31 AM

"Can anyone help me figure out what is the problem?" You've got to be kidding me. Tell us *precisely* what the code is supposed to do and how that differs from what it's actually doing; then we might have a chance of tracking down the problem. We can't help you if all you tell us is that it doesn't work.
reedbeta.com - developer blog, OpenGL demos, and other projects

#5 Khadgar

    New Member

  • Members
  • PipPip
  • 14 posts

Posted 26 April 2008 - 01:08 PM

Reedbeta said:

"Can anyone help me figure out what is the problem?" You've got to be kidding me. Tell us *precisely* what the code is supposed to do and how that differs from what it's actually doing; then we might have a chance of tracking down the problem. We can't help you if all you tell us is that it doesn't work.

When I execute the segmentation function, my application stop working and prompt out message as this:

Posted Image

There is no error in my code and I never learn about memory so I hope someone can help me on this.

What I expected from my code is, it suppose to scan each pixel of the image from left to right and top to bottom.

While scanning , it will check the pixel value of the pixel which at the top and at left of the current pixel. Base on the condition as I stated ( as what I wrote in the comment ), it will assign new pixel value accordingly.

After this process, the pixels which locate in the same segment will have the same value, therefore different segment will show different color.

#6 Reedbeta

    DevMaster Staff

  • Administrators
  • 4979 posts
  • LocationBellevue, WA

Posted 26 April 2008 - 05:41 PM

Think about what happens on the very first iteration of the loop, when ccl = 0. The expressions ccl - nOffset and ccl - 3 will be negative, so you are trying to access memory that is not part of the image. That's why you are getting an error, because the program tries to access invalid memory.

Geometrically, you're trying to look at the pixels above and to the left from the current pixel, but if you're in the first row of the image those don't exist.

A couple other things: if you are at the first pixel in a row, ccl - 3 will give you the last pixel in the previous row, probably not what you want. Also you should be adding or subtracting stride, not nOffset, to get to the next or previous row. stride is the number of bytes in one row in memory, nOffset is just the *difference* between stride and the actual width of the image (in bytes), i.e. the amount of space that's not part of the image.

By the way, the code right before that error, "if (ccl < 0) ccl = 0", is useless. ccl will never be negative, as you can see from the line that calculates it: ccl = y * stride + x, where y, stride, and x are all positive or zero.
reedbeta.com - developer blog, OpenGL demos, and other projects

#7 Khadgar

    New Member

  • Members
  • PipPip
  • 14 posts

Posted 27 April 2008 - 02:28 PM

Reedbeta said:

Think about what happens on the very first iteration of the loop, when ccl = 0. The expressions ccl - nOffset and ccl - 3 will be negative, so you are trying to access memory that is not part of the image. That's why you are getting an error, because the program tries to access invalid memory.

Geometrically, you're trying to look at the pixels above and to the left from the current pixel, but if you're in the first row of the image those don't exist.

A couple other things: if you are at the first pixel in a row, ccl - 3 will give you the last pixel in the previous row, probably not what you want. Also you should be adding or subtracting stride, not nOffset, to get to the next or previous row. stride is the number of bytes in one row in memory, nOffset is just the *difference* between stride and the actual width of the image (in bytes), i.e. the amount of space that's not part of the image.

By the way, the code right before that error, "if (ccl < 0) ccl = 0", is useless. ccl will never be negative, as you can see from the line that calculates it: ccl = y * stride + x, where y, stride, and x are all positive or zero.

Thanks for helping :lol:

My programming skill is bad and I still cannot get rid on my bad habit( keep trying and fixing without analyse ) :sad:

I had change my code a lot, "somehow" that error does not prompt out again ( but I cannot get the effect I want.


public static bool Segmentation(Bitmap img)

        {

            BitmapData bmpdt = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmpdt.Stride;

            System.IntPtr Scan0 = bmpdt.Scan0;


            unsafe

            {

                byte* px = (byte*)(void*)Scan0;

                byte* label = (byte*)(void*)Scan0; ;

                int nextline = stride - img.Width * 3;

                int realWidth = img.Width * 3;

                byte newlabelvalue = 100;


                for (int y = 0; y < img.Height; y++)

                {

                    //if this is first row, skip scanning

                    if (y == 0)

                    {

                        y += 1;

                    }


                    for (int x = 0; x < realWidth; x++)

                    {

                        //if this is first column, skip scanning

                        if (x == 0)

                        {

                            x += 1;

                        }


                        int ccl = (y * stride) + x;

                        label[ccl] = (byte)px[ccl];


                        //if ((byte)px[ccl] == 0) //if current pixel value is 0, keep scanning

                        //{

                        //    px[ccl] = (byte)px[ccl];

                        //}

                        //else

                            //if ((byte)px[ccl] == 1) //if current pixel value is 1, check top and left neighbour pixel value

                            //{

                                //if both top and left value of the current pixel is 0, assign new label to current pixel

                                if ((byte)label[ccl - stride] == 0 && (byte)label[ccl - 1] == 0)

                                {

                                    

                                    px[ccl] -= newlabelvalue; //place the new value to the previous pixel, so that next pixel can refer on the original pixel value of current pixel

                                    newlabelvalue += 50;

                                }


                                //either top or left value of current pixel is 1 and another is 0, keep the label value same as previous one

                                if ((byte)label[ccl - stride] == 0 && (byte)label[ccl - 1] == 1)

                                {

                                    px[ccl] = (byte)px[ccl - 1];

                                }

                                if ((byte)label[ccl - stride] == 1 && (byte)label[ccl - 1] == 0)

                                {

                                    px[ccl] = (byte)px[ccl - stride];

                                }


                                //if both top and left value of the current pixel is 0, assign the lesser label value to current pixel

                                if ((byte)label[ccl - stride] == 1 && (byte)label[ccl - 1] == 1)

                                {

                                    if ((byte)label[ccl - stride] < (byte)label[ccl - 1])

                                    {

                                        px[ccl] = (byte)px[ccl - stride];

                                    }

                                    if ((byte)label[ccl - 1] < (byte)label[ccl - stride])

                                    {

                                        px[ccl] = (byte)px[ccl - 1];

                                    }

                                }                                

                            //}

                        

                        //++px; 

                    }

                    //px += nextline; 

                }

            }

            img.UnlockBits(bmpdt);

            return true;

        }


The effect I get is like this( top image is before and bottom image is after):
Posted Image

Beside this, if I add that "if ((byte)px[ccl] == 1)" statement, there is no effect at all...





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users