I am new to Open CV and am working on a ALPR solution based on violation images from multiple cameras. In most cases I am able to extract the text from the plate and run OCR however if the image brightness/contrast is out this poses a problem.
I've transferred my code to a console app and pasted below.
class Program
{
static void Main(string[] args)
{
var path = @$"path to image";
var img = LoadImage(path);
var resized = Resize(img);
var gray = Gray(resized);
var otsu = SimpleThresh(gray, 0, 43, ThresholdType.Otsu);
var binary = SimpleThresh(otsu, 0, 255, ThresholdType.Binary);
DetectText(inverse);
Show(binary, "binary");
}
}
static Mat LoadImage(string path)
{
return CvInvoke.Imread(path);
}
static Mat SimpleThresh(Mat img, double low, double max, ThresholdType type)
{
var th = new Mat();
CvInvoke.Threshold(img, th, low, max, type);
return th;
}
static Mat Brighten(Mat img, double alpha=1.95, double beta=0)
{
Mat bright = new Mat();
var mean = CvInvoke.Mean(img);
CvInvoke.ConvertScaleAbs(img, bright, alpha, beta);
return bright;
}
static Mat Resize(Mat orginalImage)
{
var newHeight = (int)(orginalImage.Height + (orginalImage.Height * 2));
var newWidth = (int)(orginalImage.Width + (orginalImage.Width * 2));
Mat img = new Mat();
CvInvoke.Resize(orginalImage, img, new Size(newWidth, newHeight), 0, 0, Inter.Cubic);
return img;
}
static Mat Gray(Mat img)
{
Mat gray = new Mat();
CvInvoke.CvtColor(img, gray, ColorConversion.Bgr2Gray);
return gray;
}
static void Show(Mat img, string name)
{
CvInvoke.Imshow(name, img);
CvInvoke.WaitKey();
}
static string DetectText(Mat img, string sourceFilePath )
{
var path = @"C:\tesseract";
using (var engine = new TesseractEngine(path, "eng"))
{
//engine.SetVariable("user_defined_dpi", "700");
engine.SetVariable("tessedit_char_whitelist", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
engine.DefaultPageSegMode = PageSegMode.SingleChar;
using ( var img1 = Pix.LoadFromFile(sourceFilePath))
{
using (var page = engine.Process(img1))
{
var text = page.GetText();
Console.WriteLine();
Console.WriteLine("---Image Text---");
Console.WriteLine();
Console.WriteLine(text);
}
}
}
var Ocr = new IronTesseract(); // nothing to configure
Ocr.Language = OcrLanguage.English;
Ocr.Configuration.TesseractVersion = TesseractVersion.Tesseract5;
Ocr.Configuration.PageSegmentationMode = TesseractPageSegmentationMode.SingleChar;
Ocr.Configuration.WhiteListCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
using (var Input = new OcrInput())
{
Input.AddImage(Emgu.CV.BitmapExtension.ToBitmap(img));
var Result = Ocr.Read(Input);
Console.WriteLine(Result.Text);
return Result.Text;
}
}
}
This code works well for in most cases, I get a nice binary and then loop through contours and cleanup before sending through to OCR engine. However if the brightness and contrast of the image is low then the binary thresholding does not work for me.
Example image where the thresholding fails
Below I have a screenshots of outputs from each stage
Example of success
screenshots of success outputs
If I brighten the image by using the Brighten() method I have posted above this resolves the problem however I have no idea which images need adjusting because I am working with mass amount of data.
Is there any way I can use c#/emgu.cv auto detect cases that require brightness/contract adjustments and set the brightness/contrast?
Or if there is an alternative route to acheive ALPR please let me know, as mentioned I am new to this.