1、using System;using System.Collections.Generic;using System.Text;using System.Drawing;using Emgu.Util;using Emgu.CV;using Emgu.CV.Structure;using tessnet2;using System.Diagnostics;namespace LicensePlateRecognition/ / A license plate detector/ public class LicensePlateDetector : DisposableObjectprivat
2、e Tesseract _ocr;/ / Create a license plate detector/ public LicensePlateDetector()/create OCR_ocr = new Tesseract();/You can download more language definition data from/http:/ supported includes:/Dutch, Spanish, German, Italian, French and English_ocr.Init(“eng“, false);/ / Detect license plate fro
3、m the given image/ / The image to search license plate from/ A list of images where the detected license plate region is stored/ A list of images where the detected license plate region with noise removed is stored/ A list where the region of license plate, defined by an MCvBox2D is stored/ The list
4、 of words for each license platepublic List DetectLicensePlate(Image img, List licensePlateList, List filteredLicensePlateList, List boxList)/Stopwatch w = Stopwatch.StartNew();List licenses = new List();using (Image gray = img.Convert()using (Image canny = new Image(gray.Size)using (MemStorage stor
5、 = new MemStorage()CvInvoke.cvCanny(gray, canny, 100, 50, 3);Contour contours = canny.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE,stor);FindLicensePlate(contours, gray, canny, licensePlateList, filteredLicensePlateList, boxList, licens
6、es);/w.Stop();return licenses;private void FindLicensePlate(Contour contours, Image gray, Image canny,List licensePlateList, List filteredLicensePlateList, List boxList,List licenses)for (; contours != null; contours = contours.HNext)Contour approxContour = contours.ApproxPoly(contours.Perimeter * 0
7、.05, contours.Storage);if (approxContour.Area 100 if (!IsParallelogram(approxContour.ToArray()Contour child = contours.VNext;if (child != null)FindLicensePlate(child, gray, canny, licensePlateList, filteredLicensePlateList, boxList, licenses);continue;MCvBox2D box = approxContour.GetMinAreaRect();do
8、uble whRatio = (double)box.size.Width / box.size.Height;if (!(3.0 child = contours.VNext;if (child != null)FindLicensePlate(child, gray, canny, licensePlateList, filteredLicensePlateList, boxList, licenses);continue;Image plate = gray.Copy(box);Image filteredPlate = FilterPlate(plate);List words;usi
9、ng (Bitmap bmp = filteredPlate.Bitmap)words = _ocr.DoOCR(bmp, filteredPlate.ROI);licenses.Add(words);licensePlateList.Add(plate);filteredLicensePlateList.Add(filteredPlate);boxList.Add(box);/ / Check if the four points forms a parallelogram/ / The four points that defines a polygon/ True if the four
10、 points defines a parallelogramprivate static bool IsParallelogram(Point pts)LineSegment2D edges = PointCollection.PolyLine(pts, true);double diff1 = Math.Abs(edges0.Length - edges2.Length);double diff2 = Math.Abs(edges1.Length - edges3.Length);if (diff1 / edges0.Length / Filter the license plate to
11、 remove noise/ / The license plate image/ License plate image without the noiseprivate static Image FilterPlate(Image plate)Image thresh = plate.ThresholdBinaryInv(new Gray(120), new Gray(255);using (Image plateMask = new Image(plate.Size)using (Image plateCanny = plate.Canny(new Gray(100), new Gray
12、(50)using (MemStorage stor = new MemStorage()plateMask.SetValue(255.0);for (Contour contours = plateCanny.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL,stor);contours != null; contours = contours.HNext)Rectangle rect = contours.Bound
13、ingRectangle;if (rect.Height (plate.Height 1)rect.X -= 1; rect.Y -= 1; rect.Width += 2; rect.Height += 2;rect.Intersect(plate.ROI);plateMask.Draw(rect, new Gray(0.0), -1);thresh.SetValue(0, plateMask);thresh._Erode(1);thresh._Dilate(1);return thresh;protected override void DisposeObject()_ocr.Dispose();