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)?