Merge branch 'master' of github.com:peters/openalpr

This commit is contained in:
Peter Rekdal Sunde
2015-07-09 22:29:42 +02:00
4 changed files with 161 additions and 70 deletions

View File

@@ -31,9 +31,9 @@ using namespace System::Security::Permissions;
// You can specify all the value or you can default the Revision and Build Numbers // You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersionAttribute("2.0.1")] [assembly: AssemblyVersionAttribute("2.1.0")]
[assembly: AssemblyFileVersionAttribute("2.0.1")] [assembly: AssemblyFileVersionAttribute("2.1.0")]
[assembly: AssemblyInformationalVersionAttribute("2.0.1")] [assembly: AssemblyInformationalVersionAttribute("2.1.0")]
[assembly:ComVisible(false)]; [assembly:ComVisible(false)];

View File

@@ -55,6 +55,16 @@ namespace openalprnet {
return result; return result;
} }
static std::vector<char> ToVector(array<Byte>^ src)
{
std::vector<char> result(src->Length);
pin_ptr<Byte> pin(&src[0]);
char* pch = reinterpret_cast<char*>(pin);
char *first(pch), *last(pch + src->Length);
std::copy(first, last, result.begin());
return result;
}
static cv::Mat BitmapToMat(Bitmap^ bitmap) static cv::Mat BitmapToMat(Bitmap^ bitmap)
{ {
int channels = 0; int channels = 0;
@@ -83,13 +93,31 @@ namespace openalprnet {
bitmap->PixelFormat bitmap->PixelFormat
); );
cv::Mat dstMat(cv::Size(bitmap->Width, bitmap->Height), CV_8UC(channels), reinterpret_cast<char*>(bitmapData->Scan0.ToPointer())); char *src = reinterpret_cast<char*>(bitmapData->Scan0.ToPointer());
pin_ptr<char> pin(&src[0]);
cv::Mat dstMat(cv::Size(bitmap->Width, bitmap->Height), CV_8UC(channels), pin);
bitmap->UnlockBits(bitmapData); bitmap->UnlockBits(bitmapData);
return dstMat; 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<Byte>^ byteArray)
{
MemoryStream^ ms = gcnew MemoryStream(byteArray);
cv::Mat mat(MemoryStreamBitmapToMat(ms));
delete ms;
return mat;
}
static Bitmap^ MatToBitmap(cv::Mat mat) static Bitmap^ MatToBitmap(cv::Mat mat)
{ {
const int width = mat.size().width; const int width = mat.size().width;
@@ -122,7 +150,10 @@ namespace openalprnet {
bitmap->PixelFormat bitmap->PixelFormat
); );
::memcpy(bitmapData->Scan0.ToPointer(), data, totalSize); char *src = reinterpret_cast<char*>(bitmapData->Scan0.ToPointer());
pin_ptr<char> pin(&src[0]);
::memcpy(pin, data, totalSize);
bitmap->UnlockBits(bitmapData); bitmap->UnlockBits(bitmapData);
@@ -213,6 +244,16 @@ namespace openalprnet {
return ResetMotionDetection(Mat(filename, matType)); return ResetMotionDetection(Mat(filename, matType));
} }
void ResetMotionDetection(MemoryStream^ memoryStream)
{
return ResetMotionDetection(Mat(memoryStream));
}
void ResetMotionDetection(array<Byte>^ byteArray)
{
return ResetMotionDetection(Mat(byteArray));
}
System::Drawing::Rectangle MotionDetect(Bitmap^ bitmap) System::Drawing::Rectangle MotionDetect(Bitmap^ bitmap)
{ {
return MotionDetect(Mat(bitmap)); return MotionDetect(Mat(bitmap));
@@ -223,6 +264,16 @@ namespace openalprnet {
return MotionDetect(Mat(filename, matType)); return MotionDetect(Mat(filename, matType));
} }
System::Drawing::Rectangle MotionDetect(MemoryStream^ memoryStream)
{
return MotionDetect(Mat(memoryStream));
}
System::Drawing::Rectangle MotionDetect(array<Byte>^ byteArray)
{
return MotionDetect(Mat(byteArray));
}
private: private:
void ResetMotionDetection(cv::Mat mat) void ResetMotionDetection(cv::Mat mat)
{ {
@@ -247,17 +298,29 @@ namespace openalprnet {
return mat; return mat;
} }
cv::Mat Mat(MemoryStream^ memoryStream)
{
cv::Mat mat = AlprHelper::MemoryStreamBitmapToMat(memoryStream);
return mat;
}
cv::Mat Mat(array<Byte>^ byteArray)
{
cv::Mat mat = AlprHelper::ByteArrayToMat(byteArray);
return mat;
}
private: private:
~AlprMotionDetectionNet() ~AlprMotionDetectionNet()
{ {
if(this->m_Disposed) if(this->m_disposed)
{ {
return; return;
} }
this->!AlprMotionDetectionNet(); this->!AlprMotionDetectionNet();
this->m_Disposed = true; this->m_disposed = true;
} }
!AlprMotionDetectionNet() !AlprMotionDetectionNet()
@@ -267,7 +330,7 @@ namespace openalprnet {
private: private:
MotionDetector* m_motionDetector; MotionDetector* m_motionDetector;
bool m_Disposed; bool m_disposed;
}; };
@@ -279,13 +342,14 @@ namespace openalprnet {
public ref class AlprConfigNet sealed public ref class AlprConfigNet sealed
{ {
public: internal:
AlprConfigNet(Config* config) : m_config(config)
AlprConfigNet(Config* config) : m_config (config)
{ {
} }
public:
property bool IsLoaded { property bool IsLoaded {
bool get() bool get()
{ {
@@ -413,7 +477,7 @@ namespace openalprnet {
} }
} }
property float minPlateSizeHeightPx { property float MinPlateSizeHeightPx {
float get() float get()
{ {
return this->m_config->minPlateSizeHeightPx; return this->m_config->minPlateSizeHeightPx;
@@ -930,19 +994,19 @@ namespace openalprnet {
m_matches_template=plate.matches_template; m_matches_template=plate.matches_template;
} }
property System::String^ characters { property System::String^ Characters {
System::String^ get() { System::String^ get() {
return m_characters; return m_characters;
} }
} }
property float overall_confidence { property float OverallConfidence {
float get() { float get() {
return m_overall_confidence; return m_overall_confidence;
} }
} }
property bool matches_template { property bool MatchesTemplate {
bool get() { bool get() {
return m_matches_template; return m_matches_template;
} }
@@ -978,49 +1042,49 @@ namespace openalprnet {
} }
} }
property int requested_topn { property int RequestedTopN {
int get() { int get() {
return m_requested_topn; return m_requested_topn;
} }
} }
property int regionConfidence { property int RegionConfidence {
int get() { int get() {
return m_regionConfidence; return m_regionConfidence;
} }
} }
property int plate_index { property int PlateIndex {
int get() { int get() {
return m_plate_index; return m_plate_index;
} }
} }
property System::String^ region { property System::String^ Region {
System::String^ get() { System::String^ get() {
return m_region; return m_region;
} }
} }
property AlprPlateNet^ bestPlate { property AlprPlateNet^ BestPlate {
AlprPlateNet^ get() { AlprPlateNet^ get() {
return m_bestPlate; return m_bestPlate;
} }
} }
property List<System::Drawing::Point>^ plate_points { property List<System::Drawing::Point>^ PlatePoints {
List<System::Drawing::Point>^ get() { List<System::Drawing::Point>^ get() {
return m_plate_points; return m_plate_points;
} }
} }
property List<AlprPlateNet^>^ topNPlates { property List<AlprPlateNet^>^ TopNPlates {
List<AlprPlateNet^>^ get() { List<AlprPlateNet^>^ get() {
return m_topNPlates; return m_topNPlates;
} }
} }
property float processing_time_ms { property float ProcessingTimeMs {
float get() { float get() {
return m_processing_time_ms; return m_processing_time_ms;
} }
@@ -1069,43 +1133,43 @@ namespace openalprnet {
m_json = AlprHelper::ToManagedString(json); m_json = AlprHelper::ToManagedString(json);
} }
property long epoch_time { property long EpochTime {
long get() { long get() {
return m_epoch_time; return m_epoch_time;
} }
} }
property int img_width { property int ImageWidth {
int get() { int get() {
return m_img_width; return m_img_width;
} }
} }
property int img_height { property int ImageHeight {
int get() { int get() {
return m_img_height; return m_img_height;
} }
} }
property float total_processing_time_ms { property float TotalProcessingTimeMs {
float get() { float get() {
return m_total_processing_time_ms; return m_total_processing_time_ms;
} }
} }
property List<System::Drawing::Rectangle>^ regionsOfInterest { property List<System::Drawing::Rectangle>^ RegionsOfInterest {
List<System::Drawing::Rectangle>^ get() { List<System::Drawing::Rectangle>^ get() {
return m_regionsOfInterest; return m_regionsOfInterest;
} }
} }
property List<AlprPlateResultNet^>^ plates { property List<AlprPlateResultNet^>^ Plates {
List<AlprPlateResultNet^>^ get() { List<AlprPlateResultNet^>^ get() {
return m_plates; return m_plates;
} }
} }
property System::String^ json { property System::String^ Json {
System::String^ get() { System::String^ get() {
return m_json; return m_json;
} }
@@ -1175,13 +1239,13 @@ namespace openalprnet {
} }
~AlprNet() { ~AlprNet() {
if(this->m_Disposed) if(this->m_disposed)
{ {
return; return;
} }
this->!AlprNet(); this->!AlprNet();
this->m_Disposed = true; this->m_disposed = true;
} }
property AlprConfigNet^ Configuration { property AlprConfigNet^ Configuration {
@@ -1257,7 +1321,7 @@ namespace openalprnet {
/// <summary> /// <summary>
/// Recognize from an image on disk /// Recognize from an image on disk
/// </summary> /// </summary>
AlprResultsNet^ recognize(System::String^ filepath) { AlprResultsNet^ Recognize(System::String^ filepath) {
AlprResults results = m_Impl->recognize(marshal_as<std::string>(filepath)); AlprResults results = m_Impl->recognize(marshal_as<std::string>(filepath));
return gcnew AlprResultsNet(results); return gcnew AlprResultsNet(results);
} }
@@ -1265,7 +1329,7 @@ namespace openalprnet {
/// <summary> /// <summary>
/// Recognize from an image on disk /// Recognize from an image on disk
/// </summary> /// </summary>
AlprResultsNet^ recognize(System::String^ filepath, List<System::Drawing::Rectangle>^ regionsOfInterest) { AlprResultsNet^ Recognize(System::String^ filepath, List<System::Drawing::Rectangle>^ regionsOfInterest) {
cv::Mat frame = cv::imread( marshal_as<std::string>(filepath) ); cv::Mat frame = cv::imread( marshal_as<std::string>(filepath) );
std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest); std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest);
AlprResults results = m_Impl->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, rois ); AlprResults results = m_Impl->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, rois );
@@ -1275,7 +1339,15 @@ namespace openalprnet {
/// <summary> /// <summary>
/// Recognize from a bitmap /// Recognize from a bitmap
/// </summary> /// </summary>
AlprResultsNet^ recognize(Bitmap^ bitmap, List<System::Drawing::Rectangle>^ regionsOfInterest) AlprResultsNet^ Recognize(Bitmap^ bitmap)
{
return Recognize(bitmap, gcnew List<System::Drawing::Rectangle>());
}
/// <summary>
/// Recognize from a bitmap
/// </summary>
AlprResultsNet^ Recognize(Bitmap^ bitmap, List<System::Drawing::Rectangle>^ regionsOfInterest)
{ {
cv::Mat frame = AlprHelper::BitmapToMat(bitmap); cv::Mat frame = AlprHelper::BitmapToMat(bitmap);
std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest); std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest);
@@ -1284,20 +1356,17 @@ namespace openalprnet {
} }
/// <summary> /// <summary>
/// Recognize from a bitmap /// Recognize from MemoryStream representing an encoded image (e.g., BMP, PNG, JPG, GIF etc).
/// </summary> /// </summary>
AlprResultsNet^ recognize(Bitmap^ bitmap) AlprResultsNet^ Recognize(MemoryStream^ memoryStream)
{ {
cv::Mat frame = AlprHelper::BitmapToMat(bitmap); return Recognize(memoryStream, gcnew List<System::Drawing::Rectangle>());
std::vector<AlprRegionOfInterest> rois;
AlprResults results = m_Impl->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, rois);
return gcnew AlprResultsNet(results);
} }
/// <summary> /// <summary>
/// Recognize from MemoryStream representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// Recognize from MemoryStream representing an encoded image (e.g., BMP, PNG, JPG, GIF etc).
/// </summary> /// </summary>
AlprResultsNet^ recognize(MemoryStream^ memoryStream) AlprResultsNet^ Recognize(MemoryStream^ memoryStream, List<System::Drawing::Rectangle>^ regionsOfInterest)
{ {
std::vector<char> p = AlprHelper::MemoryStreamToVector(memoryStream); std::vector<char> p = AlprHelper::MemoryStreamToVector(memoryStream);
AlprResults results = m_Impl->recognize(p); AlprResults results = m_Impl->recognize(p);
@@ -1308,7 +1377,15 @@ namespace openalprnet {
/// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc). /// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc).
/// </summary> /// </summary>
/// <param name="imageBuffer">Bytes representing image data</param> /// <param name="imageBuffer">Bytes representing image data</param>
AlprResultsNet^ recognize(cli::array<char>^ imageBuffer) { AlprResultsNet^ Recognize(cli::array<Byte>^ imageBuffer) {
return Recognize(imageBuffer, gcnew List<System::Drawing::Rectangle>());
}
/// <summary>
/// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc).
/// </summary>
/// <param name="imageBuffer">Bytes representing image data</param>
AlprResultsNet^ Recognize(cli::array<Byte>^ imageBuffer, List<System::Drawing::Rectangle>^ regionsOfInterest) {
std::vector<char> p = AlprHelper::ToVector(imageBuffer); std::vector<char> p = AlprHelper::ToVector(imageBuffer);
AlprResults results = m_Impl->recognize(p); AlprResults results = m_Impl->recognize(p);
return gcnew AlprResultsNet(results); return gcnew AlprResultsNet(results);
@@ -1317,19 +1394,26 @@ namespace openalprnet {
/// <summary> /// <summary>
/// Recognize from raw pixel data /// Recognize from raw pixel data
/// </summary> /// </summary>
AlprResultsNet^ recognize(cli::array<unsigned char>^ pixelData, int bytesPerPixel, int imgWidth, int imgHeight, List<System::Drawing::Rectangle>^ regionsOfInterest) { AlprResultsNet^ Recognize(cli::array<Byte>^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight) {
unsigned char* p = AlprHelper::ToCharPtr(pixelData); return Recognize(imageBuffer, bytesPerPixel, imgWidth, imgHeight, gcnew List<System::Drawing::Rectangle>());
}
/// <summary>
/// Recognize from raw pixel data
/// </summary>
AlprResultsNet^ Recognize(cli::array<Byte>^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight, List<System::Drawing::Rectangle>^ regionsOfInterest) {
unsigned char* p = AlprHelper::ToCharPtr(imageBuffer);
std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest); std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest);
AlprResults results = m_Impl->recognize(p, bytesPerPixel, imgWidth, imgHeight, rois); AlprResults results = m_Impl->recognize(p, bytesPerPixel, imgWidth, imgHeight, rois);
free(p); // ?? memory leak? free(p); // ?? memory leak?
return gcnew AlprResultsNet(results); return gcnew AlprResultsNet(results);
} }
bool isLoaded() { bool IsLoaded() {
return m_Impl->isLoaded(); return m_Impl->isLoaded();
} }
static System::String^ getVersion() { static System::String^ GetVersion() {
return AlprHelper::ToManagedString(Alpr::getVersion()); return AlprHelper::ToManagedString(Alpr::getVersion());
} }
@@ -1346,6 +1430,6 @@ namespace openalprnet {
int m_topN; int m_topN;
bool m_detectRegion; bool m_detectRegion;
System::String^ m_defaultRegion; System::String^ m_defaultRegion;
bool m_Disposed; bool m_disposed;
}; };
} }

View File

@@ -66,11 +66,11 @@ namespace openalprnet_cli
val => { if (val.Any()) filename = val.First().Trim(); }) 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 config = Path.Combine(AssemblyDirectory, "openalpr.conf");
var runtime_data = Path.Combine(AssemblyDirectory, "runtime_data"); var runtime_data = Path.Combine(AssemblyDirectory, "runtime_data");
var alpr = new AlprNet(region, config, runtime_data); var alpr = new AlprNet(region, config, runtime_data);
if (!alpr.isLoaded()) if (!alpr.IsLoaded())
{ {
Console.WriteLine("OpenAlpr failed to load!"); Console.WriteLine("OpenAlpr failed to load!");
return; return;
@@ -110,8 +110,7 @@ namespace openalprnet_cli
private static void PerformAlpr(AlprNet alpr, byte[] buffer, bool benchmark, bool writeJson) private static void PerformAlpr(AlprNet alpr, byte[] buffer, bool benchmark, bool writeJson)
{ {
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
sbyte[] signedBuffer = (sbyte[])(Array)buffer; var results = alpr.Recognize(buffer);
var results = alpr.recognize(signedBuffer);
sw.Stop(); sw.Stop();
if (benchmark) if (benchmark)
{ {
@@ -125,14 +124,14 @@ namespace openalprnet_cli
else else
{ {
var i = 0; 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("Plate {0}: {1} result(s)", i++, result.TopNPlates.Count);
Console.WriteLine(" Processing Time: {0} msec(s)", result.processing_time_ms); Console.WriteLine(" Processing Time: {0} msec(s)", result.ProcessingTimeMs);
foreach (var plate in result.topNPlates) foreach (var plate in result.TopNPlates)
{ {
Console.WriteLine(" - {0}\t Confidence: {1}\tMatches Template: {2}", plate.characters, Console.WriteLine(" - {0}\t Confidence: {1}\tMatches Template: {2}", plate.Characters,
plate.overall_confidence, plate.matches_template); plate.OverallConfidence, plate.MatchesTemplate);
} }
} }
} }

View File

@@ -22,6 +22,7 @@ using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using openalprnet; using openalprnet;
@@ -135,7 +136,7 @@ namespace openalprnet_windemo
String runtime_data_dir = Path.Combine(AssemblyDirectory, "runtime_data"); String runtime_data_dir = Path.Combine(AssemblyDirectory, "runtime_data");
using (var alpr = new AlprNet(region, config_file, runtime_data_dir)) using (var alpr = new AlprNet(region, config_file, runtime_data_dir))
{ {
if (!alpr.isLoaded()) if (!alpr.IsLoaded())
{ {
lbxPlates.Items.Add("Error initializing OpenALPR"); lbxPlates.Items.Add("Error initializing OpenALPR");
return; return;
@@ -143,24 +144,31 @@ namespace openalprnet_windemo
picOriginal.ImageLocation = fileName; picOriginal.ImageLocation = fileName;
picOriginal.Load(); picOriginal.Load();
var results = alpr.recognize(fileName); var motionDetection = new AlprMotionDetectionNet();
var b = File.ReadAllBytes(fileName);
var images = new List<Image>(results.plates.Count()); Parallel.For(0, int.MaxValue, (x) =>
var i = 1;
foreach (var result in results.plates)
{ {
var rect = boundingRectangle(result.plate_points); motionDetection.MotionDetect(b);
});
var results = alpr.Recognize(fileName);
var images = new List<Image>(results.Plates.Count());
var i = 1;
foreach (var result in results.Plates)
{
var rect = boundingRectangle(result.PlatePoints);
var img = Image.FromFile(fileName); var img = Image.FromFile(fileName);
var cropped = cropImage(img, rect); var cropped = cropImage(img, rect);
images.Add(cropped); images.Add(cropped);
lbxPlates.Items.Add("\t\t-- Plate #" + i++ + " --"); 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}", lbxPlates.Items.Add(string.Format(@"{0} {1}% {2}",
plate.characters.PadRight(12), plate.Characters.PadRight(12),
plate.overall_confidence.ToString("N1").PadLeft(8), plate.OverallConfidence.ToString("N1").PadLeft(8),
plate.matches_template.ToString().PadLeft(8))); plate.MatchesTemplate.ToString().PadLeft(8)));
} }
} }