Search code examples
c#-4.0image-processingbitmapdata

Noise Removal by Averaging Multiple Images in c#


I tried code for two images but it fails after that limit..and not getting proper solution as well for collection of images you can visit Click Here For collection of images

In these Images numbers on that images in green color are noise please help me to find these solution

I have tried Following Code

    public Bitmap GetAveragedBitmap()
    {

        int numberOfImages = _imageCollection.Count;
        Bitmap bmpresult = null;


        if (numberOfImages > 1)
        {
            Stopwatch clock = new Stopwatch();
            clock.Start();
            BitmapData[] bmpData = new BitmapData[numberOfImages];
            Bitmap[] bit = new Bitmap[numberOfImages];
            int width = 0;
            int height = 0;

            for (int index = 0; index < numberOfImages; index++)
            {
                bmpData[index] = _imageCollection[index].LockBits(new Rectangle(0, 0, _imageCollection[index].Width, _imageCollection[index].Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                if (index > 0)
                {
                    if (bmpData[index].Width > width)
                    {
                        width = bmpData[index].Width;
                    }
                    if (bmpData[index].Height > height)
                    {
                        height = bmpData[index].Height;
                    }
                }
                else
                {
                    width = bmpData[0].Width;
                    height = bmpData[0].Height;
                }

                _imageCollection[index].UnlockBits(bmpData[index]);




            }//end of for loop
            for (int index = 0; index < numberOfImages; index++)
            {
                bit[index] = new Bitmap(_imageCollection[index], width, height);

            }

            bmpresult = new Bitmap(width, height);
            BitmapData[] data = new BitmapData[numberOfImages];
            for (int index = 0; index < numberOfImages; index++)
            {
                data[index] = bit[index].LockBits(new Rectangle(0, 0, bit[index].Width, bit[index].Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            }
            data[1].Reserved = 1;
            BitmapData dataResult = bmpresult.LockBits(new Rectangle(0, 0, bmpresult.Width, bmpresult.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            unsafe
            {
                int[] remain = new int[numberOfImages];
                byte*[] ptr = new byte*[numberOfImages];
                long totalIntensity = 0;

                for (int index = 0; index < numberOfImages; index++)
                {
                    ptr[index] = (byte*)data[index].Scan0;
                    remain[index] = data[index].Stride - data[index].Width * 3;
                }
                byte* ptrResult = (byte*)dataResult.Scan0;
                //for resultant image
                int remainResult = dataResult.Stride - dataResult.Width * 3;


                for (int i = 0; i < height; i++)
                    for (int j = 0; j < width * 3; j++)
                    {
                        for (int index = 0; index < numberOfImages; index++)
                        {
                            totalIntensity += (int)(ptr[index][0]);
                            ptr[index]++;
                        }
                    }
                    totalIntensity= totalIntensity/ numberOfImages;
                int average = (int)totalIntensity / (numberOfImages * height * width);
                //reset the pointer
                for (int index = 0; index < numberOfImages; index++)
                {
                    ptr[index] = (byte*)data[index].Scan0;
                }

                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < width * 3; j++)
                    {

                        int result = 1;
                        for (int k = 0; k < numberOfImages; k++)
                        {

                            result = (ptr[k][0] * 1 * result);

                        }

                        ptrResult[0] = (byte)(result / average);

                        for (int index = 0; index < numberOfImages; index++)
                        {
                            ptr[index]++;
                        }
                        ptrResult++;

                    }
                    for (int index = 0; index < numberOfImages; index++)
                    {
                        ptr[index] += remain[index];
                    }

                    ptrResult += remainResult;


                }

                //  }//end of for loop                           

            }//end of unsafe

            for (int index = 0; index < numberOfImages; index++)
            {
                bit[index].UnlockBits(data[index]);
            }
            bmpresult.UnlockBits(dataResult);
            clock.Stop();
            Debug.WriteLine("Time for average " + clock.ElapsedMilliseconds.ToString());

        }
        return bmpresult;



    }

Solution

  • I have done this,

    I went for ideas to AForge framework and luckily there is filter AForge.NET Framework Morph Class that creates average from two images. I think the original intent was to morph two different images as an effect, but if you uses two shots of same scene you get noise reduction.

    I would assume you would like 2-n averaging so I suggest you take the source of the Merge filter as a starting point and create your customized version for multiple images.

    Here is source : GitHub.com | AForge.NET / Merge.cs

    PS. You might need to downloaded whole AForge project source to find where to put your implementation better.