Automatically complete a line in Visual Studio

Just discovered that Shift+Enter magically completes a line for you. For example, you can type

String Hello = "Hello world

Then Press Shift + Enter, you’ll have

String Hello = "Hello world";
| (cursor waiting on the next line)

Difference between LINQ and lambda expression

I have stuck at this field for a long time. Today it suddenly becomes clear to me: LINQ and lambda expressions are to very different things (though they complements each other on many occasions).

Lambda expression

Lambda expression, to sum up, is only about the operator “=>” (read as “goes to”). It serves as a shorthand for anonymous function (usually used to write short expressions like “x => x % 2 == 0” to find even numbers). It will be automatically typed as either an Expression, a delegate or a Func depending on where it is used.

LINQ

LINQ is like SQL for objects. It can query arrays, list or any other enumerable objects. It’s sort of an advanced for loops with SQL-like operations like sorting, grouping and of course, lambda expression support. Usual syntax is “from <iterator name> in <data> where <condition on iterator> select <iterator>”

Note on capturing value of a variable in an anonymous function

Extraction from “C# programming language 4th edition”

When not captured, there is no way to observe exactly how often a local variable is instan-tiated: Because the lifetimes of the instantiations are disjoint, it is possible for each
instantiation to simply use the same storage location. However, when an anonymous
function captures a local variable, the effects of instantiation become apparent.
The example

using System;
delegate void D();
class Test 
{
static D[] F() {
D[] result = new D[3];
for (int i = 0; i  { Console.WriteLine(x); };
}
return result;
}
static void Main() {
foreach (D d in F()) d();
} 
}

produces the following output:
1
3
5
However, when the declaration of xis moved outside the loop

static D[] F() {
D[] result = new D[3];
int x;
for (int i = 0; i  { Console.WriteLine(x); };
}
return result; 
}

the output is
5
5
5
If a forloop declares an iteration variable, that variable itself is considered to be declared
outside of the loop. Thus, if the example is changed to capture the iteration variable itself,

static D[] F() {
D[] result = new D[3];
for (int i = 0; i  { Console.WriteLine(i); };
}
return result; 
}
only one instance of the iteration variable is captured, which produces the following 
output:
3 
3 
3

The reason is C# capture the variable, not the value. It’s a bit hard to warp your head around this

Calling C# from C++

Most of the post on the internet about interoperability is the other way around (Calling C++ from C#) since C# is apparently the superior language in terms of developer friendliness. But a part of research work is to make weird combinations of system work regardless of the reason.

I succeeded in doing just that thank to this Visual C++ example (documentation is available in part 1 of the tutorial).

One thing to add is, I needed a tool to export .NET 4.0 to .tlb files so I can use the same assemblies in C++ (pure C++ and not C++.NET). The tool is called tlbgen, and the syntax is quite simple:

tlbgen System.Net.dll

(Very) crude .NET wrapper for Tesseract 3

I was searching for a quick way to recognize license plates and stumbled upon EmguCV’s sample code. But this code requires Tesseract OCR (An open source OCR engine currently sponsored by Google) and its .NET wrapper. Unfortunately, this code was written when Tesseract was still at version 2, so is the .NET wrapper so none of them will work for me (I need Tesseract 3 to use a new language supported by this version), worse still, the original wrapper developer has stated that he won’t touch Tesseract code again, so the only way to proceed would be to write my own wrapper.

As you may have know, writing and debugging a wrapper for another language is a tedious and painstaking process, so I opted for the easy way out: use Tesseract command line version to recognize text without digging into the source code.

And here’s the result: A wrapper class for Tesseract on .NET – it will write your bitmap to a temporary file, execute Tesseract and extract the result back into the code. Note that this will run very slow, and that’s why I say it’s crude, a better way would be to analyze Tesseract code and write an interop DLL, but i just don’t have time for that 🙂

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;

namespace PlateDetection
{
    class Tesseract
    {
        string Language = "eng";
        const string Program = @"C:Program Files (x86)Tesseract-OCRtesseract";

        /// <summary>
        /// Changes language
        /// </summary>
        /// <param name="language">Language code</param>
        /// <param name="NotUsed">Not used but kept for compatibitily with Tesseract.net old wrapper</param>
        internal void Init(string language, bool NotUsed)
        {
            Language = language;
        }

        /// <summary>
        /// Main function, recognize any text in the bitmap
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="rectangle">Not used, you may change that easily by cutting the bitmap</param>
        /// <returns></returns>
        internal List<string> DoOCR(System.Drawing.Bitmap bmp, System.Drawing.Rectangle rectangle)
        {
            bmp.Save("temp.png", System.Drawing.Imaging.ImageFormat.Png);
            System.Diagnostics.Process.Start(Program, "temp.png temp -l " + Language);
            
            string [] Words = new string[0];
            // The application may need some time to process, file is not ready yet,
            // or the application may still writing
            while (true)
            {
                try
                {
                    Words = File.ReadAllText("temp.txt").Split(new char[] { ' ', 'r', 'n', 't' }, StringSplitOptions.RemoveEmptyEntries);
                    break;
                }
                catch
                {

                }
            }
            File.Delete("temp.png");
            File.Delete("temp.txt");
            List<string> Result = new List<string>(Words);
            return Result;
        }

        /// <summary>
        /// Currently not used as there is no allocation done
        /// </summary>
        internal void Dispose()
        {
            
        }
    }
}

And here’s the full plate detection class

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.Util;
using System.Diagnostics;
using Emgu.CV.Structure;

namespace PlateDetection
{
    /// <summary>
    /// A license plate detector
    /// </summary>
    public class LicensePlateDetector : DisposableObject
    {

        private Tesseract _ocr;

        /// <summary>
        /// Create a license plate detector
        /// </summary>
        public LicensePlateDetector()
        {
            //create OCR
            _ocr = new Tesseract();

            //You can download more language definition data from
            //http://code.google.com/p/tesseract-ocr/downloads/list
            //Languages supported includes:
            //Dutch, Spanish, German, Italian, French and English
            _ocr.Init("eng", false);
        }

        /// <summary>
        /// Create a license plate detector
        /// </summary>
        public LicensePlateDetector(string language)
        {
            //create OCR
            _ocr = new Tesseract();

            //You can download more language definition data from
            //http://code.google.com/p/tesseract-ocr/downloads/list
            //Languages supported includes:
            //Dutch, Spanish, German, Italian, French and English
            _ocr.Init(language, false);
        }

        /// <summary>
        /// Detect license plate from the given image
        /// </summary>
        /// <param name="img">The image to search license plate from</param>
        /// <param name="licensePlateList">A list of images where the detected license plate region is stored</param>
        /// <param name="filteredLicensePlateList">A list of images where the detected license plate region with noise removed is stored</param>
        /// <param name="boxList">A list where the region of license plate, defined by an MCvBox2D is stored</param>
        /// <returns>The list of words for each license plate</returns>
        public List<List<string>> DetectLicensePlate(Image<Bgr, byte> img, List<Image<Gray, Byte>> licensePlateList, List<Image<Gray, Byte>> filteredLicensePlateList, List<MCvBox2D> boxList)
        {
            //Stopwatch w = Stopwatch.StartNew();
            List<List<string>> licenses = new List<List<string>>();
            using (Image<Gray, byte> gray = img.Convert<Gray, Byte>())
            using (Image<Gray, Byte> canny = new Image<Gray, byte>(gray.Size))
            using (MemStorage stor = new MemStorage())
            {
                CvInvoke.cvCanny(gray, canny, 100, 50, 3);

                Contour<Point> 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, licenses);
            }
            //w.Stop();
            return licenses;
        }

        private void FindLicensePlate(
           Contour<Point> contours, Image<Gray, Byte> gray, Image<Gray, Byte> canny,
           List<Image<Gray, Byte>> licensePlateList, List<Image<Gray, Byte>> filteredLicensePlateList, List<MCvBox2D> boxList,
           List<List<string>> licenses)
        {
            for (; contours != null; contours = contours.HNext)
            {
                Contour<Point> approxContour = contours.ApproxPoly(contours.Perimeter * 0.05, contours.Storage);

                if (approxContour.Area > 100 && approxContour.Total == 4)
                {
                    //img.Draw(contours, new Bgr(Color.Red), 1);
                    if (!IsParallelogram(approxContour.ToArray()))
                    {
                        Contour<Point> child = contours.VNext;
                        if (child != null)
                            FindLicensePlate(child, gray, canny, licensePlateList, filteredLicensePlateList, boxList, licenses);
                        continue;
                    }

                    MCvBox2D box = approxContour.GetMinAreaRect();

                    double whRatio = (double)box.size.Width / box.size.Height;
                    if (!(3.0 < whRatio && whRatio < 8.0))
                    {
                        Contour<Point> child = contours.VNext;
                        if (child != null)
                            FindLicensePlate(child, gray, canny, licensePlateList, filteredLicensePlateList, boxList, licenses);
                        continue;
                    }

                    Image<Gray, Byte> plate = gray.Copy(box);
                    Image<Gray, Byte> filteredPlate = FilterPlate(plate);

                    List<string> words;
                    using (Bitmap bmp = filteredPlate.Bitmap)
                        words = _ocr.DoOCR(bmp, filteredPlate.ROI);

                    licenses.Add(words);
                    licensePlateList.Add(plate);
                    filteredLicensePlateList.Add(filteredPlate);
                    boxList.Add(box);
                }
            }
        }

        /// <summary>
        /// Check if the four points forms a parallelogram
        /// </summary>
        /// <param name="pts">The four points that defines a polygon</param>
        /// <returns>True if the four points defines a parallelogram</returns>
        private static bool IsParallelogram(Point[] pts)
        {
            LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

            double diff1 = Math.Abs(edges[0].Length - edges[2].Length);
            double diff2 = Math.Abs(edges[1].Length - edges[3].Length);
            if (diff1 / edges[0].Length <= 0.05 && diff1 / edges[2].Length <= 0.05
               && diff2 / edges[1].Length <= 0.05 && diff2 / edges[3].Length <= 0.05)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// Filter the license plate to remove noise
        /// </summary>
        /// <param name="plate">The license plate image</param>
        /// <returns>License plate image without the noise</returns>
        private static Image<Gray, Byte> FilterPlate(Image<Gray, Byte> plate)
        {
            Image<Gray, Byte> thresh = plate.ThresholdBinaryInv(new Gray(120), new Gray(255));

            using (Image<Gray, Byte> plateMask = new Image<Gray, byte>(plate.Size))
            using (Image<Gray, Byte> plateCanny = plate.Canny(new Gray(100), new Gray(50)))
            using (MemStorage stor = new MemStorage())
            {
                plateMask.SetValue(255.0);
                for (
                   Contour<Point> 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.BoundingRectangle;
                    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();
        }
    }
}

Seeing is believing, here’s a sample of the algorithm run on a live feed off the camera:

And even though I say it’s slow, it’s still fast enough to process my movements and only goes into recognition when the plate is detected, so the performance is acceptable anyways :). The code above is for anyone who just want to test the algorithm to decide whether or not they will use it, I don’t think it’s a good idea to put these into production code 🙂