How to create a Mat from byte[] with JavaCV - javacv

Trying to use JavaCV for image processing to rotate image according to it's Exif data.
Reading and writing from file to either Mat or IplImage works, but since the file is being upload or downloaded, I also want to be able to do the same thing processing byte[] instead of having to write to file.
However, I cannot find how to create a Mat instance from byte[].
The method 'aMat.put(0, 0, byteArray)' which is mentions in some answers is not available on a Mat instance in javacp version 1.0 using javacpp-presets:opencv:3.0.0.
Trying to put the bytes in the Mat data via : 'aMat.data().put(imageBytes, 0, 0)' throws a NPE because data() returns null. I cannot find how to set the data since it is a JNI call.
Any idea's on how to create a opencv_core.Mat from byte[]?

Did you try using:
yourMat.data().put(yourByteArray);
Just make sure yourMat is of the right size.

Related

BackgroundSubtractorMOG2 bgm->apply throws exception in Visual Studio 2017

I'm new to C++ and opencv and having difficulty running the background subtractor model. I'm using Visual Studio 2017 (VC++) and opencv 3.2.
I need to use BackgroundSubtractorMOG2 and it creates the model fine but throws exception when I pass it a new frame that is converted from an encoded image (because I'm using a USB3 camera that doesn't allow direct reading of frame by opencv) to cv::Mat. The code snippet is below
if (EncodeRawImage(pRawImage, &frameDesc, imageFormat, &pEncodedImage, &encodedImageSize) == SUCCESS) {
// Convert current raw image to openCV Mat format for analysis
auto store = gcnew cli::array<Byte>(encodedImageSize);
System::Runtime::InteropServices::Marshal::Copy(IntPtr(pEncodedImage), store, 0, encodedImageSize);
auto stream = gcnew System::IO::MemoryStream(store);
System::Drawing::Bitmap^ bitmapFrame = safe_cast<System::Drawing::Bitmap ^> (Image::FromStream(stream));
Mat imgBuf = Mat(bitmapFrame->Width, bitmapFrame->Height, CV_8U, pEncodedImage);
Mat imgMat = imdecode(imgBuf, CV_LOAD_IMAGE_COLOR);
bgm->apply(imgMat , fgMaskMOG);
returnCode = 1;
}
The exception is
owner 0x0000023afa2a2ec0 Information not available, no symbols loaded for opencv_world320d.dll> cv::detail::PtrOwner *
stored 0x0000023afa29baa0 Information not available, no symbols loaded for opencv_world320d.dll> cv::BackgroundSubtractorMOG2 *
Even though the opencv320d.lib are linked properly and a few other basic opencv samples run for me in the same program (e.g., cv::subtract, cv::calcHist etc). I wonder if it because the image size is too large (4608x3288) and bitmpaFrame that I'm creating may have an issue?
Or if I'm trying to access image data in the stream/memory in a way that is not allowed?
Even though the Information not found string is still there when I do the breakpoint, I just found that the model was throwing exception because of large image size as I mentioned in my original question (4608x3288). I resizes the image (resize(newImageMat, newImageMat, cv::Size(1000, 1000 * newImageMat.rows / newImageMat.cols), INTER_LINEAR);) and the error is gone and the model learns and shows the result. The text maybe a Visual Studio bug since I was reading about a similar issue here https://stackoverflow.com/a/7736034/3377101?

Manually populate an ImageField

I have a models.ImageField which I sometimes populate with the corresponding forms.ImageField. Sometimes, instead of using a form, I want to update the image field with an ajax POST. I am passing both the image filename, and the image content (base64 encoded), so that in my api view I have everything I need. But I do not really know how to do this manually, since I have always relied in form processing, which automatically populates the models.ImageField.
How can I manually populate the models.ImageField having the filename and the file contents?
EDIT
I have reached the following status:
instance.image.save(file_name, File(StringIO(data)))
instance.save()
And this is updating the file reference, using the right value configured in upload_to in the ImageField.
But it is not saving the image. I would have imagined that the first .save call would:
Generate a file name in the configured storage
Save the file contents to the selected file, including handling of any kind of storage configured for this ImageField (local FS, Amazon S3, or whatever)
Update the reference to the file in the ImageField
And the second .save would actually save the updated instance to the database.
What am I doing wrong? How can I make sure that the new image content is actually written to disk, in the automatically generated file name?
EDIT2
I have a very unsatisfactory workaround, which is working but is very limited. This illustrates the problems that using the ImageField directly would solve:
# TODO: workaround because I do not yet know how to correctly populate the ImageField
# This is very limited because:
# - only uses local filesystem (no AWS S3, ...)
# - does not provide the advance splitting provided by upload_to
local_file = os.path.join(settings.MEDIA_ROOT, file_name)
with open(local_file, 'wb') as f:
f.write(data)
instance.image = file_name
instance.save()
EDIT3
So, after some more playing around I have discovered that my first implementation is doing the right thing, but silently failing if the passed data has the wrong format (I was mistakingly passing the base64 instead of the decoded data). I'll post this as a solution
Just save the file and the instance:
instance.image.save(file_name, File(StringIO(data)))
instance.save()
No idea where the docs for this usecase are.
You can use InMemoryUploadedFile directly to save data:
file = cStringIO.StringIO(base64.b64decode(request.POST['file']))
image = InMemoryUploadedFile(file,
field_name='file',
name=request.POST['name'],
content_type="image/jpeg",
size=sys.getsizeof(file),
charset=None)
instance.image = image
instance.save()

Getting a remote image to use with Codename One

I am trying to retrieve a remote image to use it in a label. My code is the following:
Dimension dimension = new Dimension(100, 100);
ImageDownloadService.createImageToStorage("http://www.example.com/logo-icono.ico",label, "cacheID-unique-identifier",dimension);
However, when I run the project, I got this error:
java.lang.IllegalArgumentException: create image failed for the given image data of length: 3906
at com.codename1.ui.Image.createImage(Image.java:627) at com.codename1.ui.Image.createImage(Image.java:627)
at com.codename1.ui.EncodedImage.getInternal(EncodedImage.java:270)
at com.codename1.ui.EncodedImage.getInternalImpl(EncodedImage.java:245)
at com.codename1.ui.EncodedImage.drawImage(EncodedImage.java:433)
at com.codename1.ui.Graphics.drawImage(Graphics.java:505)
at com.codename1.ui.plaf.DefaultLookAndFeel.drawComponent(DefaultLookAndFeel.java:1079)
at com.codename1.ui.plaf.DefaultLookAndFeel.drawLabel(DefaultLookAndFeel.java:380)
at com.codename1.ui.Label.paint(Label.java:335)
at com.codename1.ui.Component.internalPaintImpl(Component.java:1029)
at com.codename1.ui.Component.paintInternalImpl(Component.java:1003)
at com.codename1.ui.Component.paintInternal(Component.java:978)
at com.codename1.ui.Container.paint(Container.java:903)
at com.codename1.ui.Component.internalPaintImpl(Component.java:1023)
at com.codename1.ui.Component.paintInternalImpl(Component.java:1003)
at com.codename1.ui.Component.paintInternal(Component.java:978)
at com.codename1.ui.Container.paint(Container.java:903)
at com.codename1.ui.Form.paint(Form.java:2716)
at com.codename1.ui.Component.internalPaintImpl(Component.java:1023)
at com.codename1.ui.Component.paintInternalImpl(Component.java:1003)
at com.codename1.ui.Component.paintInternal(Component.java:978)
at com.codename1.ui.Component.paintInternal(Component.java:946)
at com.codename1.ui.Component.paintComponent(Component.java:1223)
at com.codename1.ui.Component.paintComponent(Component.java:1175)
at com.codename1.impl.CodenameOneImplementation.paintDirty(CodenameOneImplementation.java:382)
at com.codename1.impl.javase.JavaSEPort.paintDirty(JavaSEPort.java:963)
at com.codename1.ui.Display.edtLoopImpl(Display.java:993)
at com.codename1.ui.Display.mainEDTLoop(Display.java:920)
at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120)
at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
at com.codename1.ui.Image.createImage(Image.java:627)
What am i doing wrong?
Ico files are windows specific and most devices don't support loading them. Only PNG & JPEG are guaranteed in devices.
I would also recommend using URLImage where applicable.

JavaCV IplImage.createFrom hangs in place

Not sure why this is happening. The method :
IplImage.createFrom(image);
Is hanging without returning any value. I've tried multiple images, and confirmed their existence. I'm writing an application that harnesses template matching, however this initial step is giving me a headache. Does anyone know why this method would suspend the thread and not return any value? I've done some research, and confirmed my OpenCV path is set up, and that all my libraries are properly setup.
Before converting a BufferedImage to iplimage we need to create an iplimage which has same height and width as the BufferedImage. Try this code:
IplImage ipl_image = IplImage.create(buffered_image.getWidth(),buffered_.getHeight(),IPL_DEPTH_8U,1);
ipl_image = IplImage.createFrom(buffered_image);

A null reference or invalid value was found [GDI+ status: InvalidParameter]

I am running an MVC3 app on Mono/linux and everything is working fine with the exception of an image upload utility. Whenever an image upload is attempted i get the Invalid Parameter error from within the method below:
System.Drawing.GDIPlus.CheckStatus(status As Status) (unknown file): N 00339
System.Drawing.Bitmap.SetResolution(xDpi As Single, yDpi As Single)
I've googled this error extensively and have found that the Invalid parameter error can often be misleading, and could fire if for example there was an error with the upload itself, or if the image was not fully read. This runs fine on IIS/Windows, but I've not been able to get it to work in Mono.
Apache2
Mono 2.10.8.1
Am i missing something simple or do i need to find a different way to handle image manipulation for mono?
After doing quite a bit of testing, I was able to determine the root of my error. I was attempting to use the Image.HorizontalResolution and Image.VerticalResolution properties for Bitmap.Resolution . While these properties were set on the initial upload (where the file is read into a stream from the tmp directory), when i posted back with the base64 encoded string of the image itself, it appears these values were lost somehow. Because of this the SetResolution method failed.
For whatever reason i do not have this issue on IIS/Windows, the properties exist in both circumstances.
I encountered a similar issue. A Bitmap loaded from disk, reported bmp.HorizontalResolution==0 and bmp.VerticalResolution==0 when they were both==300. This behaviour does not occur on Windows.
A bit more digging, I found that the following test fails:
[Test]
public void GDI_SetResoltion()
{
var b1 = new Bitmap (100, 100);
Assert.That (b1.HorizontalResolution, Is.Not.EqualTo (0));
Assert.That (b1.VerticalResolution, Is.Not.EqualTo (0));
}
I believe Windows will default resolution to 96 dpi.

Resources