I am running a EmguCV example for Image Stitching. Here's the important code from that example:
try
{
using (Stitcher stitcher = new Stitcher(false))
{
Image<Bgr, Byte> result = stitcher.Stitch(sourceImages);
IMGBXDisplayStitched.Image = result;
}
}
finally
{
foreach (Image<Bgr, Byte> img in sourceImages)
{
img.Dispose();
}
}
It works well, but when I change the value of Stitcher() to true (I want to use GPU), it shows this error:
An unhandled exception of type 'Emgu.CV.Util.CvException' occurred in Emgu.CV.dll
Additional information: OpenCV: You should explicitly call download method for gpu::GpuMat object
How can I solve this?
If you take a look at this example page, it says
There is currently a bug in Open CV such that GPU processing cannot produce the correct result. Must specify false as parameter. Hope this will be fixed soon to enable GPU processing
Related
I'm trying to save face images and predict them using Emgu CV 4.4 with EigenFaceRecognizer using .Net5.
Basically I am getting a single image, resizing it (I read somewhere that smaller images have better accuracy),adding it to the List<Mat>and saving the trained data to see what is there out of curiosity.After that I'm using the same image and attempt to predict what it is (label).
Unfortunately it fails producing this error.
Emgu.CV.Util.CvException: 'OpenCV: Wrong shapes for given matrices. Was size(src) = (1,57600), size(W) = (19200,1).'
I also tried imageForTraining.Mat within Predict however the same error occurred.
// Get The GrayImage And Resize It.
Image<Bgr, byte> imageForTraining = grayImage.Resize(128, 150, Emgu.CV.CvEnum.Inter.Cubic);
// Create New cv::Mat Lists.
List<Mat> mats = new List<Mat>()
{
imageForTraining.Mat
};
// Dirty Solution For Label Testing.
List<int> labels = new List<int>()
{
0
};
// Create Face Recognizer And Tell It There Is Only 1 Item.
FaceRecognizer faceRecognizer = new EigenFaceRecognizer(1);
// Write Data To File To See If Something Is There.
faceRecognizer.Write("trainingData");
// Attempt To Train.
faceRecognizer.Train(new VectorOfMat(mats.ToArray()), new VectorOfInt(labels.ToArray()));
// Test Image That Was Just Trained.
FaceRecognizer.PredictionResult predictionResult = faceRecognizer.Predict(imageForTraining);
I am getting "Value cannot be null.\r\nParameter name: encoder" error while saving a Bitmap image using RawFormat.
Sample code:
class Program
{
static void Main(string[] args)
{
try
{
var image = new System.Drawing.Bitmap(500, 400);
var stream = new MemoryStream();
image.Save(stream, image.RawFormat);
}
catch (Exception exp)
{
Console.WriteLine(exp.ToString());
}
}
}
The RawFormat doesn't exist in the existing list of ImageEncoders as below code returns null.
var imageCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(codec => codec.FormatID == image.RawFormat.Guid);
Note: The image could be any type(JPEG, BMP, PNG) etc. Image.Save() should work on image.RawFormat.
RawFormat is not Bitmap type. If I Change image.RawFormat to ImageFormat.Bmp, the save operation succeeds.
Referred below links but found nothing for making it independent of image type.
Image.Save crashing: {"Value cannot be null.\r\nParameter name: encoder"}
Why is Image.Save(Stream, ImageFormat) throwing an exception?
Any suggestions are welcome.
If you load an image from disk, you can use image.RawFormat to save that image using its original format. However there is no encoder associated with an in-memory bitmap (which is what you are creating in this sample application), so you'll have to specify an image format yourself (ie. ImageFormat.Bmp).
You can use this and it will be fixed:
image.Save(stream,ImageFormat.Jpeg);
In my project, I need to retrieve a custom image file (from disk). If the image file does not exist at the path provided, then the app will use a default image (embedded resource). Once I have the image, I need to resize it for use futher on in my application.
If I attempt to access only the embedded resource (Code Section 1), everything works as expected. If attempt to place a condition on the image (Code Section 2), the object comes back with all kinds of exceptions on the object, most notably for my purposes:
((System.Drawing.Image)(ReportLogoToUse)).Height' threw an exception of type 'System.ArgumentException' int {System.ArgumentException}
((System.Drawing.Image)(ReportLogoToUse)).Width' threw an exception of type 'System.ArgumentException' int {System.ArgumentException}
Here is my code
// Code Section 1
using (var myImage = Resources.sie_logo_petrol_rgb){
// resize the image to max allowed dimensions (64 x 233)
var resizedImage = Helpers.ResizeImage(myImage, (int)maxWidth, (int)maxHeight); // this code executes with no errors
pictureBox1.Image = resizedImage;
}
// Code Section 2
using (var ReportLogoToUse = Helpers.ReportLogo(filePath)){
// resize the image to max allowed dimensions (64 x 233)
var resizedImage = Helpers.ResizeImage(ReportLogoToUse, (int)maxWidth, (int)maxHeight); // Invalid Parameter error
pictureBox2.Image = resizedImage;
}
public static Bitmap ReportLogo(string filePath){
try{
var myImage = Image.FromFile(filePath, true);
return (Bitmap)myImage;
}
catch (Exception ex){
// use the embedded logo
using (var myResourceImage = Resources.sie_logo_petrol_rgb){
var myImage = myResourceImage;
return (Bitmap)myImage;
}
}
}
What is the difference between the objects in Code Section 1 and Code Section 2? Aren't they returning the same kind of object?
By removing the using... block in the catch... section, and just returning the file itself, it appears to be functioning now.
public static Bitmap ReportLogo(string filePath){
try{
return (Bitmap)Image.FromFile(filePath, true);
}
catch (Exception ex){
// use the embedded logo
return Resources.sie_logo_petrol_rgb;
}
}
Any insight as to why it works now would be greatly appreciated (because I am completely baffled).
I am getting "Value cannot be null.\r\nParameter name: encoder" error while saving a Bitmap image using RawFormat.
Sample code:
class Program
{
static void Main(string[] args)
{
try
{
var image = new System.Drawing.Bitmap(500, 400);
var stream = new MemoryStream();
image.Save(stream, image.RawFormat);
}
catch (Exception exp)
{
Console.WriteLine(exp.ToString());
}
}
}
The RawFormat doesn't exist in the existing list of ImageEncoders as below code returns null.
var imageCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(codec => codec.FormatID == image.RawFormat.Guid);
Note: The image could be any type(JPEG, BMP, PNG) etc. Image.Save() should work on image.RawFormat.
RawFormat is not Bitmap type. If I Change image.RawFormat to ImageFormat.Bmp, the save operation succeeds.
Referred below links but found nothing for making it independent of image type.
Image.Save crashing: {"Value cannot be null.\r\nParameter name: encoder"}
Why is Image.Save(Stream, ImageFormat) throwing an exception?
Any suggestions are welcome.
If you load an image from disk, you can use image.RawFormat to save that image using its original format. However there is no encoder associated with an in-memory bitmap (which is what you are creating in this sample application), so you'll have to specify an image format yourself (ie. ImageFormat.Bmp).
You can use this and it will be fixed:
image.Save(stream,ImageFormat.Jpeg);
I am using an Epson Perfection V700 scanner and selecting the following options when scanning using their tool:
ICM Color correction (source: EPSON-Standard and target: sRGB)
Unsharp Mask (medium)
That produces this image:
Now my problem is this - I actually need to interact with this scanner using TWAIN .Net and when I do so, the image I get back is this:
Aside: I unselected the aforementioned two options and scanned again with the Epson and got a very similar image to what I get through TWAIN.
So I figure that perhaps these are post processing steps that I can do myself on the image (maybe they are done in the hardware somehow though, I don't know).
I am using EmguCV so first of all I created an extension method that applies the ICM (I struggled to find any documentation for this, so it is a bit of a guess and maybe I am wrong straight away but I got the information from here: The bitmap transform class and it seems to make a difference to the image):
public static Image<Bgr, TDepth> ApplyIcm<TDepth>(
this Image<Bgr, TDepth> source,
string sourceIcm,
string targetIcm)
where TDepth : new()
{
var target = source.CopyBlank();
using (source)
{
using (var b = source.Bitmap)
{
using (var memory = new MemoryStream())
{
b.Save(memory, ImageFormat.Bmp);
memory.Position = 0;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
var ccb = new ColorConvertedBitmap();
ccb.BeginInit();
ccb.Source = bitmapImage;
ccb.SourceColorContext =
new ColorContext(new Uri(sourceIcm));
ccb.DestinationColorContext =
new ColorContext(new Uri(targetIcm));
ccb.EndInit();
var encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(ccb));
using (var ms = new MemoryStream())
{
encoder.Save(ms);
target.Bitmap = new Bitmap(ms);
}
}
}
}
return target;
}
Then I looked at that unsharpen thing and came across this question: How to sharpen an image in OpenCV? which says:
You use a gaussian smoothing filter and subtract the smoothed version from the original image
(I also checked this question to find out what the equivalent emgucv call is Why might EmguCV Gaussian blur not return identical results as OpenCV Gaussian blur?) and came up with this additional extension method:
public static Image<Bgr, TDepth> UnsharpMask<TDepth>(
this Image<Bgr, TDepth> source,
Size kernelSize,
int kernelHoritonalStandardDeviation,
int kernelVerticalStandardDeviation,
double alpha,
double beta,
double gamma)
where TDepth : new()
{
Image<Bgr, TDepth> ret = source.CopyBlank();
CvInvoke.cvSmooth(source,
ret,
SMOOTH_TYPE.CV_GAUSSIAN,
kernelSize.Width,
kernelSize.Height,
kernelHoritonalStandardDeviation,
kernelVerticalStandardDeviation);
CvInvoke.cvAddWeighted(source, alpha, ret, beta, gamma, ret);
return ret;
}
Now I call it like so:
string sourceIcm = #"C:\Windows\System32\spool\drivers\color\ewrgb18.icm";
string targetIcm = #"C:\Windows\System32\spool\drivers\color\ewsrgb.icm";
using(var im = new Image<Bgr, byte>("out.bmp"))
{
using (var icmmed = im.ApplyIcm(sourceIcm, targetIcm))
{
using (var ret = icmmed.UnsharpMask(new Size(0, 0), 5, 5, 2.4, -1.5, 0))
{
ret.Save("ret.bmp");
}
}
}
and this is the result:
Not very good! :-(
I have fiddled with the parameters endlessly but I just cannot work out how (or even if) I can achieve the same result as the Epson tool.
So, my question is:
Does anyone know if it is possible to achieve a result using opencv/emgucv (or even TWAIN - I had a look through the documentation for that and tried adjusting some of the capability parameters but I just made the image worse) that is similar in sharpness to the original image above or is there another technique I should try (could it be that I would need to know some details about the hardware itself in order to achieve correct sharpening)?
I think you should know how using WIA (Windows Image Acquisition) in your project, you may don't need to get access to hardware using opencv. WIA is used for integrating with webcams and scanners. Or, you can use TWAIN as you mentioned
have a look at these examples they could by helpful for your project:
using WIA
and
using TWAIN
Concerning the sharpening, you can use opencv functionality at software level, as another choice to solve your problem