From 0987f6858a0b2b517b59c6cd364e68e3ae38a2ff Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 17:23:37 +0200 Subject: [PATCH 01/14] Use c++/cli type Byte instead of char so you don't have to cast C# byte[] array to unsigned byte array. --- src/bindings/csharp/openalpr-net/openalpr-net.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index 2849380..38a8ebb 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -55,6 +55,16 @@ namespace openalprnet { return result; } + static std::vector ToVector(array^ src) + { + std::vector result(src->Length); + pin_ptr pin(&src[0]); + char* pch = reinterpret_cast(pin); + char *first(pch), *last(pch + src->Length); + std::copy(first, last, result.begin()); + return result; + } + static cv::Mat BitmapToMat(Bitmap^ bitmap) { int channels = 0; @@ -1308,7 +1318,7 @@ namespace openalprnet { /// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// /// Bytes representing image data - AlprResultsNet^ recognize(cli::array^ imageBuffer) { + AlprResultsNet^ recognize(cli::array^ imageBuffer) { std::vector p = AlprHelper::ToVector(imageBuffer); AlprResults results = m_Impl->recognize(p); return gcnew AlprResultsNet(results); @@ -1317,7 +1327,7 @@ namespace openalprnet { /// /// Recognize from raw pixel data /// - AlprResultsNet^ recognize(cli::array^ pixelData, int bytesPerPixel, int imgWidth, int imgHeight, List^ regionsOfInterest) { + AlprResultsNet^ recognize(cli::array^ pixelData, int bytesPerPixel, int imgWidth, int imgHeight, List^ regionsOfInterest) { unsigned char* p = AlprHelper::ToCharPtr(pixelData); std::vector rois = AlprHelper::ToVector(regionsOfInterest); AlprResults results = m_Impl->recognize(p, bytesPerPixel, imgWidth, imgHeight, rois); From 82cf3f95fb9f52ba985400cd8da438ff8abf7338 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 17:25:26 +0200 Subject: [PATCH 02/14] Add overloads for MemoryStream and byte array to motion detector. --- .../csharp/openalpr-net/openalpr-net.cpp | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index 38a8ebb..05a5ecd 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -100,6 +100,21 @@ namespace openalprnet { return dstMat; } + static cv::Mat MemoryStreamBitmapToMat(MemoryStream^ memoryStream) + { + Bitmap^ bitmap = gcnew Bitmap(memoryStream); + cv::Mat mat = BitmapToMat(bitmap); + return mat; + } + + static cv::Mat ByteArrayToMat(array^ byteArray) + { + MemoryStream^ ms = gcnew MemoryStream(byteArray); + cv::Mat mat(MemoryStreamBitmapToMat(ms)); + delete ms; + return mat; + } + static Bitmap^ MatToBitmap(cv::Mat mat) { const int width = mat.size().width; @@ -223,6 +238,16 @@ namespace openalprnet { return ResetMotionDetection(Mat(filename, matType)); } + void ResetMotionDetection(MemoryStream^ memoryStream) + { + return ResetMotionDetection(Mat(memoryStream)); + } + + void ResetMotionDetection(array^ byteArray) + { + return ResetMotionDetection(Mat(byteArray)); + } + System::Drawing::Rectangle MotionDetect(Bitmap^ bitmap) { return MotionDetect(Mat(bitmap)); @@ -233,6 +258,16 @@ namespace openalprnet { return MotionDetect(Mat(filename, matType)); } + System::Drawing::Rectangle MotionDetect(MemoryStream^ memoryStream) + { + return MotionDetect(Mat(memoryStream)); + } + + System::Drawing::Rectangle MotionDetect(array^ byteArray) + { + return MotionDetect(Mat(byteArray)); + } + private: void ResetMotionDetection(cv::Mat mat) { @@ -257,6 +292,18 @@ namespace openalprnet { return mat; } + cv::Mat Mat(MemoryStream^ memoryStream) + { + cv::Mat mat = AlprHelper::MemoryStreamBitmapToMat(memoryStream); + return mat; + } + + cv::Mat Mat(array^ byteArray) + { + cv::Mat mat = AlprHelper::ByteArrayToMat(byteArray); + return mat; + } + private: ~AlprMotionDetectionNet() From 2e6350b19145fa3a12c8d88ac36d025b6155897f Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 18:13:59 +0200 Subject: [PATCH 03/14] Bugfix: Signed buffer has been removed. --- src/bindings/csharp/openalprnet-cli/Program.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bindings/csharp/openalprnet-cli/Program.cs b/src/bindings/csharp/openalprnet-cli/Program.cs index fee8e32..0f9bd5e 100644 --- a/src/bindings/csharp/openalprnet-cli/Program.cs +++ b/src/bindings/csharp/openalprnet-cli/Program.cs @@ -110,8 +110,7 @@ namespace openalprnet_cli private static void PerformAlpr(AlprNet alpr, byte[] buffer, bool benchmark, bool writeJson) { var sw = Stopwatch.StartNew(); - sbyte[] signedBuffer = (sbyte[])(Array)buffer; - var results = alpr.recognize(signedBuffer); + var results = alpr.recognize(buffer); sw.Stop(); if (benchmark) { From 7be8e3b42b80c3b8019551c25c0940873d39a4e4 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 18:14:27 +0200 Subject: [PATCH 04/14] Bugfix: Incorrect version number. --- src/bindings/csharp/openalpr-net/AssemblyInfo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/AssemblyInfo.cpp b/src/bindings/csharp/openalpr-net/AssemblyInfo.cpp index f600e22..ac5af8d 100644 --- a/src/bindings/csharp/openalpr-net/AssemblyInfo.cpp +++ b/src/bindings/csharp/openalpr-net/AssemblyInfo.cpp @@ -31,9 +31,9 @@ using namespace System::Security::Permissions; // You can specify all the value or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersionAttribute("2.0.1")] -[assembly: AssemblyFileVersionAttribute("2.0.1")] -[assembly: AssemblyInformationalVersionAttribute("2.0.1")] +[assembly: AssemblyVersionAttribute("2.1.0")] +[assembly: AssemblyFileVersionAttribute("2.1.0")] +[assembly: AssemblyInformationalVersionAttribute("2.1.0")] [assembly:ComVisible(false)]; From 1dcb757d980dcc3a9f4f7913685612f930404fae Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 18:43:02 +0200 Subject: [PATCH 05/14] Add additional overloads for recognize. --- .../csharp/openalpr-net/openalpr-net.cpp | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index 05a5ecd..bd0ed82 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -1329,6 +1329,14 @@ namespace openalprnet { return gcnew AlprResultsNet(results); } + /// + /// Recognize from a bitmap + /// + AlprResultsNet^ recognize(Bitmap^ bitmap) + { + return recognize(bitmap, gcnew List()); + } + /// /// Recognize from a bitmap /// @@ -1341,20 +1349,17 @@ namespace openalprnet { } /// - /// Recognize from a bitmap + /// Recognize from MemoryStream representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// - AlprResultsNet^ recognize(Bitmap^ bitmap) + AlprResultsNet^ recognize(MemoryStream^ memoryStream) { - cv::Mat frame = AlprHelper::BitmapToMat(bitmap); - std::vector rois; - AlprResults results = m_Impl->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, rois); - return gcnew AlprResultsNet(results); + return recognize(memoryStream, gcnew List()); } /// /// Recognize from MemoryStream representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// - AlprResultsNet^ recognize(MemoryStream^ memoryStream) + AlprResultsNet^ recognize(MemoryStream^ memoryStream, List^ regionsOfInterest) { std::vector p = AlprHelper::MemoryStreamToVector(memoryStream); AlprResults results = m_Impl->recognize(p); @@ -1366,6 +1371,14 @@ namespace openalprnet { /// /// Bytes representing image data AlprResultsNet^ recognize(cli::array^ imageBuffer) { + return recognize(imageBuffer, gcnew List()); + } + + /// + /// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). + /// + /// Bytes representing image data + AlprResultsNet^ recognize(cli::array^ imageBuffer, List^ regionsOfInterest) { std::vector p = AlprHelper::ToVector(imageBuffer); AlprResults results = m_Impl->recognize(p); return gcnew AlprResultsNet(results); @@ -1374,8 +1387,15 @@ namespace openalprnet { /// /// Recognize from raw pixel data /// - AlprResultsNet^ recognize(cli::array^ pixelData, int bytesPerPixel, int imgWidth, int imgHeight, List^ regionsOfInterest) { - unsigned char* p = AlprHelper::ToCharPtr(pixelData); + AlprResultsNet^ recognize(cli::array^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight) { + return recognize(imageBuffer, bytesPerPixel, imgWidth, imgHeight, gcnew List()); + } + + /// + /// Recognize from raw pixel data + /// + AlprResultsNet^ recognize(cli::array^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight, List^ regionsOfInterest) { + unsigned char* p = AlprHelper::ToCharPtr(imageBuffer); std::vector rois = AlprHelper::ToVector(regionsOfInterest); AlprResults results = m_Impl->recognize(p, bytesPerPixel, imgWidth, imgHeight, rois); free(p); // ?? memory leak? From 7f385a33f356b96a2b98e8382080c64524ac8785 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 18:58:21 +0200 Subject: [PATCH 06/14] Bugfix: Pin memory while copying bitmap raw pointer. --- src/bindings/csharp/openalpr-net/openalpr-net.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index bd0ed82..9884668 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -93,7 +93,10 @@ namespace openalprnet { bitmap->PixelFormat ); - cv::Mat dstMat(cv::Size(bitmap->Width, bitmap->Height), CV_8UC(channels), reinterpret_cast(bitmapData->Scan0.ToPointer())); + char *src = reinterpret_cast(bitmapData->Scan0.ToPointer()); + pin_ptr pin(&src[0]); + + cv::Mat dstMat(cv::Size(bitmap->Width, bitmap->Height), CV_8UC(channels), pin); bitmap->UnlockBits(bitmapData); @@ -147,7 +150,10 @@ namespace openalprnet { bitmap->PixelFormat ); - ::memcpy(bitmapData->Scan0.ToPointer(), data, totalSize); + char *src = reinterpret_cast(bitmapData->Scan0.ToPointer()); + pin_ptr pin(&src[0]); + + ::memcpy(pin, data, totalSize); bitmap->UnlockBits(bitmapData); From 84a032112ca67657ae8da7d6a2b91f26addd5eb0 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 19:27:25 +0200 Subject: [PATCH 07/14] AlprConfigNet ctor must be internal. --- src/bindings/csharp/openalpr-net/openalpr-net.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index 9884668..37a1615 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -342,13 +342,14 @@ namespace openalprnet { public ref class AlprConfigNet sealed { - public: - - AlprConfigNet(Config* config) : m_config (config) + internal: + AlprConfigNet(Config* config) : m_config(config) { - + } + public: + property bool IsLoaded { bool get() { From c3fb3d950306af702915acbf8383f0e226b07381 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 19:40:19 +0200 Subject: [PATCH 08/14] Capitalize variables / function in order to adhere to .NET naming convention. --- .../csharp/openalpr-net/openalpr-net.cpp | 82 +++++++++---------- .../csharp/openalprnet-cli/Program.cs | 18 ++-- .../csharp/openalprnet-windemo/Form1.cs | 30 ++++--- 3 files changed, 69 insertions(+), 61 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index 37a1615..eafc926 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -314,13 +314,13 @@ namespace openalprnet { ~AlprMotionDetectionNet() { - if(this->m_Disposed) + if(this->m_disposed) { return; } this->!AlprMotionDetectionNet(); - this->m_Disposed = true; + this->m_disposed = true; } !AlprMotionDetectionNet() @@ -330,7 +330,7 @@ namespace openalprnet { private: MotionDetector* m_motionDetector; - bool m_Disposed; + bool m_disposed; }; @@ -477,7 +477,7 @@ namespace openalprnet { } } - property float minPlateSizeHeightPx { + property float MinPlateSizeHeightPx { float get() { return this->m_config->minPlateSizeHeightPx; @@ -994,19 +994,19 @@ namespace openalprnet { m_matches_template=plate.matches_template; } - property System::String^ characters { + property System::String^ Characters { System::String^ get() { return m_characters; } } - property float overall_confidence { + property float OverallConfidence { float get() { return m_overall_confidence; } } - property bool matches_template { + property bool MatchesTemplate { bool get() { return m_matches_template; } @@ -1042,49 +1042,49 @@ namespace openalprnet { } } - property int requested_topn { + property int RequestedTopN { int get() { return m_requested_topn; } } - property int regionConfidence { + property int RegionConfidence { int get() { return m_regionConfidence; } } - property int plate_index { + property int PlateIndex { int get() { return m_plate_index; } } - property System::String^ region { + property System::String^ Region { System::String^ get() { return m_region; } } - property AlprPlateNet^ bestPlate { + property AlprPlateNet^ BestPlate { AlprPlateNet^ get() { return m_bestPlate; } } - property List^ plate_points { + property List^ PlatePoints { List^ get() { return m_plate_points; } } - property List^ topNPlates { + property List^ TopNPlates { List^ get() { return m_topNPlates; } } - property float processing_time_ms { + property float ProcessingTimeMs { float get() { return m_processing_time_ms; } @@ -1133,43 +1133,43 @@ namespace openalprnet { m_json = AlprHelper::ToManagedString(json); } - property long epoch_time { + property long EpochTime { long get() { return m_epoch_time; } } - property int img_width { + property int ImageWidth { int get() { return m_img_width; } } - property int img_height { + property int ImageHeight { int get() { return m_img_height; } } - property float total_processing_time_ms { + property float TotalProcessingTimeMs { float get() { return m_total_processing_time_ms; } } - property List^ regionsOfInterest { + property List^ RegionsOfInterest { List^ get() { return m_regionsOfInterest; } } - property List^ plates { + property List^ Plates { List^ get() { return m_plates; } } - property System::String^ json { + property System::String^ Json { System::String^ get() { return m_json; } @@ -1239,13 +1239,13 @@ namespace openalprnet { } ~AlprNet() { - if(this->m_Disposed) + if(this->m_disposed) { return; } this->!AlprNet(); - this->m_Disposed = true; + this->m_disposed = true; } property AlprConfigNet^ Configuration { @@ -1321,7 +1321,7 @@ namespace openalprnet { /// /// Recognize from an image on disk /// - AlprResultsNet^ recognize(System::String^ filepath) { + AlprResultsNet^ Recognize(System::String^ filepath) { AlprResults results = m_Impl->recognize(marshal_as(filepath)); return gcnew AlprResultsNet(results); } @@ -1329,7 +1329,7 @@ namespace openalprnet { /// /// Recognize from an image on disk /// - AlprResultsNet^ recognize(System::String^ filepath, List^ regionsOfInterest) { + AlprResultsNet^ Recognize(System::String^ filepath, List^ regionsOfInterest) { cv::Mat frame = cv::imread( marshal_as(filepath) ); std::vector rois = AlprHelper::ToVector(regionsOfInterest); AlprResults results = m_Impl->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, rois ); @@ -1339,15 +1339,15 @@ namespace openalprnet { /// /// Recognize from a bitmap /// - AlprResultsNet^ recognize(Bitmap^ bitmap) + AlprResultsNet^ Recognize(Bitmap^ bitmap) { - return recognize(bitmap, gcnew List()); + return Recognize(bitmap, gcnew List()); } /// /// Recognize from a bitmap /// - AlprResultsNet^ recognize(Bitmap^ bitmap, List^ regionsOfInterest) + AlprResultsNet^ Recognize(Bitmap^ bitmap, List^ regionsOfInterest) { cv::Mat frame = AlprHelper::BitmapToMat(bitmap); std::vector rois = AlprHelper::ToVector(regionsOfInterest); @@ -1358,15 +1358,15 @@ namespace openalprnet { /// /// Recognize from MemoryStream representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// - AlprResultsNet^ recognize(MemoryStream^ memoryStream) + AlprResultsNet^ Recognize(MemoryStream^ memoryStream) { - return recognize(memoryStream, gcnew List()); + return Recognize(memoryStream, gcnew List()); } /// /// Recognize from MemoryStream representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// - AlprResultsNet^ recognize(MemoryStream^ memoryStream, List^ regionsOfInterest) + AlprResultsNet^ Recognize(MemoryStream^ memoryStream, List^ regionsOfInterest) { std::vector p = AlprHelper::MemoryStreamToVector(memoryStream); AlprResults results = m_Impl->recognize(p); @@ -1377,15 +1377,15 @@ namespace openalprnet { /// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// /// Bytes representing image data - AlprResultsNet^ recognize(cli::array^ imageBuffer) { - return recognize(imageBuffer, gcnew List()); + AlprResultsNet^ Recognize(cli::array^ imageBuffer) { + return Recognize(imageBuffer, gcnew List()); } /// /// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// /// Bytes representing image data - AlprResultsNet^ recognize(cli::array^ imageBuffer, List^ regionsOfInterest) { + AlprResultsNet^ Recognize(cli::array^ imageBuffer, List^ regionsOfInterest) { std::vector p = AlprHelper::ToVector(imageBuffer); AlprResults results = m_Impl->recognize(p); return gcnew AlprResultsNet(results); @@ -1394,14 +1394,14 @@ namespace openalprnet { /// /// Recognize from raw pixel data /// - AlprResultsNet^ recognize(cli::array^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight) { - return recognize(imageBuffer, bytesPerPixel, imgWidth, imgHeight, gcnew List()); + AlprResultsNet^ Recognize(cli::array^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight) { + return Recognize(imageBuffer, bytesPerPixel, imgWidth, imgHeight, gcnew List()); } /// /// Recognize from raw pixel data /// - AlprResultsNet^ recognize(cli::array^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight, List^ regionsOfInterest) { + AlprResultsNet^ Recognize(cli::array^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight, List^ regionsOfInterest) { unsigned char* p = AlprHelper::ToCharPtr(imageBuffer); std::vector rois = AlprHelper::ToVector(regionsOfInterest); AlprResults results = m_Impl->recognize(p, bytesPerPixel, imgWidth, imgHeight, rois); @@ -1409,11 +1409,11 @@ namespace openalprnet { return gcnew AlprResultsNet(results); } - bool isLoaded() { + bool IsLoaded() { return m_Impl->isLoaded(); } - static System::String^ getVersion() { + static System::String^ GetVersion() { return AlprHelper::ToManagedString(Alpr::getVersion()); } @@ -1430,6 +1430,6 @@ namespace openalprnet { int m_topN; bool m_detectRegion; System::String^ m_defaultRegion; - bool m_Disposed; + bool m_disposed; }; } diff --git a/src/bindings/csharp/openalprnet-cli/Program.cs b/src/bindings/csharp/openalprnet-cli/Program.cs index 0f9bd5e..556d4d3 100644 --- a/src/bindings/csharp/openalprnet-cli/Program.cs +++ b/src/bindings/csharp/openalprnet-cli/Program.cs @@ -66,11 +66,11 @@ namespace openalprnet_cli val => { if (val.Any()) filename = val.First().Trim(); }) ); - Console.WriteLine("OpenAlpr Version: {0}", AlprNet.getVersion()); + Console.WriteLine("OpenAlpr Version: {0}", AlprNet.GetVersion()); var config = Path.Combine(AssemblyDirectory, "openalpr.conf"); var runtime_data = Path.Combine(AssemblyDirectory, "runtime_data"); var alpr = new AlprNet(region, config, runtime_data); - if (!alpr.isLoaded()) + if (!alpr.IsLoaded()) { Console.WriteLine("OpenAlpr failed to load!"); return; @@ -110,7 +110,7 @@ namespace openalprnet_cli private static void PerformAlpr(AlprNet alpr, byte[] buffer, bool benchmark, bool writeJson) { var sw = Stopwatch.StartNew(); - var results = alpr.recognize(buffer); + var results = alpr.Recognize(buffer); sw.Stop(); if (benchmark) { @@ -124,14 +124,14 @@ namespace openalprnet_cli else { var i = 0; - foreach (var result in results.plates) + foreach (var result in results.Plates) { - Console.WriteLine("Plate {0}: {1} result(s)", i++, result.topNPlates.Count); - Console.WriteLine(" Processing Time: {0} msec(s)", result.processing_time_ms); - foreach (var plate in result.topNPlates) + Console.WriteLine("Plate {0}: {1} result(s)", i++, result.TopNPlates.Count); + Console.WriteLine(" Processing Time: {0} msec(s)", result.ProcessingTimeMs); + foreach (var plate in result.TopNPlates) { - Console.WriteLine(" - {0}\t Confidence: {1}\tMatches Template: {2}", plate.characters, - plate.overall_confidence, plate.matches_template); + Console.WriteLine(" - {0}\t Confidence: {1}\tMatches Template: {2}", plate.Characters, + plate.OverallConfidence, plate.MatchesTemplate); } } } diff --git a/src/bindings/csharp/openalprnet-windemo/Form1.cs b/src/bindings/csharp/openalprnet-windemo/Form1.cs index 98587c8..e60ab62 100644 --- a/src/bindings/csharp/openalprnet-windemo/Form1.cs +++ b/src/bindings/csharp/openalprnet-windemo/Form1.cs @@ -22,6 +22,7 @@ using System.Drawing; using System.IO; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using System.Windows.Forms; using openalprnet; @@ -135,7 +136,7 @@ namespace openalprnet_windemo String runtime_data_dir = Path.Combine(AssemblyDirectory, "runtime_data"); using (var alpr = new AlprNet(region, config_file, runtime_data_dir)) { - if (!alpr.isLoaded()) + if (!alpr.IsLoaded()) { lbxPlates.Items.Add("Error initializing OpenALPR"); return; @@ -143,24 +144,31 @@ namespace openalprnet_windemo picOriginal.ImageLocation = fileName; picOriginal.Load(); - var results = alpr.recognize(fileName); - - var images = new List(results.plates.Count()); - var i = 1; - foreach (var result in results.plates) + var motionDetection = new AlprMotionDetectionNet(); + var b = File.ReadAllBytes(fileName); + Parallel.For(0, int.MaxValue, (x) => { - var rect = boundingRectangle(result.plate_points); + motionDetection.MotionDetect(b); + }); + + var results = alpr.Recognize(fileName); + + var images = new List(results.Plates.Count()); + var i = 1; + foreach (var result in results.Plates) + { + var rect = boundingRectangle(result.PlatePoints); var img = Image.FromFile(fileName); var cropped = cropImage(img, rect); images.Add(cropped); lbxPlates.Items.Add("\t\t-- Plate #" + i++ + " --"); - foreach (var plate in result.topNPlates) + foreach (var plate in result.TopNPlates) { lbxPlates.Items.Add(string.Format(@"{0} {1}% {2}", - plate.characters.PadRight(12), - plate.overall_confidence.ToString("N1").PadLeft(8), - plate.matches_template.ToString().PadLeft(8))); + plate.Characters.PadRight(12), + plate.OverallConfidence.ToString("N1").PadLeft(8), + plate.MatchesTemplate.ToString().PadLeft(8))); } } From 32a3a330ab86bdabdda6ed3013ca3bbb7b335160 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 22:31:37 +0200 Subject: [PATCH 09/14] Bugfix: DetectionStrictness is an int, not float. --- src/bindings/csharp/openalpr-net/openalpr-net.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index eafc926..9c0c844 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -378,12 +378,12 @@ namespace openalprnet { } } - property float DetectionStrictness { - float get() + property int DetectionStrictness { + int get() { return this->m_config->detectionStrictness; } - void set(float value) + void set(int value) { this->m_config->detectionStrictness = value; } From 87d5cb500970e3c160f28b6738fed3c59a3039bd Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 23:06:06 +0200 Subject: [PATCH 10/14] Bugfix: Avoid nasty memory leaks by adding a wrapper class for converting a bitmap to cv::Mat. --- .../csharp/openalpr-net/openalpr-net.cpp | 187 ++++++++++++------ 1 file changed, 124 insertions(+), 63 deletions(-) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index 9c0c844..df279c3 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -43,29 +43,62 @@ using namespace alpr; namespace openalprnet { private ref class AlprHelper sealed + private ref class BitmapMat : IDisposable { + private: + cv::Mat* m_bitmap; + bool m_disposed; public: - static std::vector ToVector(array^ src) + BitmapMat(array^ byteArray) { - std::vector result(src->Length); - pin_ptr pin(&src[0]); - char *first(pin), *last(pin + src->Length); - std::copy(first, last, result.begin()); - return result; + this->m_bitmap = ByteArrayToMat(byteArray); } - static std::vector ToVector(array^ src) + BitmapMat(Bitmap^ bitmap) { - std::vector result(src->Length); - pin_ptr pin(&src[0]); - char* pch = reinterpret_cast(pin); - char *first(pch), *last(pch + src->Length); - std::copy(first, last, result.begin()); - return result; + this->m_bitmap = BitmapToMat(bitmap); } - static cv::Mat BitmapToMat(Bitmap^ bitmap) + BitmapMat(MemoryStream^ memoryStream) + { + this->m_bitmap = MemoryStreamBitmapToMat(memoryStream); + } + + BitmapMat(String^ filename) + { + Bitmap^ bitmap = gcnew Bitmap(filename); + this->m_bitmap = BitmapToMat(bitmap); + delete bitmap; + } + + property cv::Mat Value { + cv::Mat get() + { + cv::Mat value = this->m_bitmap->clone(); + return value; + } + } + + ~BitmapMat() + { + if (this->m_disposed) + { + return; + } + + this->!BitmapMat(); + this->m_disposed = true; + } + + !BitmapMat() + { + delete[] m_bitmap->data; + } + + private: + + static cv::Mat* BitmapToMat(Bitmap^ bitmap) { int channels = 0; @@ -93,31 +126,59 @@ namespace openalprnet { bitmap->PixelFormat ); - char *src = reinterpret_cast(bitmapData->Scan0.ToPointer()); - pin_ptr pin(&src[0]); + const int totalBytes = bitmap->Height * bitmapData->Stride; - cv::Mat dstMat(cv::Size(bitmap->Width, bitmap->Height), CV_8UC(channels), pin); + char *dst = new char[totalBytes]; + ::memcpy(dst, bitmapData->Scan0.ToPointer(), totalBytes); + + cv::Mat* dstMat = new cv::Mat(cv::Size(bitmap->Width, bitmap->Height), CV_8UC(channels), dst); bitmap->UnlockBits(bitmapData); return dstMat; } - static cv::Mat MemoryStreamBitmapToMat(MemoryStream^ memoryStream) + static cv::Mat* MemoryStreamBitmapToMat(MemoryStream^ memoryStream) { Bitmap^ bitmap = gcnew Bitmap(memoryStream); - cv::Mat mat = BitmapToMat(bitmap); + cv::Mat* mat = BitmapToMat(bitmap); + delete bitmap; return mat; } - static cv::Mat ByteArrayToMat(array^ byteArray) + static cv::Mat* ByteArrayToMat(array^ byteArray) { MemoryStream^ ms = gcnew MemoryStream(byteArray); - cv::Mat mat(MemoryStreamBitmapToMat(ms)); + cv::Mat* mat = MemoryStreamBitmapToMat(ms); delete ms; return mat; } + }; + + private ref class AlprHelper sealed + { + public: + + static std::vector ToVector(array^ src) + { + std::vector result(src->Length); + pin_ptr pin(&src[0]); + char *first(pin), *last(pin + src->Length); + std::copy(first, last, result.begin()); + return result; + } + + static std::vector ToVector(array^ src) + { + std::vector result(src->Length); + pin_ptr pin(&src[0]); + char* pch = reinterpret_cast(pin); + char *first(pch), *last(pch + src->Length); + std::copy(first, last, result.begin()); + return result; + } + static Bitmap^ MatToBitmap(cv::Mat mat) { const int width = mat.size().width; @@ -217,14 +278,16 @@ namespace openalprnet { return System::Drawing::Rectangle(rect.x, rect.y, rect.width, rect.height); } - }; + static List^ ToRectangleList(std::vector srcRects) + { + List^ rects = gcnew List(); + for each(cv::Rect rect in srcRects) + { + rects->Add(ToRectangle(rect)); + } + return rects; + } - public enum class OpenCVMatType { - Unchanged = CV_LOAD_IMAGE_UNCHANGED, - Grayscale = CV_LOAD_IMAGE_GRAYSCALE, - Color = CV_LOAD_IMAGE_COLOR, - AnyDepth = CV_LOAD_IMAGE_ANYDEPTH, - AnyColor = CV_LOAD_IMAGE_ANYCOLOR }; public ref class AlprMotionDetectionNet : IDisposable { @@ -236,42 +299,62 @@ namespace openalprnet { void ResetMotionDetection(Bitmap^ bitmap) { - ResetMotionDetection(Mat(bitmap)); + BitmapMat^ wrapper = gcnew BitmapMat(bitmap); + ResetMotionDetection(wrapper->Value); + delete wrapper; } - void ResetMotionDetection(String^ filename, OpenCVMatType matType) + void ResetMotionDetection(String^ filename) { - return ResetMotionDetection(Mat(filename, matType)); + BitmapMat^ wrapper = gcnew BitmapMat(filename); + ResetMotionDetection(wrapper->Value); + delete wrapper; } void ResetMotionDetection(MemoryStream^ memoryStream) { - return ResetMotionDetection(Mat(memoryStream)); + BitmapMat^ wrapper = gcnew BitmapMat(memoryStream); + ResetMotionDetection(wrapper->Value); + delete wrapper; } void ResetMotionDetection(array^ byteArray) { - return ResetMotionDetection(Mat(byteArray)); + BitmapMat^ wrapper = gcnew BitmapMat(byteArray); + ResetMotionDetection(wrapper->Value); + delete wrapper; } System::Drawing::Rectangle MotionDetect(Bitmap^ bitmap) { - return MotionDetect(Mat(bitmap)); + BitmapMat^ wrapper = gcnew BitmapMat(bitmap); + System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); + delete wrapper; + return motion; } - System::Drawing::Rectangle MotionDetect(String^ filename, OpenCVMatType matType) + System::Drawing::Rectangle MotionDetect(String^ filename) { - return MotionDetect(Mat(filename, matType)); + BitmapMat^ wrapper = gcnew BitmapMat(filename); + System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); + delete wrapper; + return motion; } System::Drawing::Rectangle MotionDetect(MemoryStream^ memoryStream) { - return MotionDetect(Mat(memoryStream)); + BitmapMat^ wrapper = gcnew BitmapMat(memoryStream); + System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); + delete wrapper; + return motion; } System::Drawing::Rectangle MotionDetect(array^ byteArray) { - return MotionDetect(Mat(byteArray)); + BitmapMat^ wrapper = gcnew BitmapMat(byteArray); + System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); + delete wrapper; + return motion; } private: @@ -286,30 +369,6 @@ namespace openalprnet { return AlprHelper::ToRectangle(rect); } - cv::Mat Mat(String^ filename, OpenCVMatType matType) - { - cv::Mat mat = cv::imread(AlprHelper::ToStlString(filename), static_cast(matType)); - return mat; - } - - cv::Mat Mat(Bitmap^ bitmap) - { - cv::Mat mat = AlprHelper::BitmapToMat(bitmap); - return mat; - } - - cv::Mat Mat(MemoryStream^ memoryStream) - { - cv::Mat mat = AlprHelper::MemoryStreamBitmapToMat(memoryStream); - return mat; - } - - cv::Mat Mat(array^ byteArray) - { - cv::Mat mat = AlprHelper::ByteArrayToMat(byteArray); - return mat; - } - private: ~AlprMotionDetectionNet() @@ -1349,9 +1408,11 @@ namespace openalprnet { /// AlprResultsNet^ Recognize(Bitmap^ bitmap, List^ regionsOfInterest) { - cv::Mat frame = AlprHelper::BitmapToMat(bitmap); + BitmapMat^ wrapper = gcnew BitmapMat(bitmap); + cv::Mat frame = wrapper->Value; std::vector rois = AlprHelper::ToVector(regionsOfInterest); AlprResults results = m_Impl->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, rois); + delete wrapper; return gcnew AlprResultsNet(results); } From d9f6571e1704720e9993054cd64aa550ad052c22 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Thu, 9 Jul 2015 23:07:17 +0200 Subject: [PATCH 11/14] Bugfix: Motion detector is not thread safe. --- src/bindings/csharp/openalpr-net/openalpr-net.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index df279c3..42ad9b2 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -39,10 +39,21 @@ using namespace System::Drawing; using namespace System::Drawing::Imaging; using namespace System::IO; using namespace alpr; +using namespace System::Threading; namespace openalprnet { - private ref class AlprHelper sealed + private ref class Lock { + Object^ m_pObject; + public: + Lock(Object ^ pObject) : m_pObject(pObject) { + Monitor::Enter(m_pObject); + } + ~Lock() { + Monitor::Exit(m_pObject); + } + }; + private ref class BitmapMat : IDisposable { private: @@ -360,11 +371,13 @@ namespace openalprnet { private: void ResetMotionDetection(cv::Mat mat) { + Lock lock(this); this->m_motionDetector->ResetMotionDetection(&mat); } System::Drawing::Rectangle MotionDetect(cv::Mat mat) { + Lock lock(this); cv::Rect rect = this->m_motionDetector->MotionDetect(&mat); return AlprHelper::ToRectangle(rect); } From 5d3281d8cd49fea96db41ebfa183509dd9275ac2 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Fri, 10 Jul 2015 09:48:16 +0200 Subject: [PATCH 12/14] Refactor openalpr-net into separate files instead of having one huge file. --- .../csharp/openalpr-net/bitmapmat-net.cpp | 27 + .../csharp/openalpr-net/bitmapmat-net.h | 106 ++ src/bindings/csharp/openalpr-net/config-net.h | 656 +++++++++++ src/bindings/csharp/openalpr-net/helper-net.h | 162 +++ src/bindings/csharp/openalpr-net/lock-net.h | 18 + .../openalpr-net/motiondetector-net.cpp | 79 ++ .../csharp/openalpr-net/motiondetector-net.h | 52 + .../csharp/openalpr-net/openalpr-net.cpp | 1033 ----------------- .../csharp/openalpr-net/openalpr-net.h | 19 +- .../csharp/openalpr-net/openalpr-net.vcxproj | 40 +- .../openalpr-net/openalpr-net.vcxproj.filters | 24 + src/bindings/csharp/openalpr-net/types-net.h | 18 + 12 files changed, 1183 insertions(+), 1051 deletions(-) create mode 100644 src/bindings/csharp/openalpr-net/bitmapmat-net.cpp create mode 100644 src/bindings/csharp/openalpr-net/bitmapmat-net.h create mode 100644 src/bindings/csharp/openalpr-net/config-net.h create mode 100644 src/bindings/csharp/openalpr-net/helper-net.h create mode 100644 src/bindings/csharp/openalpr-net/lock-net.h create mode 100644 src/bindings/csharp/openalpr-net/motiondetector-net.cpp create mode 100644 src/bindings/csharp/openalpr-net/motiondetector-net.h create mode 100644 src/bindings/csharp/openalpr-net/types-net.h diff --git a/src/bindings/csharp/openalpr-net/bitmapmat-net.cpp b/src/bindings/csharp/openalpr-net/bitmapmat-net.cpp new file mode 100644 index 0000000..69db8f7 --- /dev/null +++ b/src/bindings/csharp/openalpr-net/bitmapmat-net.cpp @@ -0,0 +1,27 @@ +#include "stdafx.h" +#include "bitmapmat-net.h" + +using namespace openalprnet; + +BitmapMat::BitmapMat(array^ byteArray) +{ + this->m_bitmap = ByteArrayToMat(byteArray); +} + +BitmapMat::BitmapMat(Bitmap^ bitmap) +{ + this->m_bitmap = BitmapToMat(bitmap); +} + +BitmapMat::BitmapMat(MemoryStream^ memoryStream) +{ + this->m_bitmap = MemoryStreamBitmapToMat(memoryStream); +} + +BitmapMat::BitmapMat(String^ filename) +{ + Bitmap^ bitmap = gcnew Bitmap(filename); + this->m_bitmap = BitmapToMat(bitmap); + delete bitmap; +} + diff --git a/src/bindings/csharp/openalpr-net/bitmapmat-net.h b/src/bindings/csharp/openalpr-net/bitmapmat-net.h new file mode 100644 index 0000000..a65acf3 --- /dev/null +++ b/src/bindings/csharp/openalpr-net/bitmapmat-net.h @@ -0,0 +1,106 @@ +#pragma once + +#include "opencv2/imgproc/imgproc.hpp" + +using namespace System; +using namespace System::Drawing; +using namespace System::Drawing::Imaging; +using namespace System::IO; + +namespace openalprnet { + + private ref class BitmapMat : IDisposable + { + private: + cv::Mat* m_bitmap; + bool m_disposed; + public: + BitmapMat(array^ byteArray); + BitmapMat(Bitmap^ bitmap); + BitmapMat(MemoryStream^ memoryStream); + BitmapMat(String^ filename); + + ~BitmapMat() + { + if (this->m_disposed) + { + return; + } + + this->!BitmapMat(); + this->m_disposed = true; + } + + !BitmapMat() + { + delete[] m_bitmap->data; + } + + property cv::Mat Value { + cv::Mat get() + { + cv::Mat value = this->m_bitmap->clone(); + return value; + } + } + + private: + + static cv::Mat* BitmapToMat(Bitmap^ bitmap) + { + int channels = 0; + + switch (bitmap->PixelFormat) + { + case PixelFormat::Format8bppIndexed: + case PixelFormat::Format1bppIndexed: + channels = 1; + break; + case PixelFormat::Format24bppRgb: + channels = 3; + break; + case PixelFormat::Format32bppRgb: + case PixelFormat::Format32bppArgb: + case PixelFormat::Format32bppPArgb: + channels = 4; + break; + default: + throw gcnew NotImplementedException(); + } + + BitmapData^ bitmapData = bitmap->LockBits( + System::Drawing::Rectangle(0, 0, bitmap->Width, bitmap->Height), + ImageLockMode::ReadOnly, + bitmap->PixelFormat + ); + + const int totalBytes = bitmap->Height * bitmapData->Stride; + + char *dst = new char[totalBytes]; + ::memcpy(dst, bitmapData->Scan0.ToPointer(), totalBytes); + + cv::Mat* dstMat = new cv::Mat(cv::Size(bitmap->Width, bitmap->Height), CV_8UC(channels), dst); + + bitmap->UnlockBits(bitmapData); + + return dstMat; + } + + static cv::Mat* MemoryStreamBitmapToMat(MemoryStream^ memoryStream) + { + Bitmap^ bitmap = gcnew Bitmap(memoryStream); + cv::Mat* mat = BitmapToMat(bitmap); + delete bitmap; + return mat; + } + + static cv::Mat* ByteArrayToMat(array^ byteArray) + { + MemoryStream^ ms = gcnew MemoryStream(byteArray); + cv::Mat* mat = MemoryStreamBitmapToMat(ms); + delete ms; + return mat; + } + + }; +} \ No newline at end of file diff --git a/src/bindings/csharp/openalpr-net/config-net.h b/src/bindings/csharp/openalpr-net/config-net.h new file mode 100644 index 0000000..e591b1a --- /dev/null +++ b/src/bindings/csharp/openalpr-net/config-net.h @@ -0,0 +1,656 @@ +#pragma once + +#include "config.h" // alpr +#include "types-net.h" +#include "helper-net.h" + +using namespace System; +using namespace openalprnet::types; + +namespace openalprnet +{ + + public ref class AlprConfigNet sealed + { + internal: + AlprConfigNet(Config* config) : m_config(config) + { + + } + + public: + + property bool IsLoaded { + bool get() + { + return this->m_config->loaded; + } + } + + property AlprDetectorTypeNet Detector { + AlprDetectorTypeNet get() { + return static_cast(this->m_config->detector); + } + void set(AlprDetectorTypeNet value) + { + this->m_config->detector = static_cast(value); + } + } + + property float DetectionIterationIncrease { + float get() + { + return this->m_config->detection_iteration_increase; + } + void set(float value) + { + this->m_config->detection_iteration_increase = value; + } + } + + property int DetectionStrictness { + int get() + { + return this->m_config->detectionStrictness; + } + void set(int value) + { + this->m_config->detectionStrictness = value; + } + } + + property float MaxPlateWidthPercent { + float get() + { + return this->m_config->maxPlateWidthPercent; + } + void set(float value) + { + this->m_config->maxPlateWidthPercent = value; + } + } + + property float MaxPlateHeightPercent { + float get() + { + return this->m_config->maxPlateHeightPercent; + } + void set(float value) + { + this->m_config->maxPlateHeightPercent = value; + } + } + + property int MaxDetectionInputWidth { + int get() + { + return this->m_config->maxDetectionInputWidth; + } + void set(int value) + { + this->m_config->maxDetectionInputWidth = value; + } + } + + property int MaxDetectionInputHeight { + int get() + { + return this->m_config->maxDetectionInputHeight; + } + void set(int value) + { + this->m_config->maxDetectionInputHeight = value; + } + } + + property bool SkipDetection { + bool get() + { + return this->m_config->skipDetection; + } + void set(bool value) + { + this->m_config->skipDetection = true; + } + } + + property String^ PreWarp { + String^ get() + { + return AlprHelper::ToManagedString(this->m_config->prewarp); + } + void set(String^ value) + { + this->m_config->prewarp = marshal_as(value); + } + } + + property int MaxPlateAngleDegrees { + int get() + { + return this->m_config->maxPlateAngleDegrees; + } + void set(int value) + { + this->m_config->maxPlateAngleDegrees = value; + } + } + + property float MinPlateSizeWidthPx { + float get() + { + return this->m_config->minPlateSizeWidthPx; + } + void set(float value) + { + this->m_config->minPlateSizeWidthPx = value; + } + } + + property float MinPlateSizeHeightPx { + float get() + { + return this->m_config->minPlateSizeHeightPx; + } + void set(float value) + { + this->m_config->minPlateSizeHeightPx = value; + } + } + + property bool Multiline { + bool get() + { + return this->m_config->multiline; + } + void set(bool value) + { + this->m_config->multiline = value; + } + } + + property float PlateWidthMM { + float get() + { + return this->m_config->plateWidthMM; + } + void set(float value) + { + this->m_config->plateWidthMM = value; + } + } + + property float PlateHeightMM { + float get() + { + return this->m_config->plateHeightMM; + } + void set(float value) + { + this->m_config->plateHeightMM = value; + } + } + + property float CharHeightMM { + float get() + { + return this->m_config->charHeightMM; + } + void set(float value) + { + this->m_config->charHeightMM = value; + } + } + + property float CharWidthMM { + float get() + { + return this->m_config->charWidthMM; + } + void set(float value) + { + this->m_config->charWidthMM = value; + } + } + + property float CharWhitespaceTopMM { + float get() + { + return this->m_config->charWhitespaceTopMM; + } + void set(float value) + { + this->m_config->charWhitespaceTopMM = value; + } + } + + property float CharWhitespaceBotMM { + float get() + { + return this->m_config->charWhitespaceBotMM; + } + void set(float value) + { + this->m_config->charWhitespaceBotMM = value; + } + } + + property int TemplateWidthPx { + int get() + { + return this->m_config->templateWidthPx; + } + void set(int value) + { + this->m_config->templateWidthPx = value; + } + } + + property int TemplateHeightPx { + int get() + { + return this->m_config->templateHeightPx; + } + void set(int value) + { + this->m_config->templateHeightPx = value; + } + } + + property int OcrImageWidthPx { + int get() + { + return this->m_config->ocrImageWidthPx; + } + void set(int value) + { + this->m_config->ocrImageWidthPx = value; + } + } + + property int OcrImageHeightPx { + int get() + { + return this->m_config->ocrImageHeightPx; + } + void set(int value) + { + this->m_config->ocrImageHeightPx = value; + } + } + + property int StateIdImageWidthPx { + int get() + { + return this->m_config->stateIdImageWidthPx; + } + void set(int value) + { + this->m_config->stateIdImageWidthPx = value; + } + } + + property int StateIdimageHeightPx { + int get() + { + return this->m_config->stateIdimageHeightPx; + } + void set(int value) + { + this->m_config->stateIdimageHeightPx = value; + } + } + + property float CharAnalysisMinPercent { + float get() + { + return this->m_config->charAnalysisMinPercent; + } + void set(float value) + { + this->m_config->charAnalysisMinPercent = value; + } + } + + property float CharAnalysisHeightRange { + float get() + { + return this->m_config->charAnalysisHeightRange; + } + void set(float value) + { + this->m_config->charAnalysisHeightRange = value; + } + } + + property float CharAnalysisHeightStepSize { + float get() + { + return this->m_config->charAnalysisHeightStepSize; + } + void set(float value) + { + this->m_config->charAnalysisHeightStepSize = value; + } + } + + property int CharAnalysisNumSteps { + int get() + { + return this->m_config->charAnalysisNumSteps; + } + void set(int value) + { + this->m_config->charAnalysisNumSteps = value; + } + } + + property float PlateLinesSensitivityVertical { + float get() + { + return this->m_config->plateLinesSensitivityVertical; + } + void set(float value) + { + this->m_config->plateLinesSensitivityVertical = value; + } + } + + property float PlateLinesSensitivityHorizontal { + float get() + { + return this->m_config->plateLinesSensitivityHorizontal; + } + void set(float value) + { + this->m_config->plateLinesSensitivityHorizontal = value; + } + } + + property int SegmentationMinBoxWidthPx { + int get() + { + return this->m_config->segmentationMinBoxWidthPx; + } + void set(int value) + { + this->m_config->segmentationMinBoxWidthPx = value; + } + } + + property float SegmentationMinCharHeightPercent { + float get() + { + return this->m_config->segmentationMinCharHeightPercent; + } + void set(float value) + { + this->m_config->segmentationMinCharHeightPercent = value; + } + } + + property float SegmentationMaxCharWidthvsAverage { + float get() + { + return this->m_config->segmentationMaxCharWidthvsAverage; + } + void set(float value) + { + this->m_config->segmentationMaxCharWidthvsAverage = value; + } + } + + property String^ OcrLanguage { + String^ get() + { + return AlprHelper::ToManagedString(this->m_config->ocrLanguage); + } + void set(String^ value) + { + this->m_config->ocrLanguage = marshal_as(value); + } + } + + property int OcrMinFontSize { + int get() + { + return this->m_config->ocrMinFontSize; + } + void set(int value) + { + this->m_config->ocrMinFontSize = value; + } + } + + property float PostProcessMinConfidence { + float get() + { + return this->m_config->postProcessMinConfidence; + } + void set(float value) + { + this->m_config->postProcessMinConfidence = value; + } + } + + property float PostProcessConfidenceSkipLevel { + float get() + { + return this->m_config->postProcessConfidenceSkipLevel; + } + void set(float value) + { + this->m_config->postProcessConfidenceSkipLevel = value; + } + } + + property unsigned int PostProcessMinCharacters { + unsigned int get() + { + return this->m_config->postProcessMinCharacters; + } + void set(unsigned int value) + { + this->m_config->postProcessMinCharacters = value; + } + } + + property unsigned int PostProcessMaxCharacters { + unsigned int get() + { + return this->m_config->postProcessMaxCharacters; + } + void set(unsigned int value) + { + this->m_config->postProcessMaxCharacters = value; + } + } + + property bool DebugGeneral { + bool get() + { + return this->m_config->debugGeneral; + } + void set(bool value) + { + this->m_config->debugGeneral = value; + } + } + + property bool DebugTiming { + bool get() + { + return this->m_config->debugTiming; + } + void set(bool value) + { + this->m_config->debugTiming = value; + } + } + + property bool DebugPrewarp { + bool get() + { + return this->m_config->debugPrewarp; + } + void set(bool value) + { + this->m_config->debugPrewarp = value; + } + } + + property bool DebugDetector { + bool get() + { + return this->m_config->debugDetector; + } + void set(bool value) + { + this->m_config->debugDetector = value; + } + } + + property bool DebugStateId { + bool get() + { + return this->m_config->debugStateId; + } + void set(bool value) + { + this->m_config->debugStateId = value; + } + } + + property bool DebugPlateLines { + bool get() + { + return this->m_config->debugPlateLines; + } + void set(bool value) + { + this->m_config->debugPlateLines = value; + } + } + + property bool DebugPlateCorners { + bool get() + { + return this->m_config->debugPlateCorners; + } + void set(bool value) + { + this->m_config->debugPlateCorners = value; + } + } + + property bool DebugCharSegmenter { + bool get() + { + return this->m_config->debugCharSegmenter; + } + void set(bool value) + { + this->m_config->debugCharSegmenter = value; + } + } + + property bool DebugCharAnalysis { + bool get() + { + return this->m_config->debugCharAnalysis; + } + void set(bool value) + { + this->m_config->debugCharAnalysis = value; + } + } + + property bool DebugColorFiler { + bool get() + { + return this->m_config->debugColorFiler; + } + void set(bool value) + { + this->m_config->debugColorFiler = value; + } + } + + property bool DebugOcr { + bool get() + { + return this->m_config->debugOcr; + } + void set(bool value) + { + this->m_config->debugOcr = value; + } + } + + property bool DebugPostProcess { + bool get() + { + return this->m_config->debugPostProcess; + } + void set(bool value) + { + this->m_config->debugPostProcess = value; + } + } + + property bool DebugShowImages { + bool get() + { + return this->m_config->debugShowImages; + } + void set(bool value) + { + this->m_config->debugShowImages = value; + } + } + + property bool DebugPauseOnFrame { + bool get() + { + return this->m_config->debugPauseOnFrame; + } + void set(bool value) + { + this->m_config->debugPauseOnFrame = value; + } + } + + void SetDebug(bool value) + { + this->m_config->setDebug(value); + } + + String^ GetKeypointsRuntimeDir() + { + return AlprHelper::ToManagedString(this->m_config->getKeypointsRuntimeDir()); + } + + String^ GetCascadeRuntimeDir() + { + return AlprHelper::ToManagedString(this->m_config->getCascadeRuntimeDir()); + } + + String^ GetPostProcessRuntimeDir() + { + return AlprHelper::ToManagedString(this->m_config->getPostProcessRuntimeDir()); + } + + String^ GetTessdataPrefix() + { + return AlprHelper::ToManagedString(this->m_config->getTessdataPrefix()); + } + + ~AlprConfigNet() + { + // void + } + + private: + Config *m_config; + }; +} \ No newline at end of file diff --git a/src/bindings/csharp/openalpr-net/helper-net.h b/src/bindings/csharp/openalpr-net/helper-net.h new file mode 100644 index 0000000..c0dd801 --- /dev/null +++ b/src/bindings/csharp/openalpr-net/helper-net.h @@ -0,0 +1,162 @@ +#pragma once + +#using +#include + +#include +#include +#include + +#include "alpr.h" +#include "opencv2/imgproc/imgproc.hpp" + +#include + +using namespace std; +using namespace alpr; + +using namespace msclr::interop; + +using namespace System; +using namespace System::Runtime::InteropServices; +using namespace System::Drawing; +using namespace System::Drawing::Imaging; +using namespace System::IO; +using namespace System::Collections::Generic; + +namespace openalprnet +{ + private ref class AlprHelper sealed + { + public: + + static std::vector ToVector(array^ src) + { + std::vector result(src->Length); + pin_ptr pin(&src[0]); + char *first(pin), *last(pin + src->Length); + std::copy(first, last, result.begin()); + return result; + } + + static std::vector ToVector(array^ src) + { + std::vector result(src->Length); + pin_ptr pin(&src[0]); + char* pch = reinterpret_cast(pin); + char *first(pch), *last(pch + src->Length); + std::copy(first, last, result.begin()); + return result; + } + + static Bitmap^ MatToBitmap(cv::Mat mat) + { + const int width = mat.size().width; + const int height = mat.size().height; + const int channels = mat.channels(); + const int totalSize = mat.total(); + void* data = reinterpret_cast(mat.data); + Bitmap ^bitmap; + + if (channels == 1) + { + bitmap = gcnew Bitmap(width, height, PixelFormat::Format8bppIndexed); + + ColorPalette ^palette = bitmap->Palette; + for (int i = 0; i < 256; i++) + { + palette->Entries[i] = Color::FromArgb(i, i, i); + } + + bitmap->Palette = palette; + } + else + { + bitmap = gcnew Bitmap(width, height, PixelFormat::Format24bppRgb); + } + + System::Drawing::Imaging::BitmapData ^bitmapData = bitmap->LockBits( + System::Drawing::Rectangle(0, 0, bitmap->Width, bitmap->Height), + System::Drawing::Imaging::ImageLockMode::ReadWrite, + bitmap->PixelFormat + ); + + char *src = reinterpret_cast(bitmapData->Scan0.ToPointer()); + pin_ptr pin(&src[0]); + + ::memcpy(pin, data, totalSize); + + bitmap->UnlockBits(bitmapData); + + return bitmap; + } + + static MemoryStream^ BitmapToMemoryStream(Bitmap^ bitmap, ImageFormat^ imageFormat) + { + MemoryStream^ ms = gcnew System::IO::MemoryStream(); + bitmap->Save(ms, imageFormat); + return ms; + } + + static std::vector MemoryStreamToVector(MemoryStream^ ms) + { + unsigned char* byteArray = ToCharPtr(ms->ToArray()); + std::vector result(byteArray, byteArray + ms->Length); + return result; + } + + static std::vector ToVector(List^ src) + { + std::vector result; + + for each(System::Drawing::Rectangle^ rect in src) + { + AlprRegionOfInterest roi(rect->X, rect->Y, rect->Width, rect->Height); + result.push_back(roi); + } + + return result; + } + + static unsigned char* ToCharPtr(array^ src) + { + //unsigned char* result = (unsigned char*) new unsigned char[src->Length]; + pin_ptr pin(&src[0]); + unsigned char* pc = pin; + return pc; + } + + static System::String^ ToManagedString(std::string s) + { + return gcnew String(s.c_str()); + } + + static std::string ToStlString(System::String^ s) + { + IntPtr ptr = Marshal::StringToHGlobalAnsi(s); + if (ptr != IntPtr::Zero) + { + std::string tmp(reinterpret_cast(static_cast(ptr))); + Marshal::FreeHGlobal(ptr); + return tmp; + } + return std::string(); + } + + static System::Drawing::Rectangle ToRectangle(cv::Rect rect) + { + return System::Drawing::Rectangle(rect.x, rect.y, rect.width, rect.height); + } + + static List^ ToRectangleList(std::vector srcRects) + { + List^ rects = gcnew List(); + for each(cv::Rect rect in srcRects) + { + rects->Add(ToRectangle(rect)); + } + return rects; + } + + }; +}; \ No newline at end of file diff --git a/src/bindings/csharp/openalpr-net/lock-net.h b/src/bindings/csharp/openalpr-net/lock-net.h new file mode 100644 index 0000000..56f05a3 --- /dev/null +++ b/src/bindings/csharp/openalpr-net/lock-net.h @@ -0,0 +1,18 @@ +#pragma once + +using namespace System::Threading; + +namespace openalprnet +{ + private ref class Lock { + Object^ m_pObject; + public: + Lock(Object ^ pObject) : m_pObject(pObject) { + Monitor::Enter(m_pObject); + } + ~Lock() { + Monitor::Exit(m_pObject); + } + }; +} + diff --git a/src/bindings/csharp/openalpr-net/motiondetector-net.cpp b/src/bindings/csharp/openalpr-net/motiondetector-net.cpp new file mode 100644 index 0000000..63721e9 --- /dev/null +++ b/src/bindings/csharp/openalpr-net/motiondetector-net.cpp @@ -0,0 +1,79 @@ +#include "stdafx.h" +#include "motiondetector-net.h" +#include "lock-net.h" +#include "bitmapmat-net.h" + +using namespace openalprnet; + +void AlprMotionDetectionNet::ResetMotionDetection(Bitmap^ bitmap) +{ + BitmapMat^ wrapper = gcnew BitmapMat(bitmap); + ResetMotionDetection(wrapper->Value); + delete wrapper; +} + +void AlprMotionDetectionNet::ResetMotionDetection(String^ filename) +{ + BitmapMat^ wrapper = gcnew BitmapMat(filename); + ResetMotionDetection(wrapper->Value); + delete wrapper; +} + +void AlprMotionDetectionNet::ResetMotionDetection(MemoryStream^ memoryStream) +{ + BitmapMat^ wrapper = gcnew BitmapMat(memoryStream); + ResetMotionDetection(wrapper->Value); + delete wrapper; +} + +void AlprMotionDetectionNet::ResetMotionDetection(array^ byteArray) +{ + BitmapMat^ wrapper = gcnew BitmapMat(byteArray); + ResetMotionDetection(wrapper->Value); + delete wrapper; +} + +System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(Bitmap^ bitmap) +{ + BitmapMat^ wrapper = gcnew BitmapMat(bitmap); + System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); + delete wrapper; + return motion; +} + +System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(String^ filename) +{ + BitmapMat^ wrapper = gcnew BitmapMat(filename); + System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); + delete wrapper; + return motion; +} + +System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(MemoryStream^ memoryStream) +{ + BitmapMat^ wrapper = gcnew BitmapMat(memoryStream); + System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); + delete wrapper; + return motion; +} + +System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(array^ byteArray) +{ + BitmapMat^ wrapper = gcnew BitmapMat(byteArray); + System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); + delete wrapper; + return motion; +} + +void AlprMotionDetectionNet::ResetMotionDetection(cv::Mat mat) +{ + Lock lock(this); + this->m_motionDetector->ResetMotionDetection(&mat); +} + +System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(cv::Mat mat) +{ + Lock lock(this); + cv::Rect rect = this->m_motionDetector->MotionDetect(&mat); + return AlprHelper::ToRectangle(rect); +} \ No newline at end of file diff --git a/src/bindings/csharp/openalpr-net/motiondetector-net.h b/src/bindings/csharp/openalpr-net/motiondetector-net.h new file mode 100644 index 0000000..86c0909 --- /dev/null +++ b/src/bindings/csharp/openalpr-net/motiondetector-net.h @@ -0,0 +1,52 @@ +#pragma once + +#include "motiondetector.h" // alpr +#include "helper-net.h" + +using namespace alpr; + +namespace openalprnet +{ + public ref class AlprMotionDetectionNet : IDisposable { + public: + AlprMotionDetectionNet() : m_motionDetector(new MotionDetector()) + { + + } + + void AlprMotionDetectionNet::ResetMotionDetection(Bitmap^ bitmap); + void AlprMotionDetectionNet::ResetMotionDetection(String^ filename); + void AlprMotionDetectionNet::ResetMotionDetection(MemoryStream^ memoryStream); + void AlprMotionDetectionNet::ResetMotionDetection(array^ byteArray); + System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(Bitmap^ bitmap); + System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(String^ filename); + System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(MemoryStream^ memoryStream); + System::Drawing::Rectangle AlprMotionDetectionNet::MotionDetect(array^ byteArray); + + private: + + ~AlprMotionDetectionNet() + { + if (this->m_disposed) + { + return; + } + + this->!AlprMotionDetectionNet(); + this->m_disposed = true; + } + + !AlprMotionDetectionNet() + { + delete m_motionDetector; + } + + private: + void ResetMotionDetection(cv::Mat mat); + System::Drawing::Rectangle MotionDetect(cv::Mat mat); + + private: + MotionDetector* m_motionDetector; + bool m_disposed; + }; +} \ No newline at end of file diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.cpp b/src/bindings/csharp/openalpr-net/openalpr-net.cpp index 42ad9b2..4988653 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.cpp +++ b/src/bindings/csharp/openalpr-net/openalpr-net.cpp @@ -18,1049 +18,16 @@ #include "stdafx.h" #include "openalpr-net.h" -#include "alpr.h" -#include "config.h" // alpr -#include "motiondetector.h" // alpr -#include -#include -#include -#using -//#include -#include - -#include "opencv2/highgui/highgui.hpp" -#include "opencv2/imgproc/imgproc.hpp" using namespace System; -using namespace msclr::interop; -using namespace System::Collections::Generic; -using namespace System::Runtime::InteropServices; -using namespace System::Drawing; -using namespace System::Drawing::Imaging; -using namespace System::IO; using namespace alpr; -using namespace System::Threading; namespace openalprnet { - private ref class Lock { - Object^ m_pObject; - public: - Lock(Object ^ pObject) : m_pObject(pObject) { - Monitor::Enter(m_pObject); - } - ~Lock() { - Monitor::Exit(m_pObject); - } - }; - - private ref class BitmapMat : IDisposable - { - private: - cv::Mat* m_bitmap; - bool m_disposed; - public: - - BitmapMat(array^ byteArray) - { - this->m_bitmap = ByteArrayToMat(byteArray); - } - - BitmapMat(Bitmap^ bitmap) - { - this->m_bitmap = BitmapToMat(bitmap); - } - - BitmapMat(MemoryStream^ memoryStream) - { - this->m_bitmap = MemoryStreamBitmapToMat(memoryStream); - } - - BitmapMat(String^ filename) - { - Bitmap^ bitmap = gcnew Bitmap(filename); - this->m_bitmap = BitmapToMat(bitmap); - delete bitmap; - } - - property cv::Mat Value { - cv::Mat get() - { - cv::Mat value = this->m_bitmap->clone(); - return value; - } - } - - ~BitmapMat() - { - if (this->m_disposed) - { - return; - } - - this->!BitmapMat(); - this->m_disposed = true; - } - - !BitmapMat() - { - delete[] m_bitmap->data; - } - - private: - - static cv::Mat* BitmapToMat(Bitmap^ bitmap) - { - int channels = 0; - - switch(bitmap->PixelFormat) - { - case PixelFormat::Format8bppIndexed: - case PixelFormat::Format1bppIndexed: - channels = 1; - break; - case PixelFormat::Format24bppRgb: - channels = 3; - break; - case PixelFormat::Format32bppRgb: - case PixelFormat::Format32bppArgb: - case PixelFormat::Format32bppPArgb: - channels = 4; - break; - default: - throw gcnew NotImplementedException(); - } - - BitmapData^ bitmapData = bitmap->LockBits( - System::Drawing::Rectangle(0, 0, bitmap->Width, bitmap->Height), - ImageLockMode::ReadOnly, - bitmap->PixelFormat - ); - - const int totalBytes = bitmap->Height * bitmapData->Stride; - - char *dst = new char[totalBytes]; - ::memcpy(dst, bitmapData->Scan0.ToPointer(), totalBytes); - - cv::Mat* dstMat = new cv::Mat(cv::Size(bitmap->Width, bitmap->Height), CV_8UC(channels), dst); - - bitmap->UnlockBits(bitmapData); - - return dstMat; - } - - static cv::Mat* MemoryStreamBitmapToMat(MemoryStream^ memoryStream) - { - Bitmap^ bitmap = gcnew Bitmap(memoryStream); - cv::Mat* mat = BitmapToMat(bitmap); - delete bitmap; - return mat; - } - - static cv::Mat* ByteArrayToMat(array^ byteArray) - { - MemoryStream^ ms = gcnew MemoryStream(byteArray); - cv::Mat* mat = MemoryStreamBitmapToMat(ms); - delete ms; - return mat; - } - - }; - - private ref class AlprHelper sealed - { - public: - - static std::vector ToVector(array^ src) - { - std::vector result(src->Length); - pin_ptr pin(&src[0]); - char *first(pin), *last(pin + src->Length); - std::copy(first, last, result.begin()); - return result; - } - - static std::vector ToVector(array^ src) - { - std::vector result(src->Length); - pin_ptr pin(&src[0]); - char* pch = reinterpret_cast(pin); - char *first(pch), *last(pch + src->Length); - std::copy(first, last, result.begin()); - return result; - } - - static Bitmap^ MatToBitmap(cv::Mat mat) - { - const int width = mat.size().width; - const int height = mat.size().height; - const int channels = mat.channels(); - const int totalSize = mat.total(); - void* data = reinterpret_cast(mat.data); - Bitmap ^bitmap; - - if (channels == 1) - { - bitmap = gcnew Bitmap(width, height, PixelFormat::Format8bppIndexed); - - ColorPalette ^palette = bitmap->Palette; - for (int i = 0; i < 256; i++) - { - palette->Entries[i] = Color::FromArgb(i, i, i); - } - - bitmap->Palette = palette; - } - else - { - bitmap = gcnew Bitmap(width, height, PixelFormat::Format24bppRgb); - } - - System::Drawing::Imaging::BitmapData ^bitmapData = bitmap->LockBits( - System::Drawing::Rectangle(0, 0, bitmap->Width, bitmap->Height), - System::Drawing::Imaging::ImageLockMode::ReadWrite, - bitmap->PixelFormat - ); - - char *src = reinterpret_cast(bitmapData->Scan0.ToPointer()); - pin_ptr pin(&src[0]); - - ::memcpy(pin, data, totalSize); - - bitmap->UnlockBits(bitmapData); - - return bitmap; - } - - static MemoryStream^ BitmapToMemoryStream(Bitmap^ bitmap, ImageFormat^ imageFormat) - { - MemoryStream^ ms = gcnew System::IO::MemoryStream(); - bitmap->Save(ms, imageFormat); - return ms; - } - - static std::vector MemoryStreamToVector(MemoryStream^ ms) - { - unsigned char* byteArray = ToCharPtr(ms->ToArray()); - std::vector result(byteArray, byteArray + ms->Length); - return result; - } - - static std::vector ToVector(List^ src) - { - std::vector result; - - for each(System::Drawing::Rectangle^ rect in src) - { - AlprRegionOfInterest roi(rect->X, rect->Y, rect->Width, rect->Height); - result.push_back(roi); - } - - return result; - } - - static unsigned char* ToCharPtr(array^ src) - { - //unsigned char* result = (unsigned char*) new unsigned char[src->Length]; - pin_ptr pin(&src[0]); - unsigned char* pc = pin; - return pc; - } - - static System::String^ ToManagedString(std::string s) - { - return gcnew String(s.c_str()); - } - - static std::string ToStlString(System::String^ s) - { - IntPtr ptr = Marshal::StringToHGlobalAnsi(s); - if(ptr != IntPtr::Zero) - { - std::string tmp(reinterpret_cast(static_cast(ptr))); - Marshal::FreeHGlobal(ptr); - return tmp; - } - return std::string(); - } - - static System::Drawing::Rectangle ToRectangle(cv::Rect rect) - { - return System::Drawing::Rectangle(rect.x, rect.y, rect.width, rect.height); - } - - static List^ ToRectangleList(std::vector srcRects) - { - List^ rects = gcnew List(); - for each(cv::Rect rect in srcRects) - { - rects->Add(ToRectangle(rect)); - } - return rects; - } - - }; - - public ref class AlprMotionDetectionNet : IDisposable { - public: - AlprMotionDetectionNet() - { - m_motionDetector = new MotionDetector(); - } - - void ResetMotionDetection(Bitmap^ bitmap) - { - BitmapMat^ wrapper = gcnew BitmapMat(bitmap); - ResetMotionDetection(wrapper->Value); - delete wrapper; - } - - void ResetMotionDetection(String^ filename) - { - BitmapMat^ wrapper = gcnew BitmapMat(filename); - ResetMotionDetection(wrapper->Value); - delete wrapper; - } - - void ResetMotionDetection(MemoryStream^ memoryStream) - { - BitmapMat^ wrapper = gcnew BitmapMat(memoryStream); - ResetMotionDetection(wrapper->Value); - delete wrapper; - } - - void ResetMotionDetection(array^ byteArray) - { - BitmapMat^ wrapper = gcnew BitmapMat(byteArray); - ResetMotionDetection(wrapper->Value); - delete wrapper; - } - - System::Drawing::Rectangle MotionDetect(Bitmap^ bitmap) - { - BitmapMat^ wrapper = gcnew BitmapMat(bitmap); - System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); - delete wrapper; - return motion; - } - - System::Drawing::Rectangle MotionDetect(String^ filename) - { - BitmapMat^ wrapper = gcnew BitmapMat(filename); - System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); - delete wrapper; - return motion; - } - - System::Drawing::Rectangle MotionDetect(MemoryStream^ memoryStream) - { - BitmapMat^ wrapper = gcnew BitmapMat(memoryStream); - System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); - delete wrapper; - return motion; - } - - System::Drawing::Rectangle MotionDetect(array^ byteArray) - { - BitmapMat^ wrapper = gcnew BitmapMat(byteArray); - System::Drawing::Rectangle motion = MotionDetect(wrapper->Value); - delete wrapper; - return motion; - } - - private: - void ResetMotionDetection(cv::Mat mat) - { - Lock lock(this); - this->m_motionDetector->ResetMotionDetection(&mat); - } - - System::Drawing::Rectangle MotionDetect(cv::Mat mat) - { - Lock lock(this); - cv::Rect rect = this->m_motionDetector->MotionDetect(&mat); - return AlprHelper::ToRectangle(rect); - } - - private: - - ~AlprMotionDetectionNet() - { - if(this->m_disposed) - { - return; - } - - this->!AlprMotionDetectionNet(); - this->m_disposed = true; - } - - !AlprMotionDetectionNet() - { - delete m_motionDetector; - } - - private: - MotionDetector* m_motionDetector; - bool m_disposed; - }; - - - public enum class AlprDetectorTypeNet : int { - DetectorLbpCpu = alpr::DETECTOR_LBP_CPU, - DetectorLbpGpu = alpr::DETECTOR_LBP_GPU, - DetectorLbpMorphCpu = alpr::DETECTOR_MORPH_CPU - }; - - public ref class AlprConfigNet sealed - { - internal: - AlprConfigNet(Config* config) : m_config(config) - { - - } - - public: - - property bool IsLoaded { - bool get() - { - return this->m_config->loaded; - } - } - - property AlprDetectorTypeNet Detector { - AlprDetectorTypeNet get() { - return static_cast(this->m_config->detector); - } - void set(AlprDetectorTypeNet value) - { - this->m_config->detector = static_cast(value); - } - } - - property float DetectionIterationIncrease { - float get() - { - return this->m_config->detection_iteration_increase; - } - void set(float value) - { - this->m_config->detection_iteration_increase = value; - } - } - - property int DetectionStrictness { - int get() - { - return this->m_config->detectionStrictness; - } - void set(int value) - { - this->m_config->detectionStrictness = value; - } - } - - property float MaxPlateWidthPercent { - float get() - { - return this->m_config->maxPlateWidthPercent; - } - void set(float value) - { - this->m_config->maxPlateWidthPercent = value; - } - } - - property float MaxPlateHeightPercent { - float get() - { - return this->m_config->maxPlateHeightPercent; - } - void set(float value) - { - this->m_config->maxPlateHeightPercent = value; - } - } - - property int MaxDetectionInputWidth { - int get() - { - return this->m_config->maxDetectionInputWidth; - } - void set(int value) - { - this->m_config->maxDetectionInputWidth = value; - } - } - - property int MaxDetectionInputHeight { - int get() - { - return this->m_config->maxDetectionInputHeight; - } - void set(int value) - { - this->m_config->maxDetectionInputHeight = value; - } - } - - property bool SkipDetection { - bool get() - { - return this->m_config->skipDetection; - } - void set(bool value) - { - this->m_config->skipDetection = true; - } - } - - property String^ PreWarp { - String^ get() - { - return AlprHelper::ToManagedString(this->m_config->prewarp); - } - void set(String^ value) - { - this->m_config->prewarp = marshal_as(value); - } - } - - property int MaxPlateAngleDegrees { - int get() - { - return this->m_config->maxPlateAngleDegrees; - } - void set(int value) - { - this->m_config->maxPlateAngleDegrees = value; - } - } - - property float MinPlateSizeWidthPx { - float get() - { - return this->m_config->minPlateSizeWidthPx; - } - void set(float value) - { - this->m_config->minPlateSizeWidthPx = value; - } - } - - property float MinPlateSizeHeightPx { - float get() - { - return this->m_config->minPlateSizeHeightPx; - } - void set(float value) - { - this->m_config->minPlateSizeHeightPx = value; - } - } - - property bool Multiline { - bool get() - { - return this->m_config->multiline; - } - void set(bool value) - { - this->m_config->multiline = value; - } - } - - property float PlateWidthMM { - float get() - { - return this->m_config->plateWidthMM; - } - void set(float value) - { - this->m_config->plateWidthMM = value; - } - } - - property float PlateHeightMM { - float get() - { - return this->m_config->plateHeightMM; - } - void set(float value) - { - this->m_config->plateHeightMM = value; - } - } - - property float CharHeightMM { - float get() - { - return this->m_config->charHeightMM; - } - void set(float value) - { - this->m_config->charHeightMM = value; - } - } - - property float CharWidthMM { - float get() - { - return this->m_config->charWidthMM; - } - void set(float value) - { - this->m_config->charWidthMM = value; - } - } - - property float CharWhitespaceTopMM { - float get() - { - return this->m_config->charWhitespaceTopMM; - } - void set(float value) - { - this->m_config->charWhitespaceTopMM = value; - } - } - - property float CharWhitespaceBotMM { - float get() - { - return this->m_config->charWhitespaceBotMM; - } - void set(float value) - { - this->m_config->charWhitespaceBotMM = value; - } - } - - property int TemplateWidthPx { - int get() - { - return this->m_config->templateWidthPx; - } - void set(int value) - { - this->m_config->templateWidthPx = value; - } - } - - property int TemplateHeightPx { - int get() - { - return this->m_config->templateHeightPx; - } - void set(int value) - { - this->m_config->templateHeightPx = value; - } - } - - property int OcrImageWidthPx { - int get() - { - return this->m_config->ocrImageWidthPx; - } - void set(int value) - { - this->m_config->ocrImageWidthPx = value; - } - } - - property int OcrImageHeightPx { - int get() - { - return this->m_config->ocrImageHeightPx; - } - void set(int value) - { - this->m_config->ocrImageHeightPx = value; - } - } - - property int StateIdImageWidthPx { - int get() - { - return this->m_config->stateIdImageWidthPx; - } - void set(int value) - { - this->m_config->stateIdImageWidthPx = value; - } - } - - property int StateIdimageHeightPx { - int get() - { - return this->m_config->stateIdimageHeightPx; - } - void set(int value) - { - this->m_config->stateIdimageHeightPx = value; - } - } - - property float CharAnalysisMinPercent { - float get() - { - return this->m_config->charAnalysisMinPercent; - } - void set(float value) - { - this->m_config->charAnalysisMinPercent = value; - } - } - - property float CharAnalysisHeightRange { - float get() - { - return this->m_config->charAnalysisHeightRange; - } - void set(float value) - { - this->m_config->charAnalysisHeightRange = value; - } - } - - property float CharAnalysisHeightStepSize { - float get() - { - return this->m_config->charAnalysisHeightStepSize; - } - void set(float value) - { - this->m_config->charAnalysisHeightStepSize = value; - } - } - - property int CharAnalysisNumSteps { - int get() - { - return this->m_config->charAnalysisNumSteps; - } - void set(int value) - { - this->m_config->charAnalysisNumSteps = value; - } - } - - property float PlateLinesSensitivityVertical { - float get() - { - return this->m_config->plateLinesSensitivityVertical; - } - void set(float value) - { - this->m_config->plateLinesSensitivityVertical = value; - } - } - - property float PlateLinesSensitivityHorizontal { - float get() - { - return this->m_config->plateLinesSensitivityHorizontal; - } - void set(float value) - { - this->m_config->plateLinesSensitivityHorizontal = value; - } - } - - property int SegmentationMinBoxWidthPx { - int get() - { - return this->m_config->segmentationMinBoxWidthPx; - } - void set(int value) - { - this->m_config->segmentationMinBoxWidthPx = value; - } - } - - property float SegmentationMinCharHeightPercent { - float get() - { - return this->m_config->segmentationMinCharHeightPercent; - } - void set(float value) - { - this->m_config->segmentationMinCharHeightPercent = value; - } - } - - property float SegmentationMaxCharWidthvsAverage { - float get() - { - return this->m_config->segmentationMaxCharWidthvsAverage; - } - void set(float value) - { - this->m_config->segmentationMaxCharWidthvsAverage = value; - } - } - - property String^ OcrLanguage { - String^ get() - { - return AlprHelper::ToManagedString(this->m_config->ocrLanguage); - } - void set(String^ value) - { - this->m_config->ocrLanguage = marshal_as(value); - } - } - - property int OcrMinFontSize { - int get() - { - return this->m_config->ocrMinFontSize; - } - void set(int value) - { - this->m_config->ocrMinFontSize = value; - } - } - - property float PostProcessMinConfidence { - float get() - { - return this->m_config->postProcessMinConfidence; - } - void set(float value) - { - this->m_config->postProcessMinConfidence = value; - } - } - - property float PostProcessConfidenceSkipLevel { - float get() - { - return this->m_config->postProcessConfidenceSkipLevel; - } - void set(float value) - { - this->m_config->postProcessConfidenceSkipLevel = value; - } - } - - property unsigned int PostProcessMinCharacters { - unsigned int get() - { - return this->m_config->postProcessMinCharacters; - } - void set(unsigned int value) - { - this->m_config->postProcessMinCharacters = value; - } - } - - property unsigned int PostProcessMaxCharacters { - unsigned int get() - { - return this->m_config->postProcessMaxCharacters; - } - void set(unsigned int value) - { - this->m_config->postProcessMaxCharacters = value; - } - } - - property bool DebugGeneral { - bool get() - { - return this->m_config->debugGeneral; - } - void set(bool value) - { - this->m_config->debugGeneral = value; - } - } - - property bool DebugTiming { - bool get() - { - return this->m_config->debugTiming; - } - void set(bool value) - { - this->m_config->debugTiming = value; - } - } - - property bool DebugPrewarp { - bool get() - { - return this->m_config->debugPrewarp; - } - void set(bool value) - { - this->m_config->debugPrewarp = value; - } - } - - property bool DebugDetector { - bool get() - { - return this->m_config->debugDetector; - } - void set(bool value) - { - this->m_config->debugDetector = value; - } - } - - property bool DebugStateId { - bool get() - { - return this->m_config->debugStateId; - } - void set(bool value) - { - this->m_config->debugStateId = value; - } - } - - property bool DebugPlateLines { - bool get() - { - return this->m_config->debugPlateLines; - } - void set(bool value) - { - this->m_config->debugPlateLines = value; - } - } - - property bool DebugPlateCorners { - bool get() - { - return this->m_config->debugPlateCorners; - } - void set(bool value) - { - this->m_config->debugPlateCorners = value; - } - } - - property bool DebugCharSegmenter { - bool get() - { - return this->m_config->debugCharSegmenter; - } - void set(bool value) - { - this->m_config->debugCharSegmenter = value; - } - } - - property bool DebugCharAnalysis { - bool get() - { - return this->m_config->debugCharAnalysis; - } - void set(bool value) - { - this->m_config->debugCharAnalysis = value; - } - } - - property bool DebugColorFiler { - bool get() - { - return this->m_config->debugColorFiler; - } - void set(bool value) - { - this->m_config->debugColorFiler = value; - } - } - - property bool DebugOcr { - bool get() - { - return this->m_config->debugOcr; - } - void set(bool value) - { - this->m_config->debugOcr = value; - } - } - - property bool DebugPostProcess { - bool get() - { - return this->m_config->debugPostProcess; - } - void set(bool value) - { - this->m_config->debugPostProcess = value; - } - } - - property bool DebugShowImages { - bool get() - { - return this->m_config->debugShowImages; - } - void set(bool value) - { - this->m_config->debugShowImages = value; - } - } - - property bool DebugPauseOnFrame { - bool get() - { - return this->m_config->debugPauseOnFrame; - } - void set(bool value) - { - this->m_config->debugPauseOnFrame = value; - } - } - - void SetDebug(bool value) - { - this->m_config->setDebug(value); - } - - String^ GetKeypointsRuntimeDir() - { - return AlprHelper::ToManagedString(this->m_config->getKeypointsRuntimeDir()); - } - - String^ GetCascadeRuntimeDir() - { - return AlprHelper::ToManagedString(this->m_config->getCascadeRuntimeDir()); - } - - String^ GetPostProcessRuntimeDir() - { - return AlprHelper::ToManagedString(this->m_config->getPostProcessRuntimeDir()); - } - - String^ GetTessdataPrefix() - { - return AlprHelper::ToManagedString(this->m_config->getTessdataPrefix()); - } - - ~AlprConfigNet() - { - // void - } - - private: - Config *m_config; - }; - public ref class AlprPlateNet sealed { public: AlprPlateNet(AlprPlate plate){ - //_characters = marshal_as(plate.characters); m_characters = AlprHelper::ToManagedString(plate.characters); m_overall_confidence=plate.overall_confidence; m_matches_template=plate.matches_template; diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.h b/src/bindings/csharp/openalpr-net/openalpr-net.h index e56ad27..52ec33e 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.h +++ b/src/bindings/csharp/openalpr-net/openalpr-net.h @@ -1,8 +1,21 @@ -// openalpr-net.h - #pragma once -//using namespace System; +#include "alpr.h" + +#include +#include +#include + +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/imgproc/imgproc.hpp" + +#using +#include + +#include "helper-net.h" +#include "bitmapmat-net.h" +#include "motiondetector-net.h" +#include "config-net.h" namespace openalprnet { diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.vcxproj b/src/bindings/csharp/openalpr-net/openalpr-net.vcxproj index 690aacc..2fe36e2 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.vcxproj +++ b/src/bindings/csharp/openalpr-net/openalpr-net.vcxproj @@ -1,4 +1,4 @@ - + @@ -23,20 +23,22 @@ v4.0 ManagedCProj openalprnet - 2.1.0 - v120 - ..\..\..\..\windows - None - $(OpenALPRWindowsDir)\build\dist\$(OpenALPRVersion)\$(PlatformToolset)\$(Configuration)\$(Platform) - $(OpenALPRWindowsDir)\build\dist\$(OpenALPRVersion)\$(PlatformToolset)\$(Configuration)\$(Platform)_CUDA_Fermi - $(OpenALPRWindowsDir)\build\dist\$(OpenALPRVersion)\$(PlatformToolset)\$(Configuration)\$(Platform)_CUDA_Kepler - 248 - 303 - 170 - d - - -debug - + 2.1.0 + v120 + ..\..\..\..\windows + None + $(OpenALPRWindowsDir)\build\dist\$(OpenALPRVersion)\$(PlatformToolset)\$(Configuration)\$(Platform) + $(OpenALPRWindowsDir)\build\dist\$(OpenALPRVersion)\$(PlatformToolset)\$(Configuration)\$(Platform)_CUDA_Fermi + $(OpenALPRWindowsDir)\build\dist\$(OpenALPRVersion)\$(PlatformToolset)\$(Configuration)\$(Platform)_CUDA_Kepler + 248 + 303 + 170 + d + + + -debug + + @@ -150,12 +152,20 @@ + + + + + + + + Create diff --git a/src/bindings/csharp/openalpr-net/openalpr-net.vcxproj.filters b/src/bindings/csharp/openalpr-net/openalpr-net.vcxproj.filters index 221dbe4..22e7904 100644 --- a/src/bindings/csharp/openalpr-net/openalpr-net.vcxproj.filters +++ b/src/bindings/csharp/openalpr-net/openalpr-net.vcxproj.filters @@ -24,6 +24,24 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -35,6 +53,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/src/bindings/csharp/openalpr-net/types-net.h b/src/bindings/csharp/openalpr-net/types-net.h new file mode 100644 index 0000000..002d67c --- /dev/null +++ b/src/bindings/csharp/openalpr-net/types-net.h @@ -0,0 +1,18 @@ +#pragma once + +#include "alpr.h" // alpr +#include "config.h" // alpr + +using namespace alpr; + +namespace openalprnet +{ + namespace types + { + public enum class AlprDetectorTypeNet : int { + DetectorLbpCpu = alpr::DETECTOR_LBP_CPU, + DetectorLbpGpu = alpr::DETECTOR_LBP_GPU, + DetectorLbpMorphCpu = alpr::DETECTOR_MORPH_CPU + }; + } +} \ No newline at end of file From 32f7c400d6f56ffc370e16082aeca51b98c60c59 Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Fri, 10 Jul 2015 09:48:36 +0200 Subject: [PATCH 13/14] Remove debug code. --- src/bindings/csharp/openalprnet-windemo/Form1.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/bindings/csharp/openalprnet-windemo/Form1.cs b/src/bindings/csharp/openalprnet-windemo/Form1.cs index e60ab62..e2081c4 100644 --- a/src/bindings/csharp/openalprnet-windemo/Form1.cs +++ b/src/bindings/csharp/openalprnet-windemo/Form1.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2015 OpenALPR Technology, Inc. * * This file is part of OpenALPR. @@ -144,13 +144,6 @@ namespace openalprnet_windemo picOriginal.ImageLocation = fileName; picOriginal.Load(); - var motionDetection = new AlprMotionDetectionNet(); - var b = File.ReadAllBytes(fileName); - Parallel.For(0, int.MaxValue, (x) => - { - motionDetection.MotionDetect(b); - }); - var results = alpr.Recognize(fileName); var images = new List(results.Plates.Count()); From 5d9e1220bc2c63f36ed22c2e541cae76cd627ebe Mon Sep 17 00:00:00 2001 From: Peter Rekdal Sunde Date: Fri, 10 Jul 2015 13:29:45 +0200 Subject: [PATCH 14/14] Bugfix: If null or whitespace then set empty string (nullptr exception). --- src/bindings/csharp/openalpr-net/config-net.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/bindings/csharp/openalpr-net/config-net.h b/src/bindings/csharp/openalpr-net/config-net.h index e591b1a..b1c7331 100644 --- a/src/bindings/csharp/openalpr-net/config-net.h +++ b/src/bindings/csharp/openalpr-net/config-net.h @@ -121,6 +121,11 @@ namespace openalprnet } void set(String^ value) { + if(String::IsNullOrWhiteSpace(value)) + { + this->m_config->prewarp = ""; + return; + } this->m_config->prewarp = marshal_as(value); } } @@ -407,6 +412,11 @@ namespace openalprnet } void set(String^ value) { + if (String::IsNullOrWhiteSpace(value)) + { + this->m_config->prewarp = ""; + return; + } this->m_config->ocrLanguage = marshal_as(value); } }