Home > Blockchain >  How can I create the loop properly while writing erosion filter?
How can I create the loop properly while writing erosion filter?

Time:03-25

I am trying to write an erosion filter.I tried determine the part that I changed but I wanna fill the other array elements as 255.How can I do that?

public static byte[] dnmmmerosion(byte[] data)
        {
            int wdth = 2400;
            int hght = 800;

            List<byte> dnmbytee = new List<byte>();

            byte[] dnmbyte = new byte[1200000];
            for (int i = 0; i < 1200000; i  )
            {
                dnmbytee[i] = 255;
            }   


            for (int k = 1; k < hght-1; k  )
            {
                for (int vvv = 0; vvv < wdth-1; vvv  )
                {
                    if (data[k vvv] == 0 && data[k *wdth vvv] == 0)
                    {
                        if (data[k * wdth   (vvv 1)] == 0 && data[k * wdth   vvv 2] == 0)
                        {
                            if (data[(k   1) * wdth   vvv] == 0)
                            {
                                dnmbytee[k * wdth   vvv 1] = 0;
                            }
                        }
                    }
                }
            }

            for (int zzz = 0; zzz < 1200000; zzz  )
            {
                dnmbyte[zzz] = dnmbytee[zzz];
            }

            return dnmbyte;
        }

I mean the elements that I fillled are above(like: data[k vvv] == 0,...) and I guess I am making a mistake about coefficients while creating loops

PS:Ijust see a dull view when I write the code like that .

enter image description here

I am doing the processes on binary image.(So array consists of elements as 255 and 0.)If the elements of the structure same with the elements in image(for example elements:1,2,3,4,5) write 255 to the 3th element.

CodePudding user response:

I don't know C#, so won't be addressing some things I don't understand in the code.

First of all, you set

int wdth = 2400;
int hght = 800;

but then allocate 1,200,000 bytes for the output buffer. This means you loop over 2400 x 800 = 1,920,000 bytes, which is quite a bit beyond your buffer. I think you meant to set hght = 500 instead. To avoid problems like this, don't use the same numerical value multiple times, instead define constants that you can use across your code:

int channels = 3;
int width = 800;   // let's not be lazy, and use real words as variable names!
int height = 500;
int buffer_size = channels * width * height;

byte[] dnmbyte = new byte[buffer_size];
for (int i = 0; i < buffer_size; i  )
...

Next, I'm unsure as to why you need the intermediate buffer dnmbytee, why you can't directly write into dnmbyte. Not knowing what a List is in C#, I'm assuming it's not an array, but an actual list data structure. This would be very expensive to use as you do, stick to arrays for pixel data!

Finally, the main problem: you are accessing the buffer as if you have 2400 x 500 pixels, each one a byte, rather than 800 x 500 pixels, each one three bytes (RGB). Morphological operations are not well defined on color images, so I will assume here that all three bytes for one pixel are always the same. If so, read the first byte of each pixel, and write all three bytes.

To do this, you would loop and index like this:

for (int y = 1; y < height-1; y  ) {   // loop over all rows except the top and bottom-most ones
   for (int x = 1; x < width-1; x  ) { // loop over all columns, except the left and right-most ones
      int current_pixel_index = (y * width   x) * channels;
      // read at data[current_pixel_index]
      ...
      dnmbyte[current_pixel_index   0] = 0;
      dnmbyte[current_pixel_index   1] = 0;
      dnmbyte[current_pixel_index   2] = 0;
   }
}

To access neighboring pixels, you always add the same values to the current pixel index: channels to get the pixel to the right, -width*channels to get the pixel to the top, etc. Create a list for each pixel in your structuring element, then loop over this list:

int[5] neighbors;
neighbors[0] = -width*channels;
neighbors[1] = -channels;
neighbors[2] = 0;
neighbors[3] =  channels;
neighbors[4] =  width*channels;

for (int y = 1; y < height-1; y  ) {
   for (int x = 1; x < width-1; x  ) {
      int current_pixel_index = (y * width   x) * channels;
      for (int k = 0; k < 5; k  ) {
         // read at data[current_pixel_index   neighbors[k]]
      }
   }
}

The erosion logic can be like this:

for (int k = 0; k < 5; k  ) {
   if (data[current_pixel_index   neighbors[k]] == 0) {
      dnmbyte[current_pixel_index   0] = 0;
      dnmbyte[current_pixel_index   1] = 0;
      dnmbyte[current_pixel_index   2] = 0;
      break;
   }
}

Since the output array was initialized to 255, if none of the neighbors are 0, it will remain at that value.

The code above does not set any of the pixels at the edge of the image (first and last row and column). If you want to process those as well, the easiest method is to pad the input by one pixel at all sides, the new pixels should have a value of 255. The alternative is to do special processing at the edge pixels, where you ensure you don't attempt to read out of bounds. That type of processing tends to slow code down a lot, and also complicates the code. Padding is usually worth it!

  • Related