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

1

0

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();
Kisung answered 17/5, 2018 at 10:18 Comment(3)
You might want to look at this answerEquestrienne
@RickM. Thanks for your reply.How can I adapt that answer to dispose off the handle in my code,please advice.Kisung
@RickM. Please see my update.Kisung
S
1

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();
    }
Sotted answered 18/5, 2018 at 11:24 Comment(5)
It seems to be caused by multiple channel image as you have said.Around 500mb memory is allocated.How can i fix this issue.I just need to sharpen the image.Please advice.Kisung
You could allocate the image as float in the first place and call Filter2d in place (each call reads and writes to one image channel, or at least uses only a one-channel float temp image). Switching to a 64 bit process or reducing the memory allocated in the rest of your code should work.Sotted
Thanks for your response.I have dropped EmguCV from the project as I need x86 build.Will look into it may be in the next update.Kisung
Yes I think OpenCvSharp can call Filter2D on 8 bit channels of a large image, so using less memory. Does my answer not answer the question?Sotted
I have accepted the answer.Can you please point me to some relevant opencvsharp sample code.Kisung

© 2022 - 2024 — McMap. All rights reserved.