/* * Copyright (c) 2015 OpenALPR Technology, Inc. * * This file is part of OpenALPR. * * OpenALPR 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" using namespace System; using namespace alpr; namespace openalprnet { public ref class AlprPlateNet sealed { public: AlprPlateNet(AlprPlate plate){ 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 OverallConfidence { float get() { return m_overall_confidence; } } property bool MatchesTemplate { 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 RequestedTopN { int get() { return m_requested_topn; } } property int RegionConfidence { int get() { return m_regionConfidence; } } property int PlateIndex { 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^ PlatePoints { List^ get() { return m_plate_points; } } property List^ TopNPlates { List^ get() { return m_topNPlates; } } property float ProcessingTimeMs { 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 EpochTime { long get() { return m_epoch_time; } } property int ImageWidth { int get() { return m_img_width; } } property int ImageHeight { int get() { return m_img_height; } } property float TotalProcessingTimeMs { 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 AlprFrameEventArgs : public EventArgs { public: AlprFrameEventArgs(int frameNumber, System::Drawing::Image^ frame, AlprResultsNet^ results) { m_frameNumber = frameNumber; m_frame = frame; m_results = results; m_cancel = false; } property int FrameNumber { int get() { return m_frameNumber; } } property System::Drawing::Image^ Frame { System::Drawing::Image^ get() { return m_frame; } } property AlprResultsNet^ Results { AlprResultsNet^ get() { return m_results; } } property bool Cancel { bool get() { return m_cancel; } void set( bool cancel ) { m_cancel = cancel; } } private: int m_frameNumber; System::Drawing::Image^ m_frame; AlprResultsNet^ m_results; bool m_cancel; }; public ref class AlprNet sealed : IDisposable { 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)) ) { this->m_config = gcnew AlprConfigNet(this->m_Impl->getConfig()); } ~AlprNet() { if(this->m_disposed) { return; } this->!AlprNet(); this->m_disposed = true; } property AlprConfigNet^ Configuration { AlprConfigNet^ get() { return this->m_config; } } 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)); } } event EventHandler^ FrameProcessed; void RecognizeFromVideo(System::String^ videoPath) { if (System::IO::File::Exists(videoPath)) { int framenum = 0; cv::VideoCapture cap = cv::VideoCapture(); cap.open(marshal_as(videoPath)); cv::Mat frame; while (cap.read(frame)) { std::vector regionsOfInterest; regionsOfInterest.push_back(AlprRegionOfInterest(0, 0, frame.cols, frame.rows)); AlprResults results = m_Impl->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, regionsOfInterest); int framecolsorig = frame.cols; if (framecolsorig % 4 != 0) copyMakeBorder(frame, frame, 0, 0, 0, 4 - (framecolsorig % 4), IPL_BORDER_REPLICATE); //Stride has to be multiple of 4 Image^ frameImage = gcnew Bitmap(framecolsorig, frame.rows, frame.step, Imaging::PixelFormat::Format24bppRgb, IntPtr(frame.data)); AlprFrameEventArgs^ alprFrameEventArgs = gcnew AlprFrameEventArgs(framenum, frameImage, gcnew AlprResultsNet(results)); FrameProcessed(this, alprFrameEventArgs); delete frameImage; if (alprFrameEventArgs->Cancel) { break; } framenum++; } } else { throw gcnew System::IO::FileNotFoundException("No video was not found at " + videoPath, videoPath); } } /// /// Recognize from an image on disk /// AlprResultsNet^ Recognize(System::String^ filepath) { return Recognize(filepath, gcnew List()); } /// /// 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 a bitmap /// AlprResultsNet^ Recognize(Bitmap^ bitmap) { return Recognize(bitmap, gcnew List()); } /// /// Recognize from a bitmap /// AlprResultsNet^ Recognize(Bitmap^ bitmap, List^ regionsOfInterest) { 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); } /// /// Recognize from MemoryStream representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// AlprResultsNet^ Recognize(MemoryStream^ memoryStream) { 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) { std::vector buffer = AlprHelper::MemoryStreamToVector(memoryStream); std::vector rois = AlprHelper::ToVector(regionsOfInterest); AlprResults results = m_Impl->recognize(buffer, 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) { 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 buffer = AlprHelper::ToVector(imageBuffer); std::vector rois = AlprHelper::ToVector(regionsOfInterest); AlprResults results = m_Impl->recognize(buffer, rois); return gcnew AlprResultsNet(results); } /// /// Recognize from raw pixel data /// 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? return gcnew AlprResultsNet(results); } /// /// Pre-warp from raw pixel data. /// array^ PreWarp(array^ imageBuffer) { std::vector buffer = AlprHelper::ToVector(imageBuffer); cv::Mat src = cv::imdecode(buffer, 1); alpr::PreWarp *preWarp = new alpr::PreWarp(m_Impl->getConfig()); cv::Mat warpedImage = preWarp->warpImage(src); std::vector warpedImageVector; cv::imencode(".jpg", warpedImage, warpedImageVector); const size_t warpedImageSize = warpedImageVector.size(); array^ warpedImageByteArray = gcnew array(warpedImageSize); pin_ptr pin(&warpedImageByteArray[0]); std::memcpy(pin, &warpedImageVector[0], warpedImageSize); delete preWarp; return warpedImageByteArray; } 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; delete m_config; } private: Alpr * m_Impl; AlprConfigNet^ m_config; int m_topN; bool m_detectRegion; System::String^ m_defaultRegion; bool m_disposed; }; }