Files
openalpr-base/src/bindings/csharp/openalpr-net/openalpr-net.cpp
Peter Rekdal Sunde ebae0af256 Use overload.
2015-08-13 17:59:57 +02:00

499 lines
13 KiB
C++

/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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<System::Drawing::Point>(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<AlprPlateNet^>(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<System::Drawing::Point>^ PlatePoints {
List<System::Drawing::Point>^ get() {
return m_plate_points;
}
}
property List<AlprPlateNet^>^ TopNPlates {
List<AlprPlateNet^>^ 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<AlprPlateNet^>^ m_topNPlates;
List<System::Drawing::Point>^ 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<System::Drawing::Rectangle>(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<AlprPlateResultNet^>(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<System::Drawing::Rectangle>^ RegionsOfInterest {
List<System::Drawing::Rectangle>^ get() {
return m_regionsOfInterest;
}
}
property List<AlprPlateResultNet^>^ Plates {
List<AlprPlateResultNet^>^ 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<System::Drawing::Rectangle>^ m_regionsOfInterest;
List<AlprPlateResultNet^>^ 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<std::string>(country), marshal_as<std::string>(configFile), marshal_as<std::string>(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<std::string>(region));
}
}
event EventHandler<AlprFrameEventArgs^>^ FrameProcessed;
void RecognizeFromVideo(System::String^ videoPath) {
if (System::IO::File::Exists(videoPath)) {
int framenum = 0;
cv::VideoCapture cap = cv::VideoCapture();
cap.open(marshal_as<std::string>(videoPath));
cv::Mat frame;
while (cap.read(frame))
{
std::vector<AlprRegionOfInterest> 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);
}
}
/// <summary>
/// Recognize from an image on disk
/// </summary>
AlprResultsNet^ Recognize(System::String^ filepath) {
return Recognize(filepath, gcnew List<System::Drawing::Rectangle>());
}
/// <summary>
/// Recognize from an image on disk
/// </summary>
AlprResultsNet^ Recognize(System::String^ filepath, List<System::Drawing::Rectangle>^ regionsOfInterest) {
array<Byte>^ byteArray = File::ReadAllBytes(filepath);
return Recognize(byteArray, regionsOfInterest);
}
/// <summary>
/// Recognize from a bitmap
/// </summary>
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)
{
BitmapMat^ wrapper = gcnew BitmapMat(bitmap);
cv::Mat frame = wrapper->Value;
std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest);
AlprResults results = m_Impl->recognize(frame.data, frame.elemSize(), frame.cols, frame.rows, rois);
delete wrapper;
return gcnew AlprResultsNet(results);
}
/// <summary>
/// Recognize from MemoryStream representing an encoded image (e.g., BMP, PNG, JPG, GIF etc).
/// </summary>
AlprResultsNet^ Recognize(MemoryStream^ memoryStream)
{
return Recognize(memoryStream, gcnew List<System::Drawing::Rectangle>());
}
/// <summary>
/// Recognize from MemoryStream representing an encoded image (e.g., BMP, PNG, JPG, GIF etc).
/// </summary>
AlprResultsNet^ Recognize(MemoryStream^ memoryStream, List<System::Drawing::Rectangle>^ regionsOfInterest)
{
return Recognize(memoryStream->ToArray(), regionsOfInterest);
}
/// <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(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(array<Byte>^ imageBuffer, List<System::Drawing::Rectangle>^ regionsOfInterest) {
std::vector<char> buffer = AlprHelper::ToVector(imageBuffer);
std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest);
AlprResults results = m_Impl->recognize(buffer, rois);
return gcnew AlprResultsNet(results);
}
/// <summary>
/// Recognize from raw pixel data
/// </summary>
AlprResultsNet^ Recognize(array<Byte>^ imageBuffer, int bytesPerPixel, int imgWidth, int imgHeight) {
return Recognize(imageBuffer, bytesPerPixel, imgWidth, imgHeight, gcnew List<System::Drawing::Rectangle>());
}
/// <summary>
/// Recognize from raw pixel data
/// </summary>
AlprResultsNet^ Recognize(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);
AlprResults results = m_Impl->recognize(p, bytesPerPixel, imgWidth, imgHeight, rois);
free(p); // ?? memory leak?
return gcnew AlprResultsNet(results);
}
/// <summary>
/// Pre-warp from raw pixel data.
/// </summary>
array<Byte>^ PreWarp(array<Byte>^ imageBuffer)
{
std::vector<char> buffer = AlprHelper::ToVector(imageBuffer);
cv::Mat src = cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR);
alpr::PreWarp *preWarp = new alpr::PreWarp(m_Impl->getConfig());
cv::Mat warpedImage = preWarp->warpImage(src);
std::vector<uchar> warpedImageVector;
cv::imencode(".jpg", warpedImage, warpedImageVector);
const size_t warpedImageSize = warpedImageVector.size();
array<Byte>^ warpedImageByteArray = gcnew array<Byte>(warpedImageSize);
pin_ptr<Byte> 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;
};
}