/* * Copyright (c) 2014 New Designs Unlimited, LLC * * This file is part of OpenAlpr.Net. * * OpenAlpr.Net is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3 as published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #include "stdafx.h" #include "openalpr-net.h" #include "alpr.h" #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 alpr; 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(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(); } }; 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; } property System::String^ characters { System::String^ get() { return m_characters; } } property float overall_confidence { float get() { return m_overall_confidence; } } property bool matches_template { bool get() { return m_matches_template; } } private: System::String^ m_characters; float m_overall_confidence; bool m_matches_template; }; public ref class AlprPlateResultNet sealed { public: AlprPlateResultNet(AlprPlateResult result) { m_plate_index = result.plate_index; m_processing_time_ms = result.processing_time_ms; m_regionConfidence = result.regionConfidence; m_region = AlprHelper::ToManagedString(result.region); m_bestPlate = gcnew AlprPlateNet(result.bestPlate); m_plate_points = gcnew List(4); for (int i = 0; i < 4; i++) { m_plate_points->Add(System::Drawing::Point(result.plate_points[i].x, result.plate_points[i].y)); } int num = result.topNPlates.size(); m_topNPlates = gcnew List(num); for (int i = 0; i < num; i++) { m_topNPlates->Add(gcnew AlprPlateNet(result.topNPlates[i])); } } property int requested_topn { int get() { return m_requested_topn; } } property int regionConfidence { int get() { return m_regionConfidence; } } property int plate_index { int get() { return m_plate_index; } } property System::String^ region { System::String^ get() { return m_region; } } property AlprPlateNet^ bestPlate { AlprPlateNet^ get() { return m_bestPlate; } } property List^ plate_points { List^ get() { return m_plate_points; } } property List^ topNPlates { List^ get() { return m_topNPlates; } } property float processing_time_ms { float get() { return m_processing_time_ms; } } private: int m_requested_topn; int m_regionConfidence; int m_plate_index; System::String^ m_region; float m_processing_time_ms; List^ m_topNPlates; List^ m_plate_points; AlprPlateNet^ m_bestPlate; }; public ref class AlprResultsNet sealed { public: AlprResultsNet(AlprResults results) { m_epoch_time = results.epoch_time; m_img_width = results.img_width; m_img_height = results.img_height; m_total_processing_time_ms = results.total_processing_time_ms; int num_rois = results.regionsOfInterest.size(); m_regionsOfInterest = gcnew List(num_rois); for (int i = 0; i < num_rois; i++) { m_regionsOfInterest->Add(System::Drawing::Rectangle( results.regionsOfInterest[i].x, results.regionsOfInterest[i].y, results.regionsOfInterest[i].width, results.regionsOfInterest[i].height)); } int num_plates = results.plates.size(); m_plates = gcnew List(num_plates); for (int i = 0; i < num_plates; i++) { m_plates->Add(gcnew AlprPlateResultNet(results.plates[i])); } std::string json = Alpr::toJson(results); m_json = AlprHelper::ToManagedString(json); } property long epoch_time { long get() { return m_epoch_time; } } property int img_width { int get() { return m_img_width; } } property int img_height { int get() { return m_img_height; } } property float total_processing_time_ms { float get() { return m_total_processing_time_ms; } } property List^ regionsOfInterest { List^ get() { return m_regionsOfInterest; } } property List^ plates { List^ get() { return m_plates; } } property System::String^ json { System::String^ get() { return m_json; } } private: long m_epoch_time; int m_img_width; int m_img_height; float m_total_processing_time_ms; List^ m_regionsOfInterest; List^ m_plates; System::String^ m_json; }; public ref class AlprNet sealed { public: // Allocate the native object on the C++ Heap via a constructor AlprNet(System::String^ country, System::String^ configFile, System::String^ runtimeDir) : m_Impl( new Alpr(marshal_as(country), marshal_as(configFile), marshal_as(runtimeDir)) ) { } // Deallocate the native object on a destructor ~AlprNet(){ delete m_Impl; } property int TopN { int get() { return m_topN; } void set( int topn ){ m_topN = topn; m_Impl->setTopN(topn); } } property bool DetectRegion { bool get() { return m_detectRegion; } void set( bool detectRegion ) { m_detectRegion = detectRegion; m_Impl->setDetectRegion(detectRegion); } } property System::String^ DefaultRegion { System::String^ get() { return m_defaultRegion; } void set( System::String^ region ){ m_defaultRegion = region; m_Impl->setDefaultRegion(marshal_as(region)); } } /// /// Recognize from an image on disk /// AlprResultsNet^ recognize(System::String^ filepath) { AlprResults results = m_Impl->recognize(marshal_as(filepath)); return gcnew AlprResultsNet(results); } /// /// Recognize from an image on disk /// 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 ); return gcnew AlprResultsNet(results); } /// /// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// /// Bytes representing image data AlprResultsNet^ recognize(cli::array^ imageBuffer) { std::vector p = AlprHelper::ToVector(imageBuffer); AlprResults results = m_Impl->recognize(p); return gcnew AlprResultsNet(results); } /// /// Recognize from raw pixel data /// 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); free(p); // ?? memory leak? return gcnew AlprResultsNet(results); } bool isLoaded() { return m_Impl->isLoaded(); } static System::String^ getVersion() { return AlprHelper::ToManagedString(Alpr::getVersion()); } protected: // Deallocate the native object on the finalizer just in case no destructor is called !AlprNet() { delete m_Impl; } private: Alpr * m_Impl; int m_topN; bool m_detectRegion; System::String^ m_defaultRegion; }; }