techno
techno

Reputation: 6500

EmguCV Out of memory exception in x86 release mode only-Sharpening Images

Im trying to increase the sharpness of an image using EmguCV

 Image<Bgr, Byte> myImage = new Image<Bgr, Byte>(new Bitmap(pictureBox1.Image));
            float[,] matrixKernel = new float[3, 3] {
                { 0,-1, 0 },
                {-1, 5,-1 },
                { 0,-1, 0 }
};
            ConvolutionKernelF matrix = new ConvolutionKernelF(matrixKernel);
            Image<Bgr, float> result = myImage.Convolution(matrix);
            Image<Bgr, Byte> BGRResult = result.ConvertScale<byte>(1, 0);
            e.Result = BGRResult.ToBitmap();
            myImage.Dispose();
            result.Dispose();
            BGRResult.Dispose();

The code works fine for medium resolution images,but when using high resolution images eg: 6000X4000 The following exception is thrown

enter image description here

Note that the sharpening works fine even for high resolution images when the project is set to AnyCPU -> Debug Mode I'm using EmguCV 3.3

Update:

As per Rick's reference answer,i made the following modification,but the issue persists.Please advice.

float[,] matrixKernel = new float[3, 3] {
{ 0,-1, 0 },
{-1, 5,-1 },
{ 0,-1, 0 }
};
ConvolutionKernelF matrix = new ConvolutionKernelF(matrixKernel);
var result2 = myImage.CopyBlank();
var handle = GCHandle.Alloc(result2); 
Image<Bgr, float> result = result2.Convolution(matrix);
Image<Bgr, Byte> BGRResult = result.ConvertScale<byte>(1, 0);

bm_dest = new Bitmap(BGRResult.ToBitmap());
handle.Free();
BGRResult.Dispose();
result.Dispose();
myImage.Dispose();
matrix.Dispose();

Upvotes: 0

Views: 948

Answers (1)

Peter Wishart
Peter Wishart

Reputation: 12280

I think this is a different problem to the access violation one linked in the comments.

Convolve calls Filter2D in the underlying OpenCv API - which works on a single channel float image.

You are passing a multiple channel byte image.

Emgu 3.3 converts your input to a float image, calls Filter2D once per channel and stitches the images back together.

For 6000 x 4000 this needs to allocate about 576MB during the call, which would be a lot if you are running in a 32 bit process.

Edit:

Calling Filter2d on each channel and disposing as you go uses less memory, but will be a bit slower.

Example using OpenCvSharp which I'm more familiar with, overhead of the filtering is only 100mb:

    var inputMat = BitmapConverter.ToMat(myBitmap);
    var kernel = OpenCvSharp.InputArray.Create(
        new float[3, 3] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } }
        );

    for (int i = 0; i < inputMat.Channels(); i++)
    {
        var c1 = inputMat.ExtractChannel(i);
        var c2 = c1.Filter2D(inputMat.Type(), kernel);
        c1.Dispose();
        c2.InsertChannel(inputMat, i);
        c2.Dispose();
    }

Upvotes: 1

Related Questions