tags:

views:

318

answers:

8
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

namespace TrainSVM
{
    class Program
    {
        static void Main(string[] args)
        {
            FileStream fs = new FileStream("dg.train",FileMode.OpenOrCreate,FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs);
            String[] filePathArr = Directory.GetFiles("E:\\images\\");

            foreach (string filePath in filePathArr)
            {
                if (filePath.Contains("HBP"))
                {
                    sw.Write("1 ");
                    Console.Write("1 ");
                }
                else
                {
                    sw.Write("1 ");
                    Console.Write("1 ");
                }

                using (Bitmap originalBMP = new Bitmap(filePath))
                {


                    /***********************/
                    Bitmap imageBody;
                    ImageBody.ImageBody im = new ImageBody.ImageBody(originalBMP);
                    using (imageBody = im.GetImageBody(-1))
                    {

                        /* white coat */
                        Bitmap whiteCoatBitmap = Rgb2Hsi.Rgb2Hsi.GetHuePlane(imageBody);
                        float WhiteCoatPixelPercentage = Rgb2Hsi.Rgb2Hsi.GetWhiteCoatPixelPercentage(whiteCoatBitmap);
                        //Console.Write("whiteDone\t");
                        sw.Write("1:" + WhiteCoatPixelPercentage + " ");
                        Console.Write("1:" + WhiteCoatPixelPercentage + " ");

                        /******************/
                        Quaternion.Quaternion qtr = new Quaternion.Quaternion(-15);
                        Bitmap yellowCoatBMP = qtr.processImage(imageBody);
                        //yellowCoatBMP.Save("yellowCoat.bmp");
                        float yellowCoatPixelPercentage = qtr.GetYellowCoatPixelPercentage(yellowCoatBMP);
                        //Console.Write("yellowCoatDone\t");
                        sw.Write("2:" + yellowCoatPixelPercentage + " ");
                        Console.Write("2:" + yellowCoatPixelPercentage + " ");

                        /**********************/
                        Bitmap balckPatchBitmap = BlackPatchDetection.BlackPatchDetector.MarkBlackPatches(imageBody);
                        float BlackPatchPixelPercentage = BlackPatchDetection.BlackPatchDetector.BlackPatchPercentage;
                        //Console.Write("balckPatchDone\n");
                        sw.Write("3:" + BlackPatchPixelPercentage + "\n");
                        Console.Write("3:" + BlackPatchPixelPercentage + "\n");
                    }
                }


                sw.Flush();

            }


            sw.Dispose();
            fs.Dispose();

        }

    }
}
+2  A: 

Shouldn't you be disposing imageBody as well?

I see it's opened:

Bitmap imageBody; 
ImageBody.ImageBody im = new ImageBody.ImageBody(originalBMP); 
imageBody = im.GetImageBody(-1); 

But I don't see you disposing of it / setting it to null?

AndyC
+1. Certainly he should, huge images lying undisposed can never be good.
Skurmedel
Disposing it and setting it to null are two completely different things (although I suspect you probably know that already).
LukeH
@Luke, yep, I know. :)
AndyC
I added it. and again running my code. I'm still getting this error.
imageWorker
What did you add?Can you update your original post to reflect your changes?
AndyC
code updated. added `imageBody.Dispose();`
imageWorker
btw.. I'm declaring these variables in side the `foreach` loop block. So doesn't that mean in each loop iteration. The previous object reference is destroyed and object should be collected by GC?
imageWorker
Yes and no, imageWorker: GC will collect them, but it won't necessarily happen straight away.
Dan Puzey
Also: why are people suggesting he dispose of this ImageBody class with no idea of what it actually does? If the image is passed in, there's no obvious reason that the class should even be disposable.
Dan Puzey
@Dan because it was the next logical step to take?
AndyC
@AndyC Seeing the code behind ImageBody would be my next logical step...
Adrian
+10  A: 

There are some Bitmap instances there that you aren't disposing. You should really try to get in the habit of using a using block rather than disposing manually, to stop these things slipping through the net.

David M
Indeed, using-blocks add a try-finally for you as well (as you certainly know) which his code lacks.
Skurmedel
Why a try-finally? If all the disposables are in using blocks these guarantee the Dispose call without needine one.
David M
I think you misunderstood me, that's one of the things you get from the using-statement. I didn't mean that you need try-finally with using-blocks, I mean that you won't need try-finally with using-blocks. :)
Skurmedel
Sorry, I misread "add" for "and" (or maybe this was your edit?).
David M
It might've been, nevermind we were in agreement all along :)
Skurmedel
+1  A: 

Try to take the Bitmap originalBMP = new Bitmap(filePath); in a using()

using (Bitmap originalBMP = new Bitmap(filePath)) {
  // your code....   
  sw.Flush();   
}

All within the using() clause is definitly disposed after leaving the clause. You could also set you variables to null, after they are disposed.

chriszero
I've got another question to this subject: When (any why) should I set variables null? Aren't they collected anyway when I leave their scope (talking about locals)?
Mudu
just to be sure ^^ ;) normaly it should be not needed.
chriszero
+1  A: 

You should use the using statement instead of Dispose() whereever possible. This way, you see in the declaration immediately that this instance you just create is freed.

Which is better?

Bitmap bmp = new Bitmap(filePath);
// .. pages of code goes here ..
bmp.Dispose(); // hopefully not forgotten

or

using (Bitmap bmp = new Bitmap(filePath))
{
// .. pages of code goes here ..
}

The using statement also ensures that all instances are freed even if you leave the current block/method prematurely with return,break or even an exception.

Note that you can put multiple assignments into the head of the using statement!

codymanix
tried it. Still outofmemory. code updated!
imageWorker
you have still lots of images in your code which are not disposed. Additionally, did you have a look at ImageBody? Does this class derive from IDisposable? If so you should also dispose it.
codymanix
You should also use .net memoryprofiler to see which objects consume so much memory
codymanix
+2  A: 

Maybe you are bitten by this bug: https://connect.microsoft.com/VisualStudio/feedback/details/521147/large-object-heap-fragmentation-causes-outofmemoryexception

In this case, adding

    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    GC.WaitForPendingFinalizers();
    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);

in the loop might help.

Or use sos.dll http://www.codeproject.com/KB/dotnet/Memory_Leak_Detection.aspx to see, where you leak memory.

Henrik
+2  A: 

You have a lot of calls to various classes, ImageBody,Rgb2Hsi,BlackPatchDetection etc

I assume these are you own code. Any of these could be holding on the resources.

I would suggest you grab a profiler and run some tests.

Most of them have trial versions giving you a couple of days with it.

http://stackoverflow.com/questions/49912/best-net-memory-and-performance-profiler

Adrian
+5  A: 

If you're getting the exception on this line:

using (Bitmap originalBMP = new Bitmap(filePath))

then that may mean you're trying to load an invalid or corrupted image file. For reasons known to no man, the OutOfMemoryException is what's thrown in this case. It actually has nothing to do with really being out of memory.

Try googling "bitmap.fromfile outofmemoryexception".

MusiGenesis
That's a good one. Completely misleading exceptions are my favorite.
Mike Two
@Mike: it's extra-bad in this case, because image files tend to be some of the largest objects you deal with in .Net, so when you run into an `OutOfMemoryException`, it's easy to assume that you're really, you know, *out of memory*.
MusiGenesis
A: 

As with any Garbage collection issue, my approach would be to start commenting things out and seeing if I can still reproduce memory leaks. Things to try out:

  1. Instantiate only one instance of Bitmap in the loop to see if the memory usage changes.
  2. Dispose/not Dispose that one instance of Bitmap to see if disposing makes any difference.

From what I can see in the latest version of the code, whiteCoatBitmap, yellowCoatBitmap and blackPatchBitmap are not being disposed. Surround those with a using block as well.

Igor Zevaka