Conflicts:
	src/openalpr/support/re2/util/strutil.cc
This commit is contained in:
Matt Hill
2015-08-12 09:09:51 -04:00
55 changed files with 525 additions and 282 deletions

View File

@@ -69,3 +69,13 @@ Description: Utilities for the OpenALPR library
OpenALPR is an open source Automatic License Plate Recognition library written OpenALPR is an open source Automatic License Plate Recognition library written
in C++. The library analyzes images and identifies license plates. The output in C++. The library analyzes images and identifies license plates. The output
is the text representation of any license plate characters found in the image. is the text representation of any license plate characters found in the image.
Package: python-openalpr
Section: python
Architecture: amd64
Depends: libopenalpr-dev (= ${binary:Version}), ${misc:Depends}
Description: Python binding for OpenALPR library
OpenALPR is an open source Automatic License Plate Recognition library written
in C++. The library analyzes images and identifies license plates. The output
is the text representation of any license plate characters found in the image.

View File

@@ -0,0 +1 @@
usr/lib/python2.7/dist-packages/openalpr

View File

@@ -30,3 +30,7 @@ min_plate_size_width_px = 85
min_plate_size_height_px = 28 min_plate_size_height_px = 28
ocr_language = lau ocr_language = lau
; Override for postprocess letters/numbers regex.
postprocess_regex_letters = [A-Z]
postprocess_regex_numbers = [0-9]

View File

@@ -31,3 +31,7 @@ min_plate_size_width_px = 100
min_plate_size_height_px = 20 min_plate_size_height_px = 20
ocr_language = lau ocr_language = lau
; Override for postprocess letters/numbers regex.
postprocess_regex_letters = [A-Z]
postprocess_regex_numbers = [0-9]

View File

@@ -32,3 +32,7 @@ min_plate_size_width_px = 65
min_plate_size_height_px = 18 min_plate_size_height_px = 18
ocr_language = leu ocr_language = leu
; Override for postprocess letters/numbers regex.
postprocess_regex_letters = [A-Z]
postprocess_regex_numbers = [0-9]

View File

@@ -5,7 +5,7 @@ char_analysis_height_range = 0.15
char_analysis_height_step_size = 0.10 char_analysis_height_step_size = 0.10
char_analysis_height_num_steps = 5 char_analysis_height_num_steps = 5
segmentation_min_box_width_px = 5 segmentation_min_box_width_px = 4
segmentation_min_charheight_percent = 0.4; segmentation_min_charheight_percent = 0.4;
segmentation_max_segment_width_percent_vs_average = 2.0; segmentation_max_segment_width_percent_vs_average = 2.0;
@@ -15,7 +15,7 @@ plate_height_mm = 110
multiline = 0 multiline = 0
char_height_mm = 80 char_height_mm = 80
char_width_mm = 53 char_width_mm = 43
char_whitespace_top_mm = 10 char_whitespace_top_mm = 10
char_whitespace_bot_mm = 10 char_whitespace_bot_mm = 10
@@ -31,3 +31,7 @@ min_plate_size_width_px = 100
min_plate_size_height_px = 20 min_plate_size_height_px = 20
ocr_language = lkr ocr_language = lkr
; Override for postprocess letters/numbers regex.
postprocess_regex_letters = \pL
postprocess_regex_numbers = \pN

View File

@@ -30,3 +30,7 @@ min_plate_size_width_px = 70
min_plate_size_height_px = 35 min_plate_size_height_px = 35
ocr_language = lus ocr_language = lus
; Override for postprocess letters/numbers regex.
postprocess_regex_letters = [A-Z]
postprocess_regex_numbers = [0-9]

View File

@@ -36,22 +36,22 @@ gi [G]####@
gr @@@#### gr @@@####
hu @@@### hu @@@###
is @@@## is @@@##
ie [12]##@###### ie ##[12][CDGLTW]######
ie [12]##@@###### ie ##[12][CDGKLMORSTW][DEHKLMNOSWXY]######
ie [12]##@##### ie ##[12][CDGLTW]#####
ie [12]##@@##### ie ##[12][CDGKLMORSTW][DEHKLMNOSWXY]#####
ie [12]##@#### ie ##[12][CDGLTW]####
ie [12]##@@#### ie ##[12][CDGKLMORSTW][DEHKLMNOSWXY]####
ie [12]##@### ie ##[12][CDGLTW]###
ie [12]##@@### ie ##[12][CDGKLMORSTW][DEHKLMNOSWXY]###
ie ##@###### ie ##[CDGLTW]######
ie ##@@###### ie ##[CDGKLMORSTW][DEHKLMNOSWXY]######
ie ##@##### ie ##[CDGLTW]#####
ie ##@@##### ie ##[CDGKLMORSTW][DEHKLMNOSWXY]#####
ie ##@#### ie ##[CDGLTW]####
ie ##@@#### ie ##[CDGKLMORSTW][DEHKLMNOSWXY]####
ie ##@### ie ##[CDGLTW]###
ie ##@@### ie ##[CDGKLMORSTW][DEHKLMNOSWXY]###
it @@###@@ it @@###@@
kz ###@@@ kz ###@@@
lv @@#### lv @@####

View File

@@ -203,6 +203,8 @@ va ####@@
va #####[JY] va #####[JY]
wa ###@@@ wa ###@@@
wa @@@#### wa @@@####
wi ###@@@
wi @@@###
wv [1-9DON]@@### wv [1-9DON]@@###
wv [1-9DON]@#### wv [1-9DON]@####
wy ###### wy ######

View File

@@ -101,6 +101,7 @@ ENDIF()
TARGET_LINK_LIBRARIES(alpr TARGET_LINK_LIBRARIES(alpr
${OPENALPR_LIB} ${OPENALPR_LIB}
statedetection
support support
video video
${OpenCV_LIBS} ${OpenCV_LIBS}
@@ -134,6 +135,7 @@ add_subdirectory(tests)
ENDIF() ENDIF()
add_subdirectory(openalpr) add_subdirectory(openalpr)
add_subdirectory(statedetection)
add_subdirectory(video) add_subdirectory(video)
if (WITH_BINDING_JAVA) if (WITH_BINDING_JAVA)

View File

@@ -38,5 +38,3 @@ using namespace System::Security::Permissions;
[assembly:ComVisible(false)]; [assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)]; [assembly:CLSCompliantAttribute(true)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];

View File

@@ -65,7 +65,7 @@ namespace openalprnet {
channels = 4; channels = 4;
break; break;
default: default:
throw gcnew NotImplementedException(); throw gcnew NotSupportedException(bitmap->PixelFormat.ToString());
} }
BitmapData^ bitmapData = bitmap->LockBits( BitmapData^ bitmapData = bitmap->LockBits(

View File

@@ -50,6 +50,11 @@ namespace openalprnet
static Bitmap^ MatToBitmap(cv::Mat mat) static Bitmap^ MatToBitmap(cv::Mat mat)
{ {
if (mat.empty())
{
return nullptr;
}
const int width = mat.size().width; const int width = mat.size().width;
const int height = mat.size().height; const int height = mat.size().height;
const int channels = mat.channels(); const int channels = mat.channels();

View File

@@ -326,7 +326,7 @@ namespace openalprnet {
event EventHandler<AlprFrameEventArgs^>^ FrameProcessed; event EventHandler<AlprFrameEventArgs^>^ FrameProcessed;
void recognizeFromVideo(System::String^ videoPath) { void RecognizeFromVideo(System::String^ videoPath) {
if (System::IO::File::Exists(videoPath)) { if (System::IO::File::Exists(videoPath)) {
int framenum = 0; int framenum = 0;
cv::VideoCapture cap = cv::VideoCapture(); cv::VideoCapture cap = cv::VideoCapture();
@@ -409,8 +409,9 @@ namespace openalprnet {
/// </summary> /// </summary>
AlprResultsNet^ Recognize(MemoryStream^ memoryStream, List<System::Drawing::Rectangle>^ regionsOfInterest) AlprResultsNet^ Recognize(MemoryStream^ memoryStream, List<System::Drawing::Rectangle>^ regionsOfInterest)
{ {
std::vector<char> p = AlprHelper::MemoryStreamToVector(memoryStream); std::vector<char> buffer = AlprHelper::MemoryStreamToVector(memoryStream);
AlprResults results = m_Impl->recognize(p); std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest);
AlprResults results = m_Impl->recognize(buffer, rois);
return gcnew AlprResultsNet(results); return gcnew AlprResultsNet(results);
} }
@@ -427,8 +428,9 @@ namespace openalprnet {
/// </summary> /// </summary>
/// <param name="imageBuffer">Bytes representing image data</param> /// <param name="imageBuffer">Bytes representing image data</param>
AlprResultsNet^ Recognize(cli::array<Byte>^ imageBuffer, List<System::Drawing::Rectangle>^ regionsOfInterest) { AlprResultsNet^ Recognize(cli::array<Byte>^ imageBuffer, List<System::Drawing::Rectangle>^ regionsOfInterest) {
std::vector<char> p = AlprHelper::ToVector(imageBuffer); std::vector<char> buffer = AlprHelper::ToVector(imageBuffer);
AlprResults results = m_Impl->recognize(p); std::vector<AlprRegionOfInterest> rois = AlprHelper::ToVector(regionsOfInterest);
AlprResults results = m_Impl->recognize(buffer, rois);
return gcnew AlprResultsNet(results); return gcnew AlprResultsNet(results);
} }
@@ -450,6 +452,32 @@ namespace openalprnet {
return gcnew AlprResultsNet(results); 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, 1);
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() { bool IsLoaded() {
return m_Impl->isLoaded(); return m_Impl->isLoaded();
} }

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "alpr.h" #include "alpr.h"
#include "prewarp.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View File

@@ -25,6 +25,7 @@
<RootNamespace>openalprnet</RootNamespace> <RootNamespace>openalprnet</RootNamespace>
<OpenALPRVersion>2.1.0</OpenALPRVersion> <OpenALPRVersion>2.1.0</OpenALPRVersion>
<PlatformToolset>v120</PlatformToolset> <PlatformToolset>v120</PlatformToolset>
<PlatformToolset Condition="$(VisualStudioVersion)=='14.0'">v140</PlatformToolset>
<OpenALPRWindowsDir>..\..\..\..\windows</OpenALPRWindowsDir> <OpenALPRWindowsDir>..\..\..\..\windows</OpenALPRWindowsDir>
<CudaGeneration Condition="$(CudaGeneration)=='' OR $(CudaGeneration)=='None'">None</CudaGeneration> <CudaGeneration Condition="$(CudaGeneration)=='' OR $(CudaGeneration)=='None'">None</CudaGeneration>
<OpenALPRDistDir Condition="$(CudaGeneration)=='None'">$(OpenALPRWindowsDir)\build\dist\$(OpenALPRVersion)\$(PlatformToolset)\$(Configuration)\$(Platform)</OpenALPRDistDir> <OpenALPRDistDir Condition="$(CudaGeneration)=='None'">$(OpenALPRWindowsDir)\build\dist\$(OpenALPRVersion)\$(PlatformToolset)\$(Configuration)\$(Platform)</OpenALPRDistDir>
@@ -105,7 +106,7 @@
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;$(OpenALPRDistDir)\opencv_videostab$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ts$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_stitching$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_contrib$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\libtesseract$(TesseractVersion)-static$(TesseractDebugPrefix).lib;$(OpenALPRDistDir)\liblept$(LeptonicaVersion)$(DebugPrefix).lib;ws2_32.lib;$(OpenALPRDistDir)\opencv_nonfree$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_gpu$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_photo$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_objdetect$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_legacy$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_video$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ml$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_calib3d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_features2d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_highgui$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_imgproc$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_flann$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_core$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\support.lib;$(OpenALPRDistDir)\openalpr-static.lib</AdditionalDependencies> <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;$(OpenALPRDistDir)\opencv_videostab$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ts$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_stitching$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_contrib$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\libtesseract$(TesseractVersion)-static$(TesseractDebugPrefix).lib;$(OpenALPRDistDir)\liblept$(LeptonicaVersion)$(DebugPrefix).lib;ws2_32.lib;$(OpenALPRDistDir)\opencv_nonfree$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_gpu$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_photo$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_objdetect$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_legacy$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_video$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ml$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_calib3d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_features2d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_highgui$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_imgproc$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_flann$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_core$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\support.lib;$(OpenALPRDistDir)\openalpr-static.lib;$(OpenALPRDistDir)\statedetection.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -118,7 +119,7 @@
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;$(OpenALPRDistDir)\opencv_videostab$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ts$(OpenCVVersion)$(DebugPrefix).lib;$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_stitching$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_contrib$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\libtesseract$(TesseractVersion)-static$(TesseractDebugPrefix).lib;$(OpenALPRDistDir)\liblept$(LeptonicaVersion)$(DebugPrefix).lib;ws2_32.lib;$(OpenALPRDistDir)\opencv_nonfree$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_gpu$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_photo$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_objdetect$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_legacy$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_video$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ml$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_calib3d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_features2d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_highgui$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_imgproc$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_flann$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_core$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\support.lib;$(OpenALPRDistDir)\openalpr-static.lib</AdditionalDependencies> <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;$(OpenALPRDistDir)\opencv_videostab$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ts$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_stitching$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_contrib$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\libtesseract$(TesseractVersion)-static$(TesseractDebugPrefix).lib;$(OpenALPRDistDir)\liblept$(LeptonicaVersion)$(DebugPrefix).lib;ws2_32.lib;$(OpenALPRDistDir)\opencv_nonfree$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_gpu$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_photo$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_objdetect$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_legacy$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_video$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ml$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_calib3d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_features2d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_highgui$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_imgproc$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_flann$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_core$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\support.lib;$(OpenALPRDistDir)\openalpr-static.lib;$(OpenALPRDistDir)\statedetection.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -130,7 +131,7 @@
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;$(OpenALPRDistDir)\opencv_videostab$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ts$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_stitching$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_contrib$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\libtesseract$(TesseractVersion)-static$(TesseractDebugPrefix).lib;$(OpenALPRDistDir)\liblept$(LeptonicaVersion)$(DebugPrefix).lib;ws2_32.lib;$(OpenALPRDistDir)\opencv_nonfree$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_gpu$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_photo$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_objdetect$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_legacy$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_video$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ml$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_calib3d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_features2d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_highgui$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_imgproc$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_flann$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_core$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\support.lib;$(OpenALPRDistDir)\openalpr-static.lib</AdditionalDependencies> <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;$(OpenALPRDistDir)\opencv_videostab$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ts$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_stitching$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_contrib$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\libtesseract$(TesseractVersion)-static$(TesseractDebugPrefix).lib;$(OpenALPRDistDir)\liblept$(LeptonicaVersion)$(DebugPrefix).lib;ws2_32.lib;$(OpenALPRDistDir)\opencv_nonfree$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_gpu$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_photo$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_objdetect$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_legacy$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_video$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ml$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_calib3d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_features2d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_highgui$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_imgproc$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_flann$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_core$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\support.lib;$(OpenALPRDistDir)\openalpr-static.lib;$(OpenALPRDistDir)\statedetection.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -142,7 +143,7 @@
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;$(OpenALPRDistDir)\opencv_videostab$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ts$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_stitching$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_contrib$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\libtesseract$(TesseractVersion)-static$(TesseractDebugPrefix).lib;$(OpenALPRDistDir)\liblept$(LeptonicaVersion)$(DebugPrefix).lib;ws2_32.lib;$(OpenALPRDistDir)\opencv_nonfree$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_gpu$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_photo$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_objdetect$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_legacy$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_video$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ml$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_calib3d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_features2d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_highgui$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_imgproc$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_flann$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_core$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\support.lib;$(OpenALPRDistDir)\openalpr-static.lib</AdditionalDependencies> <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;$(OpenALPRDistDir)\opencv_videostab$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ts$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_stitching$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_contrib$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\libtesseract$(TesseractVersion)-static$(TesseractDebugPrefix).lib;$(OpenALPRDistDir)\liblept$(LeptonicaVersion)$(DebugPrefix).lib;ws2_32.lib;$(OpenALPRDistDir)\opencv_nonfree$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_gpu$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_photo$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_objdetect$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_legacy$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_video$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_ml$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_calib3d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_features2d$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_highgui$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_imgproc$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_flann$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\opencv_core$(OpenCVVersion)$(DebugPrefix).lib;$(OpenALPRDistDir)\support.lib;$(OpenALPRDistDir)\openalpr-static.lib;$(OpenALPRDistDir)\statedetection.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>

View File

@@ -17,4 +17,7 @@ set_target_properties(openalprpy PROPERTIES SOVERSION ${OPENALPR_MAJOR_VERSION})
TARGET_LINK_LIBRARIES(openalprpy openalpr) TARGET_LINK_LIBRARIES(openalprpy openalpr)
install (TARGETS openalprpy DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) install (TARGETS openalprpy DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
install (DIRECTORY openalpr DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/python2.7/dist-packages
USE_SOURCE_PERMISSIONS
)

View File

@@ -0,0 +1 @@
from openalpr import Alpr

View File

@@ -13,48 +13,52 @@ class Alpr():
self._initialize_func = self._openalprpy_lib.initialize self._initialize_func = self._openalprpy_lib.initialize
self._initialize_func.restype = ctypes.c_void_p
self._initialize_func.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p] self._initialize_func.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p]
self._dispose_func = self._openalprpy_lib.dispose self._dispose_func = self._openalprpy_lib.dispose
self._dispose_func.argtypes = [ctypes.c_void_p]
self._is_loaded_func = self._openalprpy_lib.isLoaded self._is_loaded_func = self._openalprpy_lib.isLoaded
self._is_loaded_func.argtypes = [ctypes.c_void_p]
self._is_loaded_func.restype = ctypes.c_bool self._is_loaded_func.restype = ctypes.c_bool
self._recognize_file_func = self._openalprpy_lib.recognizeFile self._recognize_file_func = self._openalprpy_lib.recognizeFile
self._recognize_file_func.restype = ctypes.c_void_p self._recognize_file_func.restype = ctypes.c_void_p
self._recognize_file_func.argtypes = [ctypes.c_char_p] self._recognize_file_func.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
self._recognize_array_func = self._openalprpy_lib.recognizeArray self._recognize_array_func = self._openalprpy_lib.recognizeArray
self._recognize_array_func.restype = ctypes.c_void_p self._recognize_array_func.restype = ctypes.c_void_p
self._recognize_array_func.argtypes = [ctypes.POINTER(ctypes.c_ubyte), ctypes.c_uint] self._recognize_array_func.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_ubyte), ctypes.c_uint]
self._free_json_mem_func = self._openalprpy_lib.freeJsonMem self._free_json_mem_func = self._openalprpy_lib.freeJsonMem
self._set_default_region_func = self._openalprpy_lib.setDefaultRegion self._set_default_region_func = self._openalprpy_lib.setDefaultRegion
self._set_default_region_func.argtypes = [ctypes.c_char_p] self._set_default_region_func.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
self._set_detect_region_func = self._openalprpy_lib.setDetectRegion self._set_detect_region_func = self._openalprpy_lib.setDetectRegion
self._set_detect_region_func.argtypes = [ctypes.c_bool] self._set_detect_region_func.argtypes = [ctypes.c_void_p, ctypes.c_bool]
self._set_top_n_func = self._openalprpy_lib.setTopN self._set_top_n_func = self._openalprpy_lib.setTopN
self._set_top_n_func.argtypes = [ctypes.c_int] self._set_top_n_func.argtypes = [ctypes.c_void_p, ctypes.c_int]
self._get_version_func = self._openalprpy_lib.getVersion self._get_version_func = self._openalprpy_lib.getVersion
self._get_version_func.argtypes = [ctypes.c_void_p]
self._get_version_func.restype = ctypes.c_void_p self._get_version_func.restype = ctypes.c_void_p
self._initialize_func(country, config_file, runtime_dir) self.alpr_pointer = self._initialize_func(country, config_file, runtime_dir)
def unload(self): def unload(self):
self._openalprpy_lib.dispose() self._openalprpy_lib.dispose(self.alpr_pointer)
def is_loaded(self): def is_loaded(self):
return self._is_loaded_func() return self._is_loaded_func(self.alpr_pointer)
def recognize_file(self, file_path): def recognize_file(self, file_path):
ptr = self._recognize_file_func(file_path) ptr = self._recognize_file_func(self.alpr_pointer, file_path)
json_data = ctypes.cast(ptr, ctypes.c_char_p).value json_data = ctypes.cast(ptr, ctypes.c_char_p).value
response_obj = json.loads(json_data) response_obj = json.loads(json_data)
self._free_json_mem_func(ctypes.c_void_p(ptr)) self._free_json_mem_func(ctypes.c_void_p(ptr))
@@ -64,7 +68,7 @@ class Alpr():
def recognize_array(self, byte_array): def recognize_array(self, byte_array):
pb = ctypes.cast(byte_array, ctypes.POINTER(ctypes.c_ubyte)) pb = ctypes.cast(byte_array, ctypes.POINTER(ctypes.c_ubyte))
ptr = self._recognize_array_func(pb, len(byte_array)) ptr = self._recognize_array_func(self.alpr_pointer, pb, len(byte_array))
json_data = ctypes.cast(ptr, ctypes.c_char_p).value json_data = ctypes.cast(ptr, ctypes.c_char_p).value
response_obj = json.loads(json_data) response_obj = json.loads(json_data)
self._free_json_mem_func(ctypes.c_void_p(ptr)) self._free_json_mem_func(ctypes.c_void_p(ptr))
@@ -73,19 +77,19 @@ class Alpr():
def get_version(self): def get_version(self):
ptr = self._get_version_func() ptr = self._get_version_func(self.alpr_pointer)
version_number = ctypes.cast(ptr, ctypes.c_char_p).value version_number = ctypes.cast(ptr, ctypes.c_char_p).value
self._free_json_mem_func(ctypes.c_void_p(ptr)) self._free_json_mem_func(ctypes.c_void_p(ptr))
return version_number return version_number
def set_top_n(self, topn): def set_top_n(self, topn):
self._set_top_n_func(topn) self._set_top_n_func(self.alpr_pointer, topn)
def set_default_region(self, region): def set_default_region(self, region):
self._set_default_region_func(region) self._set_default_region_func(self.alpr_pointer, region)
def set_detect_region(self, enabled): def set_detect_region(self, enabled):
self._set_detect_region_func(enabled) self._set_detect_region_func(self.alpr_pointer, enabled)

View File

@@ -16,10 +16,8 @@ extern "C" {
using namespace alpr; using namespace alpr;
bool initialized = false;
static Alpr* nativeAlpr;
OPENALPR_EXPORT void initialize(char* ccountry, char* cconfigFile, char* cruntimeDir) OPENALPR_EXPORT Alpr* initialize(char* ccountry, char* cconfigFile, char* cruntimeDir)
{ {
//printf("Initialize"); //printf("Initialize");
@@ -29,35 +27,29 @@ extern "C" {
std::string runtimeDir(cruntimeDir); std::string runtimeDir(cruntimeDir);
//std::cout << country << std::endl << configFile << std::endl << runtimeDir << std::endl; //std::cout << country << std::endl << configFile << std::endl << runtimeDir << std::endl;
nativeAlpr = new alpr::Alpr(country, configFile, runtimeDir); Alpr* nativeAlpr = new alpr::Alpr(country, configFile, runtimeDir);
initialized = true; return nativeAlpr;
return;
} }
OPENALPR_EXPORT void dispose() OPENALPR_EXPORT void dispose(Alpr* nativeAlpr)
{ {
//printf("Dispose");
initialized = false;
delete nativeAlpr; delete nativeAlpr;
} }
OPENALPR_EXPORT bool isLoaded() OPENALPR_EXPORT bool isLoaded(Alpr* nativeAlpr)
{ {
//printf("IS LOADED"); //printf("IS LOADED");
if (!initialized)
return false;
return nativeAlpr->isLoaded(); return nativeAlpr->isLoaded();
} }
OPENALPR_EXPORT char* recognizeFile(char* cimageFile) OPENALPR_EXPORT char* recognizeFile(Alpr* nativeAlpr, char* cimageFile)
{ {
//printf("Recognize file"); //printf("Recognize file");
@@ -83,12 +75,13 @@ extern "C" {
} }
OPENALPR_EXPORT char* recognizeArray(unsigned char* buf, int len) OPENALPR_EXPORT char* recognizeArray(Alpr* nativeAlpr, unsigned char* buf, int len)
{ {
//printf("Recognize byte array"); //printf("Recognize byte array");
//printf("buffer pointer: %p\n", buf); //printf("buffer pointer: %p\n", buf);
//printf("buffer length: %d\n", len); //printf("buffer length: %d\n", len);
//std::cout << "Using instance: " << nativeAlpr << std::endl;
std::vector<char> cvec(buf, buf+len); std::vector<char> cvec(buf, buf+len);
@@ -103,7 +96,7 @@ extern "C" {
return membuffer; return membuffer;
} }
OPENALPR_EXPORT void setDefaultRegion(char* cdefault_region) OPENALPR_EXPORT void setDefaultRegion(Alpr* nativeAlpr, char* cdefault_region)
{ {
// Convert strings from java to C++ and release resources // Convert strings from java to C++ and release resources
std::string default_region(cdefault_region); std::string default_region(cdefault_region);
@@ -111,17 +104,17 @@ extern "C" {
nativeAlpr->setDefaultRegion(default_region); nativeAlpr->setDefaultRegion(default_region);
} }
OPENALPR_EXPORT void setDetectRegion(bool detect_region) OPENALPR_EXPORT void setDetectRegion(Alpr* nativeAlpr, bool detect_region)
{ {
nativeAlpr->setDetectRegion(detect_region); nativeAlpr->setDetectRegion(detect_region);
} }
OPENALPR_EXPORT void setTopN(int top_n) OPENALPR_EXPORT void setTopN(Alpr* nativeAlpr, int top_n)
{ {
nativeAlpr->setTopN(top_n); nativeAlpr->setTopN(top_n);
} }
OPENALPR_EXPORT char* getVersion() OPENALPR_EXPORT char* getVersion(Alpr* nativeAlpr)
{ {
std::string version = nativeAlpr->getVersion(); std::string version = nativeAlpr->getVersion();

View File

@@ -0,0 +1,12 @@
#!/usr/bin/env python
from distutils.core import setup
setup(name='openalpr',
version='1.0',
description='OpenALPR Python Bindings',
author='Matt Hill',
author_email='matthill@openalpr.com',
url='http://www.openalpr.com/',
packages=['openalpr']
)

View File

@@ -198,7 +198,9 @@ int main( int argc, const char** argv )
std::cout << "Video processing ended" << std::endl; std::cout << "Video processing ended" << std::endl;
} }
else if (hasEndingInsensitive(filename, ".avi") || hasEndingInsensitive(filename, ".mp4") || hasEndingInsensitive(filename, ".webm") || else if (hasEndingInsensitive(filename, ".avi") || hasEndingInsensitive(filename, ".mp4") || hasEndingInsensitive(filename, ".webm") ||
hasEndingInsensitive(filename, ".flv") || hasEndingInsensitive(filename, ".mjpg") || hasEndingInsensitive(filename, ".mjpeg")) hasEndingInsensitive(filename, ".flv") || hasEndingInsensitive(filename, ".mjpg") || hasEndingInsensitive(filename, ".mjpeg") ||
hasEndingInsensitive(filename, ".mkv")
)
{ {
if (fileExists(filename.c_str())) if (fileExists(filename.c_str()))
{ {

View File

@@ -2,6 +2,7 @@
ADD_EXECUTABLE( openalpr-utils-sortstate sortstate.cpp ) ADD_EXECUTABLE( openalpr-utils-sortstate sortstate.cpp )
TARGET_LINK_LIBRARIES(openalpr-utils-sortstate TARGET_LINK_LIBRARIES(openalpr-utils-sortstate
${OPENALPR_LIB} ${OPENALPR_LIB}
statedetection
support support
${OpenCV_LIBS} ${OpenCV_LIBS}
${Tesseract_LIBRARIES} ${Tesseract_LIBRARIES}
@@ -23,6 +24,7 @@ ADD_EXECUTABLE(openalpr-utils-benchmark
) )
TARGET_LINK_LIBRARIES(openalpr-utils-benchmark TARGET_LINK_LIBRARIES(openalpr-utils-benchmark
${OPENALPR_LIB} ${OPENALPR_LIB}
statedetection
support support
pthread pthread
${OpenCV_LIBS} ${OpenCV_LIBS}
@@ -72,4 +74,3 @@ ENDIF()
install (TARGETS openalpr-utils-prepcharsfortraining DESTINATION bin) install (TARGETS openalpr-utils-prepcharsfortraining DESTINATION bin)
install (TARGETS openalpr-utils-tagplates DESTINATION bin) install (TARGETS openalpr-utils-tagplates DESTINATION bin)
install (TARGETS openalpr-utils-calibrate DESTINATION bin) install (TARGETS openalpr-utils-calibrate DESTINATION bin)

View File

@@ -167,7 +167,7 @@ int main( int argc, const char** argv )
alpr.setDetectRegion(true); alpr.setDetectRegion(true);
Detector* plateDetector = createDetector(&config); Detector* plateDetector = createDetector(&config);
StateIdentifier stateIdentifier(&config); StateDetector stateDetector(country, config.runtimeBaseDir);
OCR ocr(&config); OCR ocr(&config);
vector<double> endToEndTimes; vector<double> endToEndTimes;
@@ -211,7 +211,7 @@ int main( int argc, const char** argv )
getTimeMonotonic(&startTime); getTimeMonotonic(&startTime);
stateIdentifier.recognize(&pipeline_data); //stateDetector.detect(&pipeline_data);
getTimeMonotonic(&endTime); getTimeMonotonic(&endTime);
double stateidTime = diffclock(startTime, endTime); double stateidTime = diffclock(startTime, endTime);
cout << "\tRegion " << z << ": State ID time: " << stateidTime << "ms." << endl; cout << "\tRegion " << z << ": State ID time: " << stateidTime << "ms." << endl;

View File

@@ -26,7 +26,6 @@
#include "postprocess/regexrule.h" #include "postprocess/regexrule.h"
#include "licenseplatecandidate.h" #include "licenseplatecandidate.h"
#include "stateidentifier.h"
#include "utility.h" #include "utility.h"
#include "support/filesystem.h" #include "support/filesystem.h"
#include "ocr.h" #include "ocr.h"
@@ -324,7 +323,7 @@ vector<string> showCharSelection(Mat image, vector<Rect> charRegions, string sta
for (int i = 0; i < charRegions.size(); i++) for (int i = 0; i < charRegions.size(); i++)
humanInputs[i] = SPACE; humanInputs[i] = SPACE;
RegexRule regex_rule("", "[\\p{Digit}\\p{Alpha}]"); RegexRule regex_rule("", "[\\pL\\pN]", "", "");
int16_t waitkey = waitKey(50); int16_t waitkey = waitKey(50);
while (waitkey != ENTER_KEY && waitkey != ESCAPE_KEY) while (waitkey != ENTER_KEY && waitkey != ESCAPE_KEY)

View File

@@ -25,7 +25,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include "licenseplatecandidate.h" #include "licenseplatecandidate.h"
#include "stateidentifier.h" #include "../statedetection/state_detector.h"
#include "utility.h" #include "utility.h"
#include "support/filesystem.h" #include "support/filesystem.h"
@@ -36,7 +36,7 @@ using namespace alpr;
// Given a directory full of pre-cropped images, identify the state that each image belongs to. // Given a directory full of pre-cropped images, identify the state that each image belongs to.
// This is used to sort our own positive image database as a first step before grabbing characters to use to train the OCR. // This is used to sort our own positive image database as a first step before grabbing characters to use to train the OCR.
bool detectPlate( StateIdentifier* identifier, Mat frame); bool detectPlate( StateDetector* identifier, Mat frame);
int main( int argc, const char** argv ) int main( int argc, const char** argv )
{ {
@@ -59,7 +59,7 @@ int main( int argc, const char** argv )
} }
Config config("us"); Config config("us");
StateIdentifier identifier(&config); StateDetector identifier(config.country, config.runtimeBaseDir);
if (DirectoryExists(outDir.c_str()) == false) if (DirectoryExists(outDir.c_str()) == false)
{ {
@@ -79,22 +79,17 @@ int main( int argc, const char** argv )
cout << fullpath << endl; cout << fullpath << endl;
frame = imread( fullpath.c_str() ); frame = imread( fullpath.c_str() );
PipelineData pipeline_data(frame, Rect(0, 0, frame.cols, frame.rows), &config);
identifier.recognize(&pipeline_data);
if (pipeline_data.region_confidence <= 20) vector<StateCandidate> candidates = identifier.detect(frame.data, frame.elemSize(), frame.cols, frame.rows);
if (candidates.size() > 0)
{ {
pipeline_data.region_code = "zz"; cout << candidates[0].confidence << " : " << candidates[0].state_code;
pipeline_data.region_confidence = 100;
}
else
{
cout << pipeline_data.region_confidence << " : " << pipeline_data.region_code;
ostringstream convert; // stream used for the conversion ostringstream convert; // stream used for the conversion
convert << i; // insert the textual representation of 'Number' in the characters in the stream convert << i; // insert the textual representation of 'Number' in the characters in the stream
string copyCommand = "cp \"" + fullpath + "\" " + outDir + pipeline_data.region_code + convert.str() + ".png"; string copyCommand = "cp \"" + fullpath + "\" " + outDir + candidates[0].state_code + convert.str() + ".png";
system( copyCommand.c_str() ); system( copyCommand.c_str() );
waitKey(50); waitKey(50);
//while ((char) waitKey(50) != 'c') { } //while ((char) waitKey(50) != 'c') { }
@@ -104,4 +99,4 @@ int main( int argc, const char** argv )
} }
} }
bool detectPlate( StateIdentifier* identifier, Mat frame); bool detectPlate( StateDetector* identifier, Mat frame);

View File

@@ -12,8 +12,6 @@ set(lpr_source_files
detection/detectormorph.cpp detection/detectormorph.cpp
licenseplatecandidate.cpp licenseplatecandidate.cpp
utility.cpp utility.cpp
stateidentifier.cpp
featurematcher.cpp
ocr.cpp ocr.cpp
postprocess/postprocess.cpp postprocess/postprocess.cpp
postprocess/regexrule.cpp postprocess/regexrule.cpp
@@ -51,6 +49,7 @@ set_target_properties(openalpr PROPERTIES SOVERSION ${OPENALPR_MAJOR_VERSION})
TARGET_LINK_LIBRARIES(openalpr TARGET_LINK_LIBRARIES(openalpr
support support
statedetection
${OpenCV_LIBS} ${OpenCV_LIBS}
${Tesseract_LIBRARIES} ${Tesseract_LIBRARIES}
) )

View File

@@ -68,6 +68,11 @@ namespace alpr
return impl->recognize(imageBytes); return impl->recognize(imageBytes);
} }
AlprResults Alpr::recognize(std::vector<char> imageBytes, std::vector<AlprRegionOfInterest> regionsOfInterest)
{
return impl->recognize(imageBytes, regionsOfInterest);
}
AlprResults Alpr::recognize(unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest) AlprResults Alpr::recognize(unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest)
{ {
return impl->recognize(pixelData, bytesPerPixel, imgWidth, imgHeight, regionsOfInterest); return impl->recognize(pixelData, bytesPerPixel, imgWidth, imgHeight, regionsOfInterest);

View File

@@ -132,8 +132,11 @@ namespace alpr
// Recognize from an image on disk // Recognize from an image on disk
AlprResults recognize(std::string filepath); AlprResults recognize(std::string filepath);
// 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).
AlprResults recognize(std::vector<char> imageBytes); AlprResults recognize(std::vector<char> imageBytes);
// Recognize from byte data representing an encoded image (e.g., BMP, PNG, JPG, GIF etc).
AlprResults recognize(std::vector<char> imageBytes, std::vector<AlprRegionOfInterest> regionsOfInterest);
// Recognize from raw pixel data. // Recognize from raw pixel data.
AlprResults recognize(unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest); AlprResults recognize(unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest);

View File

@@ -36,7 +36,7 @@ namespace alpr
config = new Config(country, configFile, runtimeDir); config = new Config(country, configFile, runtimeDir);
plateDetector = ALPR_NULL_PTR; plateDetector = ALPR_NULL_PTR;
stateIdentifier = ALPR_NULL_PTR; stateDetector = ALPR_NULL_PTR;
ocr = ALPR_NULL_PTR; ocr = ALPR_NULL_PTR;
prewarp = ALPR_NULL_PTR; prewarp = ALPR_NULL_PTR;
@@ -69,8 +69,8 @@ namespace alpr
if (plateDetector != ALPR_NULL_PTR) if (plateDetector != ALPR_NULL_PTR)
delete plateDetector; delete plateDetector;
if (stateIdentifier != ALPR_NULL_PTR) if (stateDetector != ALPR_NULL_PTR)
delete stateIdentifier; delete stateDetector;
if (ocr != ALPR_NULL_PTR) if (ocr != ALPR_NULL_PTR)
delete ocr; delete ocr;
@@ -97,6 +97,10 @@ namespace alpr
response.results.img_width = img.cols; response.results.img_width = img.cols;
response.results.img_height = img.rows; response.results.img_height = img.rows;
// Fix regions of interest in case they extend beyond the bounds of the image
for (unsigned int i = 0; i < regionsOfInterest.size(); i++)
regionsOfInterest[i] = expandRect(regionsOfInterest[i], 0, 0, img.cols, img.rows);
for (unsigned int i = 0; i < regionsOfInterest.size(); i++) for (unsigned int i = 0; i < regionsOfInterest.size(); i++)
{ {
response.results.regionsOfInterest.push_back(AlprRegionOfInterest(regionsOfInterest[i].x, regionsOfInterest[i].y, response.results.regionsOfInterest.push_back(AlprRegionOfInterest(regionsOfInterest[i].x, regionsOfInterest[i].y,
@@ -152,6 +156,7 @@ namespace alpr
plateQueue.pop(); plateQueue.pop();
PipelineData pipeline_data(img, grayImg, plateRegion.rect, config); PipelineData pipeline_data(img, grayImg, plateRegion.rect, config);
pipeline_data.prewarp = prewarp;
timespec platestarttime; timespec platestarttime;
getTimeMonotonic(&platestarttime); getTimeMonotonic(&platestarttime);
@@ -180,11 +185,15 @@ namespace alpr
if (detectRegion) if (detectRegion)
{ {
stateIdentifier->recognize(&pipeline_data); std::vector<StateCandidate> state_candidates = stateDetector->detect(pipeline_data.color_deskewed.data,
if (pipeline_data.region_confidence > 0) pipeline_data.color_deskewed.elemSize(),
pipeline_data.color_deskewed.cols,
pipeline_data.color_deskewed.rows);
if (state_candidates.size() > 0)
{ {
plateResult.region = pipeline_data.region_code; plateResult.region = state_candidates[0].state_code;
plateResult.regionConfidence = (int) pipeline_data.region_confidence; plateResult.regionConfidence = (int) state_candidates[0].confidence;
} }
} }
@@ -345,6 +354,16 @@ namespace alpr
return this->recognize(img); return this->recognize(img);
} }
AlprResults AlprImpl::recognize(std::vector<char> imageBytes, std::vector<AlprRegionOfInterest> regionsOfInterest)
{
cv::Mat img = cv::imdecode(cv::Mat(imageBytes), 1);
std::vector<cv::Rect> rois = convertRects(regionsOfInterest);
AlprFullDetails fullDetails = recognizeFullDetails(img, rois);
return fullDetails.results;
}
AlprResults AlprImpl::recognize( unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest) AlprResults AlprImpl::recognize( unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest)
{ {
@@ -570,12 +589,12 @@ namespace alpr
{ {
this->detectRegion = detectRegion; this->detectRegion = detectRegion;
if (detectRegion && this->stateIdentifier == NULL) if (detectRegion && this->stateDetector == NULL)
{ {
timespec startTime; timespec startTime;
getTimeMonotonic(&startTime); getTimeMonotonic(&startTime);
this->stateIdentifier = new StateIdentifier(this->config); this->stateDetector = new StateDetector(this->config->country, this->config->runtimeBaseDir);
timespec endTime; timespec endTime;
getTimeMonotonic(&endTime); getTimeMonotonic(&endTime);

View File

@@ -35,7 +35,7 @@
#include "prewarp.h" #include "prewarp.h"
#include "licenseplatecandidate.h" #include "licenseplatecandidate.h"
#include "stateidentifier.h" #include "../statedetection/state_detector.h"
#include "segmentation/charactersegmenter.h" #include "segmentation/charactersegmenter.h"
#include "ocr.h" #include "ocr.h"
@@ -76,6 +76,7 @@ namespace alpr
AlprFullDetails recognizeFullDetails(cv::Mat img, std::vector<cv::Rect> regionsOfInterest); AlprFullDetails recognizeFullDetails(cv::Mat img, std::vector<cv::Rect> regionsOfInterest);
AlprResults recognize( std::vector<char> imageBytes ); AlprResults recognize( std::vector<char> imageBytes );
AlprResults recognize( std::vector<char> imageBytes, std::vector<AlprRegionOfInterest> regionsOfInterest );
AlprResults recognize( unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest ); AlprResults recognize( unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight, std::vector<AlprRegionOfInterest> regionsOfInterest );
AlprResults recognize( cv::Mat img ); AlprResults recognize( cv::Mat img );
AlprResults recognize( cv::Mat img, std::vector<cv::Rect> regionsOfInterest ); AlprResults recognize( cv::Mat img, std::vector<cv::Rect> regionsOfInterest );
@@ -99,7 +100,7 @@ namespace alpr
private: private:
Detector* plateDetector; Detector* plateDetector;
StateIdentifier* stateIdentifier; StateDetector* stateDetector;
OCR* ocr; OCR* ocr;
PreWarp* prewarp; PreWarp* prewarp;

View File

@@ -244,6 +244,9 @@ namespace alpr
ocrLanguage = getString(ini, "", "ocr_language", "none"); ocrLanguage = getString(ini, "", "ocr_language", "none");
postProcessRegexLetters = getString(ini, "", "postprocess_regex_letters", "\\pL");
postProcessRegexNumbers = getString(ini, "", "postprocess_regex_numbers", "\\pN");
ocrImageWidthPx = round(((float) templateWidthPx) * ocrImagePercent); ocrImageWidthPx = round(((float) templateWidthPx) * ocrImagePercent);
ocrImageHeightPx = round(((float)templateHeightPx) * ocrImagePercent); ocrImageHeightPx = round(((float)templateHeightPx) * ocrImagePercent);
stateIdImageWidthPx = round(((float)templateWidthPx) * stateIdImagePercent); stateIdImageWidthPx = round(((float)templateWidthPx) * stateIdImagePercent);

View File

@@ -100,6 +100,9 @@ namespace alpr
unsigned int postProcessMinCharacters; unsigned int postProcessMinCharacters;
unsigned int postProcessMaxCharacters; unsigned int postProcessMaxCharacters;
std::string postProcessRegexLetters;
std::string postProcessRegexNumbers;
bool debugGeneral; bool debugGeneral;
bool debugTiming; bool debugTiming;
bool debugPrewarp; bool debugPrewarp;
@@ -122,12 +125,13 @@ namespace alpr
std::string getPostProcessRuntimeDir(); std::string getPostProcessRuntimeDir();
std::string getTessdataPrefix(); std::string getTessdataPrefix();
std::string runtimeBaseDir;
private: private:
float ocrImagePercent; float ocrImagePercent;
float stateIdImagePercent; float stateIdImagePercent;
std::string runtimeBaseDir;
void loadCommonValues(std::string configFile); void loadCommonValues(std::string configFile);
void loadCountryValues(std::string configFile, std::string country); void loadCountryValues(std::string configFile, std::string country);

View File

@@ -69,18 +69,19 @@ namespace alpr
float total = getTotal(); float total = getTotal();
std::cout << "--------------------" << std::endl;
std::cout << "Total: " << total << std::endl;
for (unsigned int i = 0; i < weight_ids.size(); i++) for (unsigned int i = 0; i < weight_ids.size(); i++)
{ {
float percent_of_total = (scores[i] * weights[i]) / total * 100; float percent_of_total = (scores[i] * weights[i]) / total * 100;
std::cout << " - " << std::setw(longest_weight_id + 1) << std::left << weight_ids[i] << std::cout << " - " << std::setw(longest_weight_id + 1) << std::left << weight_ids[i] <<
" Weighted Score: " << std::setw(10) << std::left << (scores[i] * weights[i]) << " Weighted Score: " << std::setw(10) << std::left << (scores[i] * weights[i]) <<
" Orig Score: " << std::setw(10) << std::left << scores[i] << " Orig Score: " << std::setw(10) << std::left << scores[i] <<
" (" << percent_of_total << "% of total)" << std::endl; " (" << percent_of_total << "% of total)" << std::endl;
} }
std::cout << "--------------------" << std::endl;
std::cout << "Total: " << total << std::endl;
} }
} }

View File

@@ -71,18 +71,30 @@ namespace alpr
getTimeMonotonic(&startTime); getTimeMonotonic(&startTime);
Mat originalCrop = pipeline_data->crop_gray; // Compute the transformation matrix to go from the current image to the new plate corners
Transformation imgTransform(this->pipeline_data->grayImg, pipeline_data->crop_gray, expandedRegion); Transformation imgTransform(this->pipeline_data->grayImg, pipeline_data->crop_gray, expandedRegion);
Size cropSize = imgTransform.getCropSize(pipeline_data->plate_corners, Size cropSize = imgTransform.getCropSize(pipeline_data->plate_corners,
Size(pipeline_data->config->ocrImageWidthPx, pipeline_data->config->ocrImageHeightPx)); Size(pipeline_data->config->ocrImageWidthPx, pipeline_data->config->ocrImageHeightPx));
Mat transmtx = imgTransform.getTransformationMatrix(pipeline_data->plate_corners, cropSize); Mat transmtx = imgTransform.getTransformationMatrix(pipeline_data->plate_corners, cropSize);
pipeline_data->crop_gray = imgTransform.crop(cropSize, transmtx);
// Crop the plate corners from the original color image (after un-applying prewarp)
vector<Point2f> projectedPoints = pipeline_data->prewarp->projectPoints(pipeline_data->plate_corners, true);
pipeline_data->color_deskewed = Mat::zeros(cropSize, pipeline_data->colorImg.type());
std::vector<cv::Point2f> deskewed_points;
deskewed_points.push_back(cv::Point2f(0,0));
deskewed_points.push_back(cv::Point2f(pipeline_data->color_deskewed.cols,0));
deskewed_points.push_back(cv::Point2f(pipeline_data->color_deskewed.cols,pipeline_data->color_deskewed.rows));
deskewed_points.push_back(cv::Point2f(0,pipeline_data->color_deskewed.rows));
cv::Mat color_transmtx = cv::getPerspectiveTransform(projectedPoints, deskewed_points);
cv::warpPerspective(pipeline_data->colorImg, pipeline_data->color_deskewed, color_transmtx, pipeline_data->color_deskewed.size());
// Make a grayscale copy as well for faster processing downstream
cv::cvtColor(pipeline_data->color_deskewed, pipeline_data->crop_gray, CV_BGR2GRAY);
if (this->config->debugGeneral) if (this->config->debugGeneral)
displayImage(config, "quadrilateral", pipeline_data->crop_gray); displayImage(config, "quadrilateral", pipeline_data->color_deskewed);

View File

@@ -42,12 +42,13 @@ namespace alpr
// Tesseract requires the prefix directory to be set as an env variable // Tesseract requires the prefix directory to be set as an env variable
tesseract.Init(config->getTessdataPrefix().c_str(), config->ocrLanguage.c_str() ); tesseract.Init(config->getTessdataPrefix().c_str(), config->ocrLanguage.c_str() );
tesseract.SetVariable("save_blob_choices", "T"); tesseract.SetVariable("save_blob_choices", "T");
tesseract.SetVariable("debug_file", "/dev/null");
tesseract.SetPageSegMode(PSM_SINGLE_CHAR); tesseract.SetPageSegMode(PSM_SINGLE_CHAR);
} }
OCR::~OCR() OCR::~OCR()
{ {
tesseract.Clear(); tesseract.End();
} }
void OCR::performOCR(PipelineData* pipeline_data) void OCR::performOCR(PipelineData* pipeline_data)

View File

@@ -7,6 +7,7 @@
#include "config.h" #include "config.h"
#include "textdetection/textline.h" #include "textdetection/textline.h"
#include "edges/scorekeeper.h" #include "edges/scorekeeper.h"
#include "prewarp.h"
namespace alpr namespace alpr
{ {
@@ -25,6 +26,8 @@ namespace alpr
// Inputs // Inputs
Config* config; Config* config;
PreWarp* prewarp;
cv::Mat colorImg; cv::Mat colorImg;
cv::Mat grayImg; cv::Mat grayImg;
cv::Rect regionOfInterest; cv::Rect regionOfInterest;
@@ -33,6 +36,8 @@ namespace alpr
cv::Mat crop_gray; cv::Mat crop_gray;
cv::Mat color_deskewed;
bool hasPlateBorder; bool hasPlateBorder;
cv::Mat plateBorderMask; cv::Mat plateBorderMask;
std::vector<TextLine> textLines; std::vector<TextLine> textLines;

View File

@@ -36,7 +36,7 @@ namespace alpr
string region, pattern; string region, pattern;
while (infile >> region >> pattern) while (infile >> region >> pattern)
{ {
RegexRule* rule = new RegexRule(region, pattern); RegexRule* rule = new RegexRule(region, pattern, config->postProcessRegexLetters, config->postProcessRegexNumbers);
//cout << "REGION: " << region << " PATTERN: " << pattern << endl; //cout << "REGION: " << region << " PATTERN: " << pattern << endl;
if (rules.find(region) == rules.end()) if (rules.find(region) == rules.end())
@@ -170,7 +170,7 @@ namespace alpr
for (int i = 0; i < letters.size(); i++) for (int i = 0; i < letters.size(); i++)
{ {
if (letters[i].size() > 0) if (letters[i].size() > 0)
sort(letters[i].begin(), letters[i].end(), letterCompare); std::stable_sort(letters[i].begin(), letters[i].end(), letterCompare);
} }
if (this->config->debugPostProcess) if (this->config->debugPostProcess)
@@ -386,12 +386,6 @@ namespace alpr
return true; return true;
} }
bool wordCompare( const PPResult &left, const PPResult &right )
{
if (left.totalscore < right.totalscore)
return false;
return true;
}
bool letterCompare( const Letter &left, const Letter &right ) bool letterCompare( const Letter &left, const Letter &right )
{ {

View File

@@ -53,7 +53,6 @@ namespace alpr
std::vector<Letter> letter_details; std::vector<Letter> letter_details;
}; };
bool wordCompare( const PPResult &left, const PPResult &right );
bool letterCompare( const Letter &left, const Letter &right ); bool letterCompare( const Letter &left, const Letter &right );
@@ -77,7 +76,7 @@ namespace alpr
private: private:
Config* config; Config* config;
//void getTopN();
void findAllPermutations(std::string templateregion, int topn); void findAllPermutations(std::string templateregion, int topn);
bool analyzePermutation(std::vector<int> letterIndices, std::string templateregion, int topn); bool analyzePermutation(std::vector<int> letterIndices, std::string templateregion, int topn);

View File

@@ -28,7 +28,7 @@ tthread::mutex regexrule_mutex_m;
namespace alpr namespace alpr
{ {
RegexRule::RegexRule(string region, string pattern) RegexRule::RegexRule(string region, string pattern, std::string letters_regex, std::string numbers_regex)
//: re2_regex("") //: re2_regex("")
{ {
this->original = pattern; this->original = pattern;
@@ -80,11 +80,11 @@ namespace alpr
} }
else if (utf_character == "@") else if (utf_character == "@")
{ {
regexval << "\\pL"; regexval << letters_regex;
} }
else if (utf_character == "#") else if (utf_character == "#")
{ {
regexval << "\\pN"; regexval << numbers_regex;
} }
else if ((utf_character == "*") || (utf_character == "+")) else if ((utf_character == "*") || (utf_character == "+"))
{ {

View File

@@ -33,7 +33,7 @@ namespace alpr
class RegexRule class RegexRule
{ {
public: public:
RegexRule(std::string region, std::string pattern); RegexRule(std::string region, std::string pattern, std::string letters_regex, std::string numbers_regex);
virtual ~RegexRule(); virtual ~RegexRule();
bool match(std::string text); bool match(std::string text);

View File

@@ -159,7 +159,6 @@ namespace alpr
getTimeMonotonic(&startTime); getTimeMonotonic(&startTime);
filterEdgeBoxes(pipeline_data->thresholds, candidateBoxes, medianCharWidth, avgCharHeight); filterEdgeBoxes(pipeline_data->thresholds, candidateBoxes, medianCharWidth, avgCharHeight);
candidateBoxes = filterMostlyEmptyBoxes(pipeline_data->thresholds, candidateBoxes);
candidateBoxes = combineCloseBoxes(candidateBoxes, medianCharWidth); candidateBoxes = combineCloseBoxes(candidateBoxes, medianCharWidth);
candidateBoxes = filterMostlyEmptyBoxes(pipeline_data->thresholds, candidateBoxes); candidateBoxes = filterMostlyEmptyBoxes(pipeline_data->thresholds, candidateBoxes);
@@ -260,7 +259,7 @@ namespace alpr
vector<Rect> CharacterSegmenter::getBestCharBoxes(Mat img, vector<Rect> charBoxes, float avgCharWidth) vector<Rect> CharacterSegmenter::getBestCharBoxes(Mat img, vector<Rect> charBoxes, float avgCharWidth)
{ {
float MAX_SEGMENT_WIDTH = avgCharWidth * 1.65; float MAX_SEGMENT_WIDTH = avgCharWidth * config->segmentationMaxCharWidthvsAverage;
// This histogram is based on how many char boxes (from ALL of the many thresholded images) are covering each column // This histogram is based on how many char boxes (from ALL of the many thresholded images) are covering each column
// Makes a sort of histogram from all the previous char boxes. Figures out the best fit from that. // Makes a sort of histogram from all the previous char boxes. Figures out the best fit from that.

View File

@@ -74,7 +74,6 @@ namespace alpr
void cleanCharRegions(std::vector<cv::Mat> thresholds, std::vector<cv::Rect> charRegions); void cleanCharRegions(std::vector<cv::Mat> thresholds, std::vector<cv::Rect> charRegions);
void cleanBasedOnColor(std::vector<cv::Mat> thresholds, cv::Mat colorMask, std::vector<cv::Rect> charRegions); void cleanBasedOnColor(std::vector<cv::Mat> thresholds, cv::Mat colorMask, std::vector<cv::Rect> charRegions);
void cleanMostlyFullBoxes(std::vector<cv::Mat> thresholds, const std::vector<cv::Rect> charRegions);
std::vector<cv::Rect> filterMostlyEmptyBoxes(std::vector<cv::Mat> thresholds, const std::vector<cv::Rect> charRegions); std::vector<cv::Rect> filterMostlyEmptyBoxes(std::vector<cv::Mat> thresholds, const std::vector<cv::Rect> charRegions);
void filterEdgeBoxes(std::vector<cv::Mat> thresholds, const std::vector<cv::Rect> charRegions, float avgCharWidth, float avgCharHeight); void filterEdgeBoxes(std::vector<cv::Mat> thresholds, const std::vector<cv::Rect> charRegions, float avgCharWidth, float avgCharHeight);

View File

@@ -1,94 +0,0 @@
/*
* Copyright (c) 2015 OpenALPR Technology, Inc.
* Open source Automated License Plate Recognition [http://www.openalpr.com]
*
* 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 "stateidentifier.h"
using namespace cv;
using namespace std;
namespace alpr
{
StateIdentifier::StateIdentifier(Config* config)
{
this->config = config;
featureMatcher = new FeatureMatcher(config);
if (featureMatcher->isLoaded() == false)
{
cout << "Can not create detector or descriptor extractor or descriptor matcher of given types" << endl;
return;
}
featureMatcher->loadRecognitionSet(config->country);
}
StateIdentifier::~StateIdentifier()
{
delete featureMatcher;
}
// Attempts to recognize the plate. Returns a confidence level. Updates the region code and confidence
// If region is found, returns true.
bool StateIdentifier::recognize(PipelineData* pipeline_data)
{
timespec startTime;
getTimeMonotonic(&startTime);
Mat plateImg = Mat(pipeline_data->grayImg, pipeline_data->regionOfInterest);
resize(plateImg, plateImg, getSizeMaintainingAspect(plateImg, config->stateIdImageWidthPx, config->stateIdimageHeightPx));
Mat debugImg(plateImg.size(), plateImg.type());
plateImg.copyTo(debugImg);
vector<int> matchesArray(featureMatcher->numTrainingElements());
RecognitionResult result = featureMatcher->recognize(plateImg, true, &debugImg, true, matchesArray );
if (this->config->debugStateId)
{
displayImage(config, "State Identifier1", plateImg);
displayImage(config, "State Identifier", debugImg);
cout << result.haswinner << " : " << result.confidence << " : " << result.winner << endl;
}
if (config->debugTiming)
{
timespec endTime;
getTimeMonotonic(&endTime);
cout << "State Identification Time: " << diffclock(startTime, endTime) << "ms." << endl;
}
if (result.haswinner == false)
return 0;
pipeline_data->region_code = result.winner;
pipeline_data->region_confidence = result.confidence;
if (result.confidence >= 10)
return true;
return false;
}
}

View File

@@ -30,8 +30,9 @@ namespace alpr
return directory; return directory;
#else #else
char buffer[2048]; char buffer[2048];
memset(buffer, 0, sizeof(buffer));
readlink("/proc/self/exe", buffer, 2048); readlink("/proc/self/exe", buffer, sizeof(buffer));
std::stringstream ss; std::stringstream ss;
ss << buffer; ss << buffer;

View File

@@ -1,7 +1,7 @@
#ifndef OPENALPR_PLATFORM_H #ifndef OPENALPR_PLATFORM_H
#define OPENALPR_PLATFORM_H #define OPENALPR_PLATFORM_H
#include <string> #include <string.h>
#include <sstream> #include <sstream>
#ifdef WINDOWS #ifdef WINDOWS

View File

@@ -0,0 +1,27 @@
set(statedetector_source_files
state_detector.cpp
featurematcher.cpp
state_detector_impl.cpp
)
if (WIN32)
add_library(statedetection STATIC ${statedetector_source_files} )
ELSE()
add_library(statedetection SHARED ${statedetector_source_files} )
ENDIF()
set_target_properties(statedetection PROPERTIES SOVERSION ${OPENALPR_MAJOR_VERSION})
TARGET_LINK_LIBRARIES(statedetection
${OpenCV_LIBS}
support
)
install (FILES state_detector.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
install (TARGETS statedetection DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)

View File

@@ -29,10 +29,8 @@ namespace alpr
//const int DEFAULT_TRAINING_FEATURES = 305; //const int DEFAULT_TRAINING_FEATURES = 305;
const float MAX_DISTANCE_TO_MATCH = 100.0f; const float MAX_DISTANCE_TO_MATCH = 100.0f;
FeatureMatcher::FeatureMatcher(Config* config) FeatureMatcher::FeatureMatcher()
{ {
this->config = config;
//this->descriptorMatcher = DescriptorMatcher::create( "BruteForce-HammingLUT" ); //this->descriptorMatcher = DescriptorMatcher::create( "BruteForce-HammingLUT" );
this->descriptorMatcher = new BFMatcher(NORM_HAMMING, false); this->descriptorMatcher = new BFMatcher(NORM_HAMMING, false);
@@ -152,8 +150,8 @@ namespace alpr
// We assume that license plates won't be upside-down or backwards. So expect lines to be closely parallel // We assume that license plates won't be upside-down or backwards. So expect lines to be closely parallel
void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints, const vector<DMatch> inputMatches, vector<DMatch> &outputMatches) void FeatureMatcher::crisscrossFiltering(const vector<KeyPoint> queryKeypoints, const vector<DMatch> inputMatches, vector<DMatch> &outputMatches)
{ {
Rect crissCrossAreaVertical(0, 0, config->stateIdImageWidthPx, config->stateIdimageHeightPx * 2); Rect crissCrossAreaVertical(0, 0, w, h * 2);
Rect crissCrossAreaHorizontal(0, 0, config->stateIdImageWidthPx * 2, config->stateIdimageHeightPx); Rect crissCrossAreaHorizontal(0, 0, w * 2, h);
for (unsigned int i = 0; i < billMapping.size(); i++) for (unsigned int i = 0; i < billMapping.size(); i++)
{ {
@@ -175,8 +173,8 @@ namespace alpr
KeyPoint tkp = trainingImgKeypoints[i][matchesForOnePlate[j].trainIdx]; KeyPoint tkp = trainingImgKeypoints[i][matchesForOnePlate[j].trainIdx];
KeyPoint qkp = queryKeypoints[matchesForOnePlate[j].queryIdx]; KeyPoint qkp = queryKeypoints[matchesForOnePlate[j].queryIdx];
vlines.push_back(LineSegment(tkp.pt.x, tkp.pt.y + config->stateIdimageHeightPx, qkp.pt.x, qkp.pt.y)); vlines.push_back(LineSegment(tkp.pt.x, tkp.pt.y + h, qkp.pt.x, qkp.pt.y));
hlines.push_back(LineSegment(tkp.pt.x, tkp.pt.y, qkp.pt.x + config->stateIdImageWidthPx, qkp.pt.y)); hlines.push_back(LineSegment(tkp.pt.x, tkp.pt.y, qkp.pt.x + w, qkp.pt.y));
matchIdx.push_back(j); matchIdx.push_back(j);
} }
@@ -215,8 +213,8 @@ namespace alpr
if (mostIntersectionsIndex >= 0) if (mostIntersectionsIndex >= 0)
{ {
if (this->config->debugStateId) // if (this->config->debugStateId)
cout << "Filtered intersection! " << billMapping[i] << endl; // cout << "Filtered intersection! " << billMapping[i] << endl;
vlines.erase(vlines.begin() + mostIntersectionsIndex); vlines.erase(vlines.begin() + mostIntersectionsIndex);
hlines.erase(hlines.begin() + mostIntersectionsIndex); hlines.erase(hlines.begin() + mostIntersectionsIndex);
matchIdx.erase(matchIdx.begin() + mostIntersectionsIndex); matchIdx.erase(matchIdx.begin() + mostIntersectionsIndex);
@@ -232,10 +230,10 @@ namespace alpr
} }
// Returns true if successful, false otherwise // Returns true if successful, false otherwise
bool FeatureMatcher::loadRecognitionSet(string country) bool FeatureMatcher::loadRecognitionSet(string directory, string country)
{ {
std::ostringstream out; std::ostringstream out;
out << config->getKeypointsRuntimeDir() << "/" << country << "/"; out << directory << "/keypoints/" << country << "/";
string country_dir = out.str(); string country_dir = out.str();
if (DirectoryExists(country_dir.c_str())) if (DirectoryExists(country_dir.c_str()))
@@ -253,7 +251,6 @@ namespace alpr
// convert to gray and resize to the size of the templates // convert to gray and resize to the size of the templates
cvtColor(img, img, CV_BGR2GRAY); cvtColor(img, img, CV_BGR2GRAY);
resize(img, img, getSizeMaintainingAspect(img, config->stateIdImageWidthPx, config->stateIdimageHeightPx));
if( img.empty() ) if( img.empty() )
{ {
@@ -290,6 +287,9 @@ namespace alpr
{ {
RecognitionResult result; RecognitionResult result;
this->w = queryImg.cols;
this->h = queryImg.rows;
result.haswinner = false; result.haswinner = false;
result.confidence = 0; result.confidence = 0;
@@ -381,13 +381,13 @@ namespace alpr
} }
} }
if (this->config->debugStateId) // if (this->config->debugStateId)
{ // {
for (unsigned int i = 0; i < billMapping.size(); i++) // for (unsigned int i = 0; i < billMapping.size(); i++)
{ // {
cout << billMapping[i] << " : " << bill_match_counts[i] << endl; // cout << billMapping[i] << " : " << bill_match_counts[i] << endl;
} // }
} // }
return result; return result;
} }

View File

@@ -44,20 +44,19 @@ namespace alpr
{ {
public: public:
FeatureMatcher(Config* config); FeatureMatcher();
virtual ~FeatureMatcher(); virtual ~FeatureMatcher();
RecognitionResult recognize( const cv::Mat& queryImg, bool drawOnImage, cv::Mat* outputImage, RecognitionResult recognize( const cv::Mat& queryImg, bool drawOnImage, cv::Mat* outputImage,
bool debug_on, std::vector<int> debug_matches_array ); bool debug_on, std::vector<int> debug_matches_array );
bool loadRecognitionSet(std::string country); bool loadRecognitionSet(std::string runtime_dir, std::string country);
bool isLoaded(); bool isLoaded();
int numTrainingElements(); int numTrainingElements();
private: private:
Config* config;
cv::Ptr<cv::DescriptorMatcher> descriptorMatcher; cv::Ptr<cv::DescriptorMatcher> descriptorMatcher;
cv::Ptr<cv::FastFeatureDetector> detector; cv::Ptr<cv::FastFeatureDetector> detector;
@@ -74,6 +73,9 @@ namespace alpr
void surfStyleMatching( const cv::Mat& queryDescriptors, std::vector<cv::KeyPoint> queryKeypoints, void surfStyleMatching( const cv::Mat& queryDescriptors, std::vector<cv::KeyPoint> queryKeypoints,
std::vector<cv::DMatch>& matches12 ); std::vector<cv::DMatch>& matches12 );
int w;
int h;
}; };
} }

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2015 OpenALPR Technology, Inc.
* Open source Automated License Plate Recognition [http://www.openalpr.com]
*
* 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 "state_detector.h"
#include "state_detector_impl.h"
using namespace std;
namespace alpr {
StateDetector::StateDetector(const std::string country, const std::string runtimeDir) {
impl = new StateDetectorImpl(country, runtimeDir);
}
StateDetector::~StateDetector() {
delete impl;
}
bool StateDetector::isLoaded() {
return impl->isLoaded();
}
void StateDetector::setTopN(int topN) {
impl->setTopN(topN);
}
vector<StateCandidate> StateDetector::detect(vector<char> imageBytes) {
return impl->detect(imageBytes);
}
vector<StateCandidate> StateDetector::detect(unsigned char *pixelData, int bytesPerPixel, int imgWidth,
int imgHeight) {
return impl->detect(pixelData, bytesPerPixel, imgWidth, imgHeight);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2015 OpenALPR Technology, Inc.
* Open source Automated License Plate Recognition [http://www.openalpr.com]
*
* 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/>.
*/
#ifndef OPENALPR_STATE_DETECTOR_H
#define OPENALPR_STATE_DETECTOR_H
#include <string>
#include <vector>
namespace alpr {
struct StateCandidate
{
std::string state_code;
float confidence;
};
class StateDetectorImpl;
class StateDetector {
public:
StateDetector(const std::string country, const std::string runtimeDir);
virtual ~StateDetector();
bool isLoaded();
// Maximum number of candidates to return
void setTopN(int topN);
// Given an image of a license plate, provide the likely state candidates
std::vector<StateCandidate> detect(std::vector<char> imageBytes);
std::vector<StateCandidate> detect(unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight);
StateDetectorImpl* impl;
};
}
#endif //OPENALPR_STATE_DETECTOR_H

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2015 OpenALPR Technology, Inc.
* Open source Automated License Plate Recognition [http://www.openalpr.com]
*
* 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 "state_detector_impl.h"
namespace alpr
{
StateDetectorImpl::StateDetectorImpl(const std::string country, const std::string runtimeDir)
{
if (featureMatcher.isLoaded() == false)
{
std::cout << "Can not create detector or descriptor extractor or descriptor matcher of given types" << std::endl;
return;
}
featureMatcher.loadRecognitionSet(runtimeDir, country);
}
StateDetectorImpl::~StateDetectorImpl() { }
bool StateDetectorImpl::isLoaded() {
return false;
}
void StateDetectorImpl::setTopN(int topN) {
}
std::vector<StateCandidate> StateDetectorImpl::detect(std::vector<char> imageBytes) {
cv::Mat img = cv::imdecode(cv::Mat(imageBytes), 1);
return this->detect(img);
}
std::vector<StateCandidate> StateDetectorImpl::detect(unsigned char *pixelData, int bytesPerPixel, int imgWidth,
int imgHeight) {
int arraySize = imgWidth * imgHeight * bytesPerPixel;
cv::Mat imgData = cv::Mat(arraySize, 1, CV_8U, pixelData);
cv::Mat img = imgData.reshape(bytesPerPixel, imgHeight);
return this->detect(img);
}
std::vector<StateCandidate> StateDetectorImpl::detect(cv::Mat image) {
std::vector<StateCandidate> results;
cv::Mat debugImg(image.size(), image.type());
image.copyTo(debugImg);
std::vector<int> matchesArray(featureMatcher.numTrainingElements());
RecognitionResult result = featureMatcher.recognize(image, true, &debugImg, true, matchesArray );
if (result.haswinner == false)
return results;
StateCandidate top_candidate;
top_candidate.confidence = result.confidence;
top_candidate.state_code = result.winner;
results.push_back(top_candidate);
return results;
}
}

View File

@@ -17,38 +17,33 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef OPENALPR_STATEIDENTIFIER_H #ifndef SRC_STATE_DETECTOR_IMPL_H
#define OPENALPR_STATEIDENTIFIER_H #define SRC_STATE_DETECTOR_IMPL_H
#include "opencv2/imgproc/imgproc.hpp" #include "state_detector.h"
#include "constants.h"
#include "featurematcher.h" #include "featurematcher.h"
#include "utility.h" #include <opencv2/core/core.hpp>
#include "config.h" #include <opencv2/highgui/highgui.hpp>
#include "pipeline_data.h"
namespace alpr namespace alpr {
{
class StateIdentifier
{
class StateDetectorImpl {
public: public:
StateIdentifier(Config* config); StateDetectorImpl(const std::string country, const std::string runtimeDir);
virtual ~StateIdentifier(); virtual ~StateDetectorImpl();
bool recognize(PipelineData* pipeline_data); bool isLoaded();
//int confidence; // Maximum number of candidates to return
void setTopN(int topN);
protected: std::vector<StateCandidate> detect(std::vector<char> imageBytes);
Config* config; std::vector<StateCandidate> detect(unsigned char* pixelData, int bytesPerPixel, int imgWidth, int imgHeight);
std::vector<StateCandidate> detect(cv::Mat image);
private:
FeatureMatcher* featureMatcher;
FeatureMatcher featureMatcher;
}; };
} }
#endif // OPENALPR_STATEIDENTIFIER_H
#endif //SRC_STATE_DETECTOR_IMPL_H

View File

@@ -11,7 +11,7 @@ using namespace alpr;
TEST_CASE( "ASCII tests", "[Regex]" ) { TEST_CASE( "ASCII tests", "[Regex]" ) {
RegexRule rule1("us", "@@@####"); RegexRule rule1("us", "@@@####", "[A-Za-z]", "[0-9]");
REQUIRE( rule1.match("123ABCD") == false); REQUIRE( rule1.match("123ABCD") == false);
REQUIRE( rule1.match("123ABC") == false); REQUIRE( rule1.match("123ABC") == false);
@@ -28,7 +28,7 @@ TEST_CASE( "ASCII tests", "[Regex]" ) {
REQUIRE( rule1.match("AAA1111") == true); REQUIRE( rule1.match("AAA1111") == true);
REQUIRE( rule1.match("zzz1111") == true); REQUIRE( rule1.match("zzz1111") == true);
RegexRule rule2("us", "[ABC]@@####"); RegexRule rule2("us", "[ABC]@@####", "[A-Z]", "[0-9]");
REQUIRE( rule2.match("ZBC1234") == false); REQUIRE( rule2.match("ZBC1234") == false);
REQUIRE( rule2.match("DBC1234") == false); REQUIRE( rule2.match("DBC1234") == false);
@@ -38,7 +38,7 @@ TEST_CASE( "ASCII tests", "[Regex]" ) {
REQUIRE( rule2.match("BAA1111") == true); REQUIRE( rule2.match("BAA1111") == true);
REQUIRE( rule2.match("CAA1111") == true); REQUIRE( rule2.match("CAA1111") == true);
RegexRule rule3("us", "[A]@@###[12]"); RegexRule rule3("us", "[A]@@###[12]", "[A-Z]", "[0-9]");
REQUIRE( rule3.match("ZBC1234") == false); REQUIRE( rule3.match("ZBC1234") == false);
REQUIRE( rule3.match("ZBC1231") == false); REQUIRE( rule3.match("ZBC1231") == false);
@@ -48,7 +48,7 @@ TEST_CASE( "ASCII tests", "[Regex]" ) {
REQUIRE( rule3.match("ABC1232") == true); REQUIRE( rule3.match("ABC1232") == true);
RegexRule rule4("us", "[A-C][E-G]1111"); RegexRule rule4("us", "[A-C][E-G]1111", "[A-Z]", "[0-9]");
REQUIRE( rule4.match("DG1111") == false); REQUIRE( rule4.match("DG1111") == false);
REQUIRE( rule4.match("AD1111") == false); REQUIRE( rule4.match("AD1111") == false);
@@ -61,7 +61,7 @@ TEST_CASE( "ASCII tests", "[Regex]" ) {
REQUIRE( rule4.match("BF1111") == true); REQUIRE( rule4.match("BF1111") == true);
REQUIRE( rule4.match("BG1111") == true); REQUIRE( rule4.match("BG1111") == true);
RegexRule rule5("us", "\\d\\d\\D\\D"); RegexRule rule5("us", "\\d\\d\\D\\D", "[A-Z]", "[0-9]");
REQUIRE( rule5.match("AA11") == false); REQUIRE( rule5.match("AA11") == false);
REQUIRE( rule5.match("11AA") == true); REQUIRE( rule5.match("11AA") == true);
@@ -69,7 +69,7 @@ TEST_CASE( "ASCII tests", "[Regex]" ) {
TEST_CASE( "Unicode tests", "[Regex]" ) { TEST_CASE( "Unicode tests", "[Regex]" ) {
RegexRule rule1("us", "@@@####"); RegexRule rule1("us", "@@@####", "\\pL", "\\pN");
REQUIRE( rule1.match("123与与与下") == false); REQUIRE( rule1.match("123与与与下") == false);
REQUIRE( rule1.match("与万12345") == false); REQUIRE( rule1.match("与万12345") == false);
@@ -78,7 +78,7 @@ TEST_CASE( "Unicode tests", "[Regex]" ) {
REQUIRE( rule1.match("与万口1234") == true); REQUIRE( rule1.match("与万口1234") == true);
RegexRule rule2("us", "[십팔]@@####"); RegexRule rule2("us", "[십팔]@@####", "\\pL", "\\pN");
REQUIRE( rule2.match("123与与与下") == false); REQUIRE( rule2.match("123与与与下") == false);
REQUIRE( rule2.match("与万12345") == false); REQUIRE( rule2.match("与万12345") == false);
@@ -93,7 +93,7 @@ TEST_CASE( "Unicode tests", "[Regex]" ) {
TEST_CASE( "Invalid tests", "[Regex]" ) { TEST_CASE( "Invalid tests", "[Regex]" ) {
RegexRule rule1("us", "[A@@####"); RegexRule rule1("us", "[A@@####", "\\pL", "\\pN");
REQUIRE( rule1.match("123ABCD") == false); REQUIRE( rule1.match("123ABCD") == false);
REQUIRE( rule1.match("123ABC") == false); REQUIRE( rule1.match("123ABC") == false);
@@ -103,6 +103,6 @@ TEST_CASE( "Invalid tests", "[Regex]" ) {
REQUIRE( rule1.match("AAA1111") == false); REQUIRE( rule1.match("AAA1111") == false);
REQUIRE( rule1.match("zzz1111") == false); REQUIRE( rule1.match("zzz1111") == false);
RegexRule rule2("us", "A####]"); RegexRule rule2("us", "A####]", "\\pL", "\\pN");
REQUIRE( rule2.match("A1234") == false); REQUIRE( rule2.match("A1234") == false);
} }