Compare commits
No commits in common. 'b' and 'master' have entirely different histories.
@ -0,0 +1,39 @@
|
||||
**I'm submitting a ...** (check one with "x")
|
||||
|
||||
```
|
||||
[ ] bug report
|
||||
[ ] help wanted
|
||||
[ ] feature request
|
||||
```
|
||||
|
||||
**Current behavior**
|
||||
|
||||
|
||||
|
||||
**Expected/desired behavior**
|
||||
|
||||
|
||||
|
||||
**Reproduction of the problem**
|
||||
|
||||
If the current behavior is a bug or you can illustrate your feature request better with an example, please provide the steps to reproduce.
|
||||
|
||||
|
||||
|
||||
**What is the expected behavior?**
|
||||
|
||||
|
||||
|
||||
**What is the motivation / use case for changing the behavior?**
|
||||
|
||||
|
||||
|
||||
**Please tell us about your environment:**
|
||||
|
||||
* **System:** CentOS
|
||||
|
||||
* **Compiler version/IDE:** gcc4.8
|
||||
|
||||
* **CMake version:** 3.5.1
|
||||
|
||||
* **OpenCV version:** [2.4.9 | 2.4.10 | 2.4.11 | 2.4.12 | 2.4.13 | 3.0 ALPHA | 3.0 BETA | 3.0 RC1 | 3.0 | 3.1 ]
|
||||
@ -0,0 +1,44 @@
|
||||
.idea/
|
||||
_build/
|
||||
resources/image/tmp/
|
||||
*.lib
|
||||
*.suo
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.exe
|
||||
*.dll
|
||||
*.ilk
|
||||
*.pdb
|
||||
experi
|
||||
/tmp
|
||||
resources/image/native_test/*.jpg
|
||||
resources/image/native_test/cars
|
||||
resources/image/native_test/*.py
|
||||
resources/image/phone_test
|
||||
*.vsp
|
||||
*.psess
|
||||
*.DS_Store
|
||||
#ignore thumbnails created by windows
|
||||
Thumbs.db
|
||||
#Ignore files build by Visual Studio
|
||||
*.user
|
||||
*.aps
|
||||
*.pch
|
||||
*.vspscc
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ncb
|
||||
*.tlb
|
||||
*.tlh
|
||||
*.bak
|
||||
[Dd]ebug*/
|
||||
*.sbr
|
||||
obj/
|
||||
[Rr]elease*/
|
||||
_ReSharper*/
|
||||
[Tt]est[Rr]esult*
|
||||
|
||||
*.obj
|
||||
*.cache
|
||||
*.log
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
cmake_minimum_required(VERSION 3.0.0)
|
||||
project(easypr)
|
||||
|
||||
# c++11 required
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/local/opt/opencv-3.2.0")
|
||||
endif ()
|
||||
|
||||
# OpenVC3 required
|
||||
find_package(OpenCV 3.2.0 REQUIRED)
|
||||
|
||||
# where to find header files
|
||||
include_directories(.)
|
||||
include_directories(include)
|
||||
include_directories(${OpenCV_INCLUDE_DIRS})
|
||||
|
||||
# sub directories
|
||||
add_subdirectory(thirdparty)
|
||||
|
||||
# sources to be compiled
|
||||
set(SOURCE_FILES
|
||||
src/core/core_func.cpp
|
||||
src/core/chars_identify.cpp
|
||||
src/core/chars_recognise.cpp
|
||||
src/core/chars_segment.cpp
|
||||
src/core/feature.cpp
|
||||
src/core/plate_detect.cpp
|
||||
src/core/plate_judge.cpp
|
||||
src/core/plate_locate.cpp
|
||||
src/core/plate_recognize.cpp
|
||||
src/core/params.cpp
|
||||
|
||||
src/train/ann_train.cpp
|
||||
src/train/annCh_train.cpp
|
||||
src/train/svm_train.cpp
|
||||
src/train/train.cpp
|
||||
src/train/create_data.cpp
|
||||
|
||||
src/util/util.cpp
|
||||
src/util/program_options.cpp
|
||||
src/util/kv.cpp
|
||||
)
|
||||
|
||||
# pack objects to static library
|
||||
add_library(easypr STATIC ${SOURCE_FILES})
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
set(EXECUTABLE_NAME "demo")
|
||||
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(EXECUTABLE_NAME "demo")
|
||||
endif ()
|
||||
|
||||
# set to be releas mode
|
||||
# set(CMAKE_BUILD_TYPE Release)
|
||||
|
||||
# test cases
|
||||
add_executable(${EXECUTABLE_NAME} test/main.cpp)
|
||||
# link opencv libs
|
||||
target_link_libraries(${EXECUTABLE_NAME} easypr thirdparty ${OpenCV_LIBS})
|
||||
# MESSAGE(${CMAKE_BINARY_DIR}/../)
|
||||
SET_TARGET_PROPERTIES(${EXECUTABLE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/../")
|
||||
@ -1,4 +0,0 @@
|
||||
def hell():
|
||||
a = 20
|
||||
b = 30
|
||||
return a+b
|
||||
@ -0,0 +1,202 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j8
|
||||
@ -0,0 +1,158 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# EasyPR auto configure script
|
||||
# --------------------------------------------------------------------
|
||||
#
|
||||
# This script configures OpenCV3.1 for Visual Studio
|
||||
# on Windows.
|
||||
#
|
||||
# You are required to have Python3.* installed, and python.exe must
|
||||
# be added to your PATH (C:\Python34 for example).
|
||||
#
|
||||
# You can use it by executing:
|
||||
#
|
||||
# C:\> cd path\to\EasyPR
|
||||
# C:\> python configure.py
|
||||
#
|
||||
# Note: compatible with python3, haven't been tested on python2.
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
kProjectDir = "vcprojs"
|
||||
|
||||
kProjects = ["libeasypr.vcxproj", "demo.vcxproj"]
|
||||
|
||||
kProjectTemplates = ["libeasypr.vcxproj.template", "demo.vcxproj.template"]
|
||||
|
||||
kOpenCVConfig = "OpenCVConfig-version.cmake"
|
||||
|
||||
kConfig = {
|
||||
"build": "",
|
||||
"include": "",
|
||||
"library": "",
|
||||
"link": ["opencv_world310"],
|
||||
"bit": "",
|
||||
"vs": ""
|
||||
}
|
||||
|
||||
kPatterns = {
|
||||
"include": "(<AdditionalIncludeDirectories>)(.*?)(</AdditionalIncludeDirectories>)",
|
||||
"library": "(<AdditionalLibraryDirectories>)(.*?)(</AdditionalLibraryDirectories>)",
|
||||
"link": "(<AdditionalDependencies>)(.*?)(</AdditionalDependencies>)"
|
||||
}
|
||||
|
||||
kReplacements = {
|
||||
"include": r"\1%s;\2\3",
|
||||
"library": r'\1%s\3',
|
||||
"link": r'\1%s;\2\3'
|
||||
}
|
||||
|
||||
|
||||
def configure():
|
||||
for i in range(2):
|
||||
print(">> creating %s" % kProjects[i])
|
||||
tpath = os.path.join(kProjectDir, kProjectTemplates[i])
|
||||
fp = open(tpath, encoding="utf-8")
|
||||
try:
|
||||
# read from disk
|
||||
original = fp.read()
|
||||
nstring = ""
|
||||
if 0 == i:
|
||||
nstring = configure_libeasypr(original)
|
||||
elif 1 == i:
|
||||
nstring = configure_demo(original)
|
||||
|
||||
# write to disk
|
||||
wpath = os.path.join(kProjectDir, kProjects[i])
|
||||
writer = open(wpath, mode="wb")
|
||||
try:
|
||||
writer.write(nstring.encode())
|
||||
finally:
|
||||
writer.close()
|
||||
finally:
|
||||
fp.close()
|
||||
print(">> all done! Open EasyPR.sln and have fun!")
|
||||
|
||||
|
||||
def configure_libeasypr(buffer):
|
||||
# additional include dir
|
||||
pattern = re.compile(kPatterns["include"])
|
||||
return pattern.sub(kReplacements["include"] %
|
||||
(kConfig["include"][:2] + re.escape(kConfig["include"][2:])),
|
||||
buffer)
|
||||
|
||||
|
||||
def configure_demo(buffer):
|
||||
# additional include dir
|
||||
pattern = re.compile(kPatterns["include"])
|
||||
nstring = pattern.sub(kReplacements["include"] %
|
||||
(kConfig["include"][:2] + re.escape(kConfig["include"][2:])),
|
||||
buffer)
|
||||
# additional library dir
|
||||
pattern = re.compile(kPatterns["library"])
|
||||
nstring = pattern.sub(kReplacements["library"] %
|
||||
(kConfig["library"][:2] + re.escape(kConfig["library"][2:])),
|
||||
nstring)
|
||||
# additional dependencies
|
||||
#lib_string = ""
|
||||
#for lib in kConfig["link"]:
|
||||
# lib_string += (lib + "d.lib")
|
||||
|
||||
#pattern = re.compile(kPatterns["link"])
|
||||
#return pattern.sub(kReplacements["link"] % lib_string, nstring)
|
||||
|
||||
return nstring
|
||||
|
||||
|
||||
def check_opencv_version():
|
||||
file = os.path.join(kConfig["build"], kOpenCVConfig)
|
||||
print(">> Checking ", file)
|
||||
fp = open(file)
|
||||
opencv_version = 0
|
||||
try:
|
||||
fline = fp.readline()
|
||||
match = re.search(r"OpenCV_VERSION (\d)\.(\d)\.(\d{,2})", fline)
|
||||
if match is not None:
|
||||
opencv_version = match.group(1) + "." + match.group(2)
|
||||
finally:
|
||||
fp.close()
|
||||
return opencv_version
|
||||
|
||||
|
||||
def cli():
|
||||
while True:
|
||||
root_ = input(r"Where is your opencv root path? (e.g, C:\path\to\opencv3): ")
|
||||
if os.path.exists(root_):
|
||||
kConfig["build"] = os.path.join(root_, "build")
|
||||
kConfig["include"] = os.path.join(kConfig["build"], "include")
|
||||
break
|
||||
else:
|
||||
print("Invalid path")
|
||||
|
||||
if check_opencv_version() != "3.1":
|
||||
print("requires opencv 3.1")
|
||||
exit()
|
||||
|
||||
kConfig["bit"] = "x64"
|
||||
|
||||
while True:
|
||||
vc = input("Which Visual Studio you are using? (vs2013 or vs2015): ")
|
||||
if vc == "vs2013":
|
||||
kConfig["vs"] = "vc12"
|
||||
break
|
||||
elif vc == "vs2015":
|
||||
kConfig["vs"] = "vc14"
|
||||
break
|
||||
else:
|
||||
print("Please type vs2013 or vs2015")
|
||||
|
||||
kConfig["library"] = os.path.normpath("%s/%s/%s/lib/" % (kConfig["build"], kConfig["bit"], kConfig["vs"]))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
||||
configure()
|
||||
@ -0,0 +1,13 @@
|
||||
#ifndef EASYPR_EASYPR_H
|
||||
#define EASYPR_EASYPR_H
|
||||
|
||||
#include "easypr/core/plate_recognize.h"
|
||||
#include "easypr/train/svm_train.h"
|
||||
#include "easypr/train/ann_train.h"
|
||||
#include "easypr/train/annCh_train.h"
|
||||
#include "easypr/util/util.h"
|
||||
#include "easypr/util/program_options.h"
|
||||
#include "easypr/api.hpp"
|
||||
#include "easypr/config.h"
|
||||
|
||||
#endif //EASYPR_EASYPR_H
|
||||
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file provides some of the most commonly used application interfaces.
|
||||
*/
|
||||
#ifndef EASYPR_API_HPP
|
||||
#define EASYPR_API_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include "easypr/config.h"
|
||||
|
||||
namespace easypr {
|
||||
|
||||
namespace api {
|
||||
|
||||
static bool plate_judge(const char* image, const char* model) {
|
||||
cv::Mat src = cv::imread(image);
|
||||
assert(!src.empty());
|
||||
|
||||
int result;
|
||||
result = PlateJudge::instance()->plateJudge(src);
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
static void plate_locate(const char* image, const bool life_mode = true) {
|
||||
cv::Mat src = cv::imread(image);
|
||||
|
||||
assert(!src.empty());
|
||||
|
||||
CPlateLocate plate;
|
||||
plate.setDebug(1);
|
||||
plate.setLifemode(life_mode);
|
||||
|
||||
std::vector<cv::Mat> results;
|
||||
plate.plateLocate(src, results);
|
||||
}
|
||||
|
||||
static std::vector<std::string> plate_recognize(const char* image,
|
||||
const char* model_svm,
|
||||
const char* model_ann,
|
||||
const bool life_mode = true) {
|
||||
cv::Mat img = cv::imread(image);
|
||||
assert(!img.empty());
|
||||
|
||||
CPlateRecognize pr;
|
||||
pr.setResultShow(false);
|
||||
pr.setLifemode(true);
|
||||
pr.setMaxPlates(1);
|
||||
pr.setDetectType(PR_DETECT_CMSER | PR_DETECT_COLOR);
|
||||
|
||||
std::vector<std::string> results;
|
||||
std::vector<CPlate> plates;
|
||||
pr.plateRecognize(img, plates, 0);
|
||||
|
||||
for (auto plate : plates) {
|
||||
results.push_back(plate.getPlateStr());
|
||||
|
||||
}
|
||||
|
||||
if (plates.size() == 1) {
|
||||
if (1) {
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
ss << "result.jpg";
|
||||
imwrite(ss.str(), plates.at(0).getPlateMat());
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(results);
|
||||
}
|
||||
|
||||
static Color get_plate_color(const char* image) {
|
||||
cv::Mat img = cv::imread(image);
|
||||
|
||||
assert(!img.empty());
|
||||
|
||||
return getPlateType(img, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // EASYPR_API_HPP
|
||||
@ -0,0 +1,148 @@
|
||||
#ifndef EASYPR_CONFIG_H_
|
||||
#define EASYPR_CONFIG_H_
|
||||
|
||||
#define CV_VERSION_THREE_ZERO
|
||||
|
||||
namespace easypr {
|
||||
|
||||
enum Color { BLUE, YELLOW , GREEN, WHITE, UNKNOWN };
|
||||
|
||||
enum LocateType { SOBEL, COLOR, CMSER, OTHER };
|
||||
|
||||
enum CharSearchDirection { LEFT, RIGHT };
|
||||
|
||||
enum
|
||||
{
|
||||
PR_MODE_UNCONSTRAINED,
|
||||
PR_MODE_CAMERPOHNE,
|
||||
PR_MODE_PARKING,
|
||||
PR_MODE_HIGHWAY
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PR_DETECT_SOBEL = 0x01, /**Sobel detect type, using twice Sobel */
|
||||
PR_DETECT_COLOR = 0x02, /**Color detect type */
|
||||
PR_DETECT_CMSER = 0x04, /**Character detect type, using mser */
|
||||
};
|
||||
|
||||
static const char* kDefaultSvmPath = "model/svm_hist.xml";
|
||||
static const char* kLBPSvmPath = "model/svm_lbp.xml";
|
||||
static const char* kHistSvmPath = "model/svm_hist.xml";
|
||||
|
||||
static const char* kDefaultAnnPath = "model/ann.xml";
|
||||
static const char* kChineseAnnPath = "model/ann_chinese.xml";
|
||||
static const char* kGrayAnnPath = "model/annCh.xml";
|
||||
|
||||
//This is important to for key transform to chinese
|
||||
static const char* kChineseMappingPath = "model/province_mapping";
|
||||
|
||||
typedef enum {
|
||||
kForward = 1, // correspond to "has plate"
|
||||
kInverse = 0 // correspond to "no plate"
|
||||
} SvmLabel;
|
||||
|
||||
static const int kPlateResizeWidth = 136;
|
||||
static const int kPlateResizeHeight = 36;
|
||||
|
||||
static const int kShowWindowWidth = 1000;
|
||||
static const int kShowWindowHeight = 800;
|
||||
|
||||
static const float kSvmPercentage = 0.7f;
|
||||
|
||||
static const int kCharacterInput = 120;
|
||||
static const int kChineseInput = 440;
|
||||
static const int kAnnInput = kCharacterInput;
|
||||
|
||||
static const int kCharacterSize = 10;
|
||||
static const int kChineseSize = 20;
|
||||
static const int kPredictSize = kCharacterSize;
|
||||
|
||||
static const int kNeurons = 40;
|
||||
|
||||
static const char *kChars[] = {
|
||||
"0", "1", "2",
|
||||
"3", "4", "5",
|
||||
"6", "7", "8",
|
||||
"9",
|
||||
/* 10 */
|
||||
"A", "B", "C",
|
||||
"D", "E", "F",
|
||||
"G", "H", /* {"I", "I"} */
|
||||
"J", "K", "L",
|
||||
"M", "N", /* {"O", "O"} */
|
||||
"P", "Q", "R",
|
||||
"S", "T", "U",
|
||||
"V", "W", "X",
|
||||
"Y", "Z",
|
||||
/* 24 */
|
||||
"zh_cuan" , "zh_e" , "zh_gan" ,
|
||||
"zh_gan1" , "zh_gui" , "zh_gui1" ,
|
||||
"zh_hei" , "zh_hu" , "zh_ji" ,
|
||||
"zh_jin" , "zh_jing" , "zh_jl" ,
|
||||
"zh_liao" , "zh_lu" , "zh_meng" ,
|
||||
"zh_min" , "zh_ning" , "zh_qing" ,
|
||||
"zh_qiong", "zh_shan" , "zh_su" ,
|
||||
"zh_sx" , "zh_wan" , "zh_xiang",
|
||||
"zh_xin" , "zh_yu" , "zh_yu1" ,
|
||||
"zh_yue" , "zh_yun" , "zh_zang" ,
|
||||
"zh_zhe"
|
||||
/* 31 */
|
||||
};
|
||||
|
||||
static const int kCharactersNumber = 34;
|
||||
static const int kChineseNumber = 31;
|
||||
static const int kCharsTotalNumber = 65;
|
||||
|
||||
static bool kDebug = false;
|
||||
|
||||
static const int kGrayCharWidth = 20;
|
||||
static const int kGrayCharHeight = 32;
|
||||
static const int kCharLBPGridX = 4;
|
||||
static const int kCharLBPGridY = 4;
|
||||
static const int kCharLBPPatterns = 16;
|
||||
|
||||
static const int kCharHiddenNeurans = 64;
|
||||
|
||||
static const int kCharsCountInOnePlate = 7;
|
||||
static const int kSymbolsCountInChinesePlate = 6;
|
||||
|
||||
static const float kPlateMaxSymbolCount = 7.5f;
|
||||
static const int kSymbolIndex = 2;
|
||||
|
||||
// Disable the copy and assignment operator for this class.
|
||||
#define DISABLE_ASSIGN_AND_COPY(className) \
|
||||
private:\
|
||||
className& operator=(const className&); \
|
||||
className(const className&)
|
||||
|
||||
// Display the image.
|
||||
#define SET_DEBUG(param) \
|
||||
kDebug = param
|
||||
|
||||
// Display the image.
|
||||
#define SHOW_IMAGE(imgName, debug) \
|
||||
if (debug) { \
|
||||
namedWindow("imgName", WINDOW_AUTOSIZE); \
|
||||
moveWindow("imgName", 500, 500); \
|
||||
imshow("imgName", imgName); \
|
||||
waitKey(0); \
|
||||
destroyWindow("imgName"); \
|
||||
}
|
||||
|
||||
// Load model. compatitable withe 3.0, 3.1 and 3.2
|
||||
#ifdef CV_VERSION_THREE_TWO
|
||||
#define LOAD_SVM_MODEL(model, path) \
|
||||
model = ml::SVM::load(path);
|
||||
#define LOAD_ANN_MODEL(model, path) \
|
||||
model = ml::ANN_MLP::load(path);
|
||||
#else
|
||||
#define LOAD_SVM_MODEL(model, path) \
|
||||
model = ml::SVM::load<ml::SVM>(path);
|
||||
#define LOAD_ANN_MODEL(model, path) \
|
||||
model = ml::ANN_MLP::load<ml::ANN_MLP>(path);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // EASYPR_CONFIG_H_
|
||||
@ -0,0 +1,131 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name: CHARACTER Header
|
||||
// Version: 1.0
|
||||
// Date: 2016-06-14
|
||||
// Author: liuruoze
|
||||
// Copyright: liuruoze
|
||||
// Desciption:
|
||||
// An abstract class for car character in plate.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#ifndef EASYPR_CORE_CHARACTER_H_
|
||||
#define EASYPR_CORE_CHARACTER_H_
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
/*! \namespace easypr
|
||||
Namespace where all the C++ EasyPR functionality resides
|
||||
*/
|
||||
namespace easypr {
|
||||
|
||||
class CCharacter {
|
||||
public:
|
||||
CCharacter()
|
||||
{
|
||||
m_characterMat = Mat();
|
||||
m_characterGrayMat = Mat();
|
||||
m_characterPos = Rect();
|
||||
m_characterStr = "";
|
||||
m_score = 0;
|
||||
m_isChinese = false;
|
||||
m_ostuLevel = 125;
|
||||
m_center = Point(0, 0);
|
||||
m_index = 0;
|
||||
}
|
||||
|
||||
CCharacter(const CCharacter& other)
|
||||
{
|
||||
m_characterMat = other.m_characterMat;
|
||||
m_characterGrayMat = other.m_characterGrayMat;
|
||||
m_characterPos = other.m_characterPos;
|
||||
m_characterStr = other.m_characterStr;
|
||||
m_score = other.m_score;
|
||||
m_isChinese = other.m_isChinese;
|
||||
m_ostuLevel = other.m_ostuLevel;
|
||||
m_center = other.m_center;
|
||||
m_index = other.m_index;
|
||||
}
|
||||
|
||||
inline void setCharacterMat(Mat param) { m_characterMat = param; }
|
||||
inline Mat getCharacterMat() const { return m_characterMat; }
|
||||
|
||||
inline void setCharacterGrayMat(Mat param) { m_characterGrayMat = param; }
|
||||
inline Mat getCharacterGrayMat() const { return m_characterGrayMat; }
|
||||
|
||||
inline void setCharacterPos(Rect param) { m_characterPos = param; }
|
||||
inline Rect getCharacterPos() const { return m_characterPos; }
|
||||
|
||||
inline void setCharacterStr(String param) { m_characterStr = param; }
|
||||
inline String getCharacterStr() const { return m_characterStr; }
|
||||
|
||||
inline void setCharacterScore(double param) { m_score = param; }
|
||||
inline double getCharacterScore() const { return m_score; }
|
||||
|
||||
inline void setIsChinese(bool param) { m_isChinese = param; }
|
||||
inline bool getIsChinese() const { return m_isChinese; }
|
||||
|
||||
inline void setOstuLevel(double param) { m_ostuLevel = param; }
|
||||
inline double getOstuLevel() const { return m_ostuLevel; }
|
||||
|
||||
inline void setCenterPoint(Point param) { m_center = param; }
|
||||
inline Point getCenterPoint() const { return m_center; }
|
||||
|
||||
inline void setIndex(int param) { m_index = param; }
|
||||
inline int getIndex() const { return m_index; }
|
||||
|
||||
inline bool getIsStrong() const { return m_score >= 0.9; }
|
||||
inline bool getIsWeak() const { return m_score < 0.9 && m_score >= 0.5; }
|
||||
inline bool getIsLittle() const { return m_score < 0.5; }
|
||||
|
||||
bool operator < (const CCharacter& other) const
|
||||
{
|
||||
return (m_score > other.m_score);
|
||||
}
|
||||
|
||||
bool operator < (const CCharacter& other)
|
||||
{
|
||||
return (m_score > other.m_score);
|
||||
}
|
||||
|
||||
private:
|
||||
//! character mat
|
||||
Mat m_characterMat;
|
||||
|
||||
//! character gray mat
|
||||
Mat m_characterGrayMat;
|
||||
|
||||
//! character rect
|
||||
Rect m_characterPos;
|
||||
|
||||
//! character str
|
||||
String m_characterStr;
|
||||
|
||||
//! character likely
|
||||
double m_score;
|
||||
|
||||
//! weather is chinese
|
||||
bool m_isChinese;
|
||||
|
||||
//! ostu level
|
||||
double m_ostuLevel;
|
||||
|
||||
//! center point
|
||||
Point m_center;
|
||||
|
||||
//! the postion in the plate, from 1 to 7 normal
|
||||
int m_index;
|
||||
|
||||
////! m_score >= 0.9
|
||||
//bool isStrong;
|
||||
|
||||
////! m_score < 0.9 && m_score >= 0.5
|
||||
//bool isWeak;
|
||||
|
||||
////! m_score < 0.5
|
||||
//bool isLittle;
|
||||
};
|
||||
|
||||
} /*! \namespace easypr*/
|
||||
|
||||
#endif // EASYPR_CORE_PLATE_H_
|
||||
@ -0,0 +1,58 @@
|
||||
#ifndef EASYPR_CORE_CHARSIDENTIFY_H_
|
||||
#define EASYPR_CORE_CHARSIDENTIFY_H_
|
||||
|
||||
#include <memory>
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
||||
#include "easypr/util/kv.h"
|
||||
#include "easypr/core/character.hpp"
|
||||
#include "easypr/core/feature.h"
|
||||
|
||||
namespace easypr {
|
||||
|
||||
class CharsIdentify {
|
||||
public:
|
||||
static CharsIdentify* instance();
|
||||
|
||||
int classify(cv::Mat f, float& maxVal, bool isChinses = false, bool isAlphabet = false);
|
||||
void classify(cv::Mat featureRows, std::vector<int>& out_maxIndexs,
|
||||
std::vector<float>& out_maxVals, std::vector<bool> isChineseVec);
|
||||
void classify(std::vector<CCharacter>& charVec);
|
||||
|
||||
void classifyChinese(std::vector<CCharacter>& charVec);
|
||||
void classifyChineseGray(std::vector<CCharacter>& charVec);
|
||||
|
||||
std::pair<std::string, std::string> identify(cv::Mat input, bool isChinese = false, bool isAlphabet = false);
|
||||
int identify(std::vector<cv::Mat> inputs, std::vector<std::pair<std::string, std::string>>& outputs,
|
||||
std::vector<bool> isChineseVec);
|
||||
|
||||
std::pair<std::string, std::string> identifyChinese(cv::Mat input, float& result, bool& isChinese);
|
||||
std::pair<std::string, std::string> identifyChineseGray(cv::Mat input, float& result, bool& isChinese);
|
||||
|
||||
bool isCharacter(cv::Mat input, std::string& label, float& maxVal, bool isChinese = false);
|
||||
|
||||
void LoadModel(std::string path);
|
||||
void LoadChineseModel(std::string path);
|
||||
void LoadGrayChANN(std::string path);
|
||||
void LoadChineseMapping(std::string path);
|
||||
|
||||
private:
|
||||
CharsIdentify();
|
||||
annCallback extractFeature;
|
||||
static CharsIdentify* instance_;
|
||||
|
||||
// binary character classifer
|
||||
cv::Ptr<cv::ml::ANN_MLP> ann_;
|
||||
|
||||
// binary character classifer, only for chinese
|
||||
cv::Ptr<cv::ml::ANN_MLP> annChinese_;
|
||||
|
||||
// gray classifer, only for chinese
|
||||
cv::Ptr<cv::ml::ANN_MLP> annGray_;
|
||||
|
||||
// used for chinese mapping
|
||||
std::shared_ptr<Kv> kv_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EASYPR_CORE_CHARSIDENTIFY_H_
|
||||
@ -0,0 +1,83 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name: chars_recognise Header
|
||||
// Version: 1.0
|
||||
// Date: 2014-09-28
|
||||
// Author: liuruoze
|
||||
// Copyright: liuruoze
|
||||
// Reference: Mastering OpenCV with Practical Computer Vision Projects
|
||||
// Reference: CSDN Bloger taotao1233
|
||||
// Desciption:
|
||||
// Defines CCharsRecognise
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#ifndef EASYPR_CORE_CHARSRECOGNISE_H_
|
||||
#define EASYPR_CORE_CHARSRECOGNISE_H_
|
||||
|
||||
#include "easypr/core/chars_segment.h"
|
||||
#include "easypr/core/chars_identify.h"
|
||||
#include "easypr/core/core_func.h"
|
||||
#include "easypr/util/util.h"
|
||||
#include "easypr/core/plate.hpp"
|
||||
#include "easypr/config.h"
|
||||
|
||||
namespace easypr {
|
||||
|
||||
class CCharsRecognise {
|
||||
public:
|
||||
CCharsRecognise();
|
||||
|
||||
~CCharsRecognise();
|
||||
|
||||
int charsRecognise(cv::Mat plate, std::string& plateLicense);
|
||||
int charsRecognise(CPlate& plate, std::string& plateLicense);
|
||||
|
||||
inline std::string getPlateColor(cv::Mat input) const {
|
||||
std::string color = "未知";
|
||||
Color result = getPlateType(input, true);
|
||||
if (BLUE == result) color = "蓝牌";
|
||||
if (YELLOW == result) color = "黄牌";
|
||||
if (WHITE == result) color = "白牌";
|
||||
#ifdef OS_WINDOWS
|
||||
color = utils::utf8_to_gbk(color.c_str());
|
||||
#endif
|
||||
return color;
|
||||
}
|
||||
|
||||
inline std::string getPlateColor(Color in) const {
|
||||
std::string color = "未知";
|
||||
if (BLUE == in) color = "蓝牌";
|
||||
if (YELLOW == in) color = "黄牌";
|
||||
if (WHITE == in) color = "白牌";
|
||||
#ifdef OS_WINDOWS
|
||||
color = utils::utf8_to_gbk(color.c_str());
|
||||
#endif
|
||||
return color;
|
||||
}
|
||||
|
||||
inline void setLiuDingSize(int param) {
|
||||
m_charsSegment->setLiuDingSize(param);
|
||||
}
|
||||
inline void setColorThreshold(int param) {
|
||||
m_charsSegment->setColorThreshold(param);
|
||||
}
|
||||
inline void setBluePercent(float param) {
|
||||
m_charsSegment->setBluePercent(param);
|
||||
}
|
||||
inline float getBluePercent() const {
|
||||
return m_charsSegment->getBluePercent();
|
||||
}
|
||||
inline void setWhitePercent(float param) {
|
||||
m_charsSegment->setWhitePercent(param);
|
||||
}
|
||||
inline float getWhitePercent() const {
|
||||
return m_charsSegment->getWhitePercent();
|
||||
}
|
||||
|
||||
private:
|
||||
//!字符分割
|
||||
|
||||
CCharsSegment* m_charsSegment;
|
||||
};
|
||||
|
||||
} /* \namespace easypr */
|
||||
|
||||
#endif // EASYPR_CORE_CHARSRECOGNISE_H_
|
||||
@ -0,0 +1,84 @@
|
||||
#ifndef EASYPR_CORE_CHARSSEGMENT_H_
|
||||
#define EASYPR_CORE_CHARSSEGMENT_H_
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include "easypr/config.h"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
namespace easypr {
|
||||
|
||||
class CCharsSegment {
|
||||
public:
|
||||
CCharsSegment();
|
||||
//! using ostu algotithm the segment chars in plate
|
||||
int charsSegment(Mat input, std::vector<Mat>& resultVec, Color color = BLUE);
|
||||
|
||||
//! using methods to segment chars in plate
|
||||
int charsSegmentUsingOSTU(Mat input, std::vector<Mat>& resultVec, std::vector<Mat>& grayChars, Color color = BLUE);
|
||||
int charsSegmentUsingMSER(Mat input, vector<Mat>& resultVec, vector<Mat>& grayChars, Color color = BLUE);
|
||||
|
||||
//! using project
|
||||
int projectSegment(const Mat& input, Color color, vector<int>& out_indexs);
|
||||
|
||||
bool verifyCharSizes(Mat r);
|
||||
|
||||
// find the best chinese binaranzation method
|
||||
void judgeChinese(Mat in, Mat& out, Color plateType);
|
||||
void judgeChineseGray(Mat in, Mat& out, Color plateType);
|
||||
|
||||
Mat preprocessChar(Mat in);
|
||||
|
||||
//! to find the position of chinese
|
||||
Rect GetChineseRect(const Rect rectSpe);
|
||||
|
||||
//! find the character refer to city, like "suA" A
|
||||
int GetSpecificRect(const std::vector<Rect>& vecRect);
|
||||
|
||||
//! Do two things
|
||||
// 1.remove rect in the left of city character
|
||||
// 2.from the city rect, to the right, choose 6 rects
|
||||
int RebuildRect(const std::vector<Rect>& vecRect, std::vector<Rect>& outRect,
|
||||
int specIndex);
|
||||
|
||||
int SortRect(const std::vector<Rect>& vecRect, std::vector<Rect>& out);
|
||||
|
||||
inline void setLiuDingSize(int param) { m_LiuDingSize = param; }
|
||||
inline void setColorThreshold(int param) { m_ColorThreshold = param; }
|
||||
|
||||
inline void setBluePercent(float param) { m_BluePercent = param; }
|
||||
inline float getBluePercent() const { return m_BluePercent; }
|
||||
inline void setWhitePercent(float param) { m_WhitePercent = param; }
|
||||
inline float getWhitePercent() const { return m_WhitePercent; }
|
||||
|
||||
static const int DEFAULT_DEBUG = 1;
|
||||
|
||||
static const int CHAR_SIZE = 20;
|
||||
static const int HORIZONTAL = 1;
|
||||
static const int VERTICAL = 0;
|
||||
|
||||
static const int DEFAULT_LIUDING_SIZE = 7;
|
||||
static const int DEFAULT_MAT_WIDTH = 136;
|
||||
static const int DEFAULT_COLORTHRESHOLD = 150;
|
||||
|
||||
inline void setDebug(int param) { m_debug = param; }
|
||||
|
||||
inline int getDebug() { return m_debug; }
|
||||
|
||||
private:
|
||||
|
||||
int m_LiuDingSize;
|
||||
|
||||
int m_theMatWidth;
|
||||
|
||||
int m_ColorThreshold;
|
||||
float m_BluePercent;
|
||||
float m_WhitePercent;
|
||||
|
||||
int m_debug;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // EASYPR_CORE_CHARSSEGMENT_H_
|
||||
@ -0,0 +1,159 @@
|
||||
#ifndef EASYPR_CORE_COREFUNC_H_
|
||||
#define EASYPR_CORE_COREFUNC_H_
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include "easypr/core/plate.hpp"
|
||||
#include "easypr/core/character.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
/*! \namespace easypr
|
||||
Namespace where all the C++ EasyPR functionality resides
|
||||
*/
|
||||
namespace easypr {
|
||||
|
||||
//! find binary image match to color
|
||||
//! input rgb, want match color ( blue or yellow)
|
||||
//! out grey, 255 is match, 0 is not match
|
||||
|
||||
Mat colorMatch(const Mat& src, Mat& match, const Color r,
|
||||
const bool adaptive_minsv);
|
||||
|
||||
//Mat mserMatch(const Mat& src, Mat& match, const Color r,
|
||||
// std::vector<RotatedRect>& plateRect, std::vector<Rect>& out_charRect);
|
||||
|
||||
bool plateColorJudge(const Mat& src, const Color r, const bool adaptive_minsv,
|
||||
float& percent);
|
||||
|
||||
bool bFindLeftRightBound(Mat& bound_threshold, int& posLeft, int& posRight);
|
||||
bool bFindLeftRightBound1(Mat& bound_threshold, int& posLeft, int& posRight);
|
||||
bool bFindLeftRightBound2(Mat& bound_threshold, int& posLeft, int& posRight);
|
||||
|
||||
bool clearLiuDing(Mat& img);
|
||||
void clearLiuDingOnly(Mat& img);
|
||||
void clearLiuDing(Mat mask, int& top, int& bottom);
|
||||
|
||||
Color getPlateType(const Mat& src, const bool adaptive_minsv);
|
||||
|
||||
Mat histeq(Mat in);
|
||||
Rect GetCenterRect(Mat& in);
|
||||
Mat CutTheRect(Mat& in, Rect& rect);
|
||||
int ThresholdOtsu(Mat mat);
|
||||
|
||||
// project histogram
|
||||
Mat ProjectedHistogram(Mat img, int t, int threshold = 20);
|
||||
|
||||
Mat showHistogram(const Mat& hist);
|
||||
|
||||
Mat preprocessChar(Mat in, int char_size);
|
||||
|
||||
Rect GetChineseRect(const Rect rectSpe);
|
||||
|
||||
bool verifyCharSizes(Rect r);
|
||||
bool verifyPlateSize(Rect mr);
|
||||
bool verifyRotatedPlateSizes(RotatedRect mr, bool showDebug = false);
|
||||
|
||||
// non-maximum suppression
|
||||
void NMStoCharacter(std::vector<CCharacter> &inVec, double overlap);
|
||||
|
||||
// draw rotatedRectangle
|
||||
void rotatedRectangle(InputOutputArray img, RotatedRect rect,
|
||||
const Scalar& color, int thickness = 1,
|
||||
int lineType = LINE_8, int shift = 0);
|
||||
|
||||
// ostu region
|
||||
void spatial_ostu(InputArray _src, int grid_x, int grid_y, Color type = BLUE);
|
||||
|
||||
// Scale to small image (for the purpose of comput mser in large image)
|
||||
Mat scaleImage(const Mat& image, const Size& maxSize, double& scale_ratio);
|
||||
|
||||
// Scale back RotatedRect
|
||||
RotatedRect scaleBackRRect(const RotatedRect& rr, const float scale_ratio);
|
||||
|
||||
//! use verify size to first generate char candidates
|
||||
void mserCharMatch(const Mat &src, std::vector<Mat> &match, std::vector<CPlate>& out_plateVec_blue, std::vector<CPlate>& out_plateVec_yellow, std::vector<CPlate>& out_plateVec_green,
|
||||
bool usePlateMser, std::vector<RotatedRect>& out_plateRRect_blue, std::vector<RotatedRect>& out_plateRRect_yellow, std::vector<RotatedRect>& out_plateRRect_green, int index = 0, bool showDebug = false);
|
||||
|
||||
// computer the insert over union about two rrect
|
||||
bool computeIOU(const RotatedRect& rrect1, const RotatedRect& rrect2, const int width, const int height, const float thresh, float& result);
|
||||
float computeIOU(const RotatedRect& rrect1, const RotatedRect& rrect2, const int width, const int height);
|
||||
|
||||
bool computeIOU(const Rect& rect1, const Rect& rect2, const float thresh, float& result);
|
||||
float computeIOU(const Rect& rect1, const Rect& rect2);
|
||||
|
||||
/** @brief convert form mser point to image.
|
||||
|
||||
The function created first by Hailiang Xu.
|
||||
Modified by Ruoze Liu.
|
||||
|
||||
@param
|
||||
*/
|
||||
Mat adaptive_image_from_points(const std::vector<Point>& points,
|
||||
const Rect& rect, const Size& size, const Scalar& backgroundColor = Scalar(0, 0, 0),
|
||||
const Scalar& forgroundColor = Scalar(255, 255, 255), bool gray = true);
|
||||
|
||||
// Calculate a rect have same length and width and remains the center
|
||||
Rect adaptive_charrect_from_rect(const Rect& rect, int maxwidth, int maxheight, bool useExtendHeight = false);
|
||||
|
||||
// calc safe rect
|
||||
bool calcSafeRect(const RotatedRect& roi_rect, const Mat& src,
|
||||
Rect_<float>& safeBoundRect);
|
||||
bool calcSafeRect(const RotatedRect &roi_rect, const int width, const int height,
|
||||
Rect_<float> &safeBoundRect);
|
||||
|
||||
// uniform resize all the image to same size for the next process
|
||||
Mat uniformResize(const Mat &result, float& scale);
|
||||
|
||||
// uniform resize all the plates to same size for the next process
|
||||
Mat uniformResizePlates(const Mat &result, float& scale);
|
||||
|
||||
// show detect results
|
||||
void showDectectResults(const Mat& img, const std::vector<CPlate> &plateVec, size_t num);
|
||||
|
||||
// show the results
|
||||
Mat showResult(const Mat &result, int img_index = 0);
|
||||
|
||||
// enlarge the char rect
|
||||
Rect rectEnlarge(const Rect& src, const int mat_width, const int mat_height);
|
||||
Rect rectFit(const Rect &src, const int mat_width, const int mat_height);
|
||||
|
||||
// write images to temp folder
|
||||
void writeTempImage(const Mat& outImg, const string path, int index = 0);
|
||||
|
||||
// remove small hor lines in the plate
|
||||
bool judegMDOratio2(const Mat &image, const Rect &rect, std::vector<Point> &contour, Mat &result, const float thresh = 1.f,
|
||||
bool useExtendHeight = false);
|
||||
|
||||
// clear top and bottom borders
|
||||
void clearBorder(const Mat &img, Rect& cropRect);
|
||||
|
||||
//! non-maximum surpresion for 1d array
|
||||
template<typename T>
|
||||
void NMSfor1D(const vector<T>& arr, vector<int>& index) {
|
||||
// prepare
|
||||
int size = (int)arr.size();
|
||||
index.resize(size);
|
||||
for (int j = 0; j < size; j++)
|
||||
index.at(j) = 0;
|
||||
|
||||
// nms
|
||||
int i = 1;
|
||||
while (i < size - 1) {
|
||||
if (arr.at(i) > arr.at(i + 1)) {
|
||||
if (arr.at(i) >= arr.at(i - 1))
|
||||
index.at(i) = 1;
|
||||
}
|
||||
else {
|
||||
while (i < size - 1 && arr.at(i) <= arr.at(i + 1))
|
||||
i = i + 1;
|
||||
if (i < size - 1)
|
||||
index.at(i) = 1;
|
||||
}
|
||||
i = i + 2;
|
||||
}
|
||||
}
|
||||
|
||||
} /*! \namespace easypr*/
|
||||
|
||||
#endif // EASYPR_CORE_COREFUNC_H_
|
||||
@ -0,0 +1,59 @@
|
||||
#ifndef EASYPR_CORE_FEATURE_H_
|
||||
#define EASYPR_CORE_FEATURE_H_
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
namespace easypr {
|
||||
|
||||
//! 获得车牌的特征数
|
||||
cv::Mat getHistogram(cv::Mat in);
|
||||
|
||||
//! EasyPR的getFeatures回调函数
|
||||
//! 用于从车牌的image生成svm的训练特征features
|
||||
typedef void (*svmCallback)(const cv::Mat& image, cv::Mat& features);
|
||||
|
||||
//! EasyPR的getFeatures回调函数
|
||||
//! convert from images to features used by gray char ann
|
||||
typedef void (*annCallback)(const cv::Mat& image, cv::Mat& features);
|
||||
|
||||
//! gray and project feature
|
||||
void getGrayPlusProject(const cv::Mat& grayChar, cv::Mat& features);
|
||||
|
||||
//! EasyPR的getFeatures回调函数
|
||||
//! 本函数是获取垂直和水平的直方图图值
|
||||
void getHistogramFeatures(const cv::Mat& image, cv::Mat& features);
|
||||
|
||||
//! 本函数是获取SIFT特征子
|
||||
void getSIFTFeatures(const cv::Mat& image, cv::Mat& features);
|
||||
|
||||
//! 本函数是获取HOG特征子
|
||||
void getHOGFeatures(const cv::Mat& image, cv::Mat& features);
|
||||
|
||||
//! 本函数是获取HSV空间量化的直方图特征子
|
||||
void getHSVHistFeatures(const cv::Mat& image, cv::Mat& features);
|
||||
|
||||
//! LBP feature
|
||||
void getLBPFeatures(const cv::Mat& image, cv::Mat& features);
|
||||
|
||||
//! color feature
|
||||
void getColorFeatures(const cv::Mat& src, cv::Mat& features);
|
||||
|
||||
//! color feature and histom
|
||||
void getHistomPlusColoFeatures(const cv::Mat& image, cv::Mat& features);
|
||||
|
||||
//! get character feature
|
||||
cv::Mat charFeatures(cv::Mat in, int sizeData);
|
||||
cv::Mat charFeatures2(cv::Mat in, int sizeData);
|
||||
|
||||
//! LBP feature + Histom feature
|
||||
void getLBPplusHistFeatures(const cv::Mat& image, cv::Mat& features);
|
||||
|
||||
//! grayChar feauter
|
||||
void getGrayCharFeatures(const cv::Mat& grayChar, cv::Mat& features);
|
||||
|
||||
void getGrayPlusLBP(const Mat& grayChar, Mat& features);
|
||||
} /*! \namespace easypr*/
|
||||
|
||||
#endif // EASYPR_CORE_FEATURE_H_
|
||||
@ -0,0 +1,96 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name: params Header
|
||||
// Version: 1.0
|
||||
// Date: 2016-07-01
|
||||
// Author: liuruoze
|
||||
// Copyright: liuruoze
|
||||
// Desciption:
|
||||
// An abstract class for runtime algorithm params in easypr.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#ifndef EASYPR_CORE_PARAMS_H_
|
||||
#define EASYPR_CORE_PARAMS_H_
|
||||
|
||||
/*! \namespace easypr
|
||||
Namespace where all the C++ EasyPR functionality resides
|
||||
*/
|
||||
namespace easypr {
|
||||
|
||||
class CParams {
|
||||
public:
|
||||
static CParams* instance();
|
||||
|
||||
CParams(const CParams& other) {
|
||||
m_isUpdate = other.m_isUpdate;
|
||||
|
||||
m_param1f = other.m_param1f;
|
||||
m_param2f = other.m_param2f;
|
||||
m_param3f = other.m_param3f;
|
||||
|
||||
m_param1i = other.m_param1i;
|
||||
m_param2i = other.m_param2i;
|
||||
m_param3i = other.m_param3i;
|
||||
|
||||
m_param1b = other.m_param1b;
|
||||
m_param2b = other.m_param2b;
|
||||
m_param3b = other.m_param3b;
|
||||
}
|
||||
|
||||
inline void setIsUpdate(bool param) { m_isUpdate = param; }
|
||||
inline bool getIsUpdate() const { return m_isUpdate; }
|
||||
|
||||
inline void setParam1f(float param) { m_param1f = param; }
|
||||
inline float getParam1f() const { return m_param1f; }
|
||||
|
||||
inline void setParam2f(float param) { m_param2f = param; }
|
||||
inline float getParam2f() const { return m_param2f; }
|
||||
|
||||
inline void setParam3f(float param) { m_param3f = param; }
|
||||
inline float getParam3f() const { return m_param3f; }
|
||||
|
||||
inline void setParam1i(int param) { m_param1i = param; }
|
||||
inline int getParam1i() const { return m_param1i; }
|
||||
|
||||
inline void setParam2i(int param) { m_param2i = param; }
|
||||
inline int getParam2i() const { return m_param2i; }
|
||||
|
||||
inline void setParam3i(int param) { m_param3i = param; }
|
||||
inline int getParam3i() const { return m_param3i; }
|
||||
|
||||
inline void setParam1b(bool param) { m_param1b = param; }
|
||||
inline bool getParam1b() const { return m_param1b; }
|
||||
|
||||
inline void setParam2b(bool param) { m_param2b = param; }
|
||||
inline bool getParam2b() const { return m_param2b; }
|
||||
|
||||
inline void setParam3b(bool param) { m_param3b = param; }
|
||||
inline bool getParam3b() const { return m_param3b; }
|
||||
|
||||
private:
|
||||
CParams() {
|
||||
m_isUpdate = false;
|
||||
}
|
||||
|
||||
static CParams* instance_;
|
||||
|
||||
// weather update;
|
||||
bool m_isUpdate;
|
||||
|
||||
//! float params
|
||||
float m_param1f;
|
||||
float m_param2f;
|
||||
float m_param3f;
|
||||
|
||||
//! int params
|
||||
int m_param1i;
|
||||
int m_param2i;
|
||||
int m_param3i;
|
||||
|
||||
//! bool params
|
||||
bool m_param1b;
|
||||
bool m_param2b;
|
||||
bool m_param3b;
|
||||
};
|
||||
|
||||
} /*! \namespace easypr*/
|
||||
|
||||
#endif // EASYPR_CORE_PARAMS_H_
|
||||
@ -0,0 +1,194 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name: plate Header
|
||||
// Version: 1.0
|
||||
// Date: 2015-03-12
|
||||
// Author: liuruoze
|
||||
// Copyright: liuruoze
|
||||
// Desciption:
|
||||
// An abstract class for car plate.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#ifndef EASYPR_CORE_PLATE_H_
|
||||
#define EASYPR_CORE_PLATE_H_
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include "easypr/core/character.hpp"
|
||||
#include "easypr/config.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
|
||||
/*! \namespace easypr
|
||||
Namespace where all the C++ EasyPR functionality resides
|
||||
*/
|
||||
namespace easypr {
|
||||
|
||||
class CPlate {
|
||||
public:
|
||||
CPlate() {
|
||||
m_score = -1;
|
||||
m_plateStr = "";
|
||||
m_plateColor = UNKNOWN;
|
||||
}
|
||||
|
||||
CPlate(const CPlate& other) {
|
||||
m_plateMat = other.m_plateMat;
|
||||
m_chineseMat = other.m_chineseMat;
|
||||
m_chineseKey = other.m_chineseKey;
|
||||
m_score = other.m_score;
|
||||
m_platePos = other.m_platePos;
|
||||
m_plateStr = other.m_plateStr;
|
||||
m_locateType = other.m_locateType;
|
||||
m_plateColor = other.m_plateColor;
|
||||
m_line = other.m_line;
|
||||
m_leftPoint = other.m_leftPoint;
|
||||
m_rightPoint = other.m_rightPoint;
|
||||
m_mergeCharRect = other.m_mergeCharRect;
|
||||
m_maxCharRect = other.m_maxCharRect;
|
||||
m_scale = other.m_scale;
|
||||
m_distVec = other.m_distVec;
|
||||
|
||||
m_mserCharVec = other.m_mserCharVec;
|
||||
m_reutCharVec = other.m_reutCharVec;
|
||||
m_ostuLevel = other.m_ostuLevel;
|
||||
}
|
||||
|
||||
CPlate& operator=(const CPlate& other) {
|
||||
if (this != &other) {
|
||||
m_plateMat = other.m_plateMat;
|
||||
m_chineseMat = other.m_chineseMat;
|
||||
m_chineseKey = other.m_chineseKey;
|
||||
m_score = other.m_score;
|
||||
m_platePos = other.m_platePos;
|
||||
m_plateStr = other.m_plateStr;
|
||||
m_locateType = other.m_locateType;
|
||||
m_plateColor = other.m_plateColor;
|
||||
m_line = other.m_line;
|
||||
m_leftPoint = other.m_leftPoint;
|
||||
m_rightPoint = other.m_rightPoint;
|
||||
m_mergeCharRect = other.m_mergeCharRect;
|
||||
m_maxCharRect = other.m_maxCharRect;
|
||||
|
||||
m_distVec = other.m_distVec;
|
||||
|
||||
m_mserCharVec = other.m_mserCharVec;
|
||||
m_reutCharVec = other.m_reutCharVec;
|
||||
m_ostuLevel = other.m_ostuLevel;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void setPlateMat(Mat param) { m_plateMat = param; }
|
||||
inline Mat getPlateMat() const { return m_plateMat; }
|
||||
|
||||
inline void setChineseMat(Mat param) { m_chineseMat = param; }
|
||||
inline Mat getChineseMat() const { return m_chineseMat; }
|
||||
|
||||
inline void setChineseKey(String param) { m_chineseKey = param; }
|
||||
inline String getChineseKey() const { return m_chineseKey; }
|
||||
|
||||
inline void setPlatePos(RotatedRect param) { m_platePos = param; }
|
||||
inline RotatedRect getPlatePos() const { return m_platePos; }
|
||||
|
||||
inline void setPlateStr(String param) { m_plateStr = param; }
|
||||
inline String getPlateStr() const { return m_plateStr; }
|
||||
|
||||
inline void setPlateLocateType(LocateType param) { m_locateType = param; }
|
||||
inline LocateType getPlateLocateType() const { return m_locateType; }
|
||||
|
||||
inline void setPlateColor(Color param) { m_plateColor = param; }
|
||||
inline Color getPlateColor() const { return m_plateColor; }
|
||||
|
||||
inline void setPlateScale(float param) { m_scale = param; }
|
||||
inline float getPlateScale() const { return m_scale; }
|
||||
|
||||
inline void setPlateScore(double param) { m_score = param; }
|
||||
inline double getPlateScore() const { return m_score; }
|
||||
|
||||
inline void setPlateLine(Vec4f param) { m_line = param; }
|
||||
inline Vec4f getPlateLine() const { return m_line; }
|
||||
|
||||
inline void setPlateLeftPoint(Point param) { m_leftPoint = param; }
|
||||
inline Point getPlateLeftPoint() const { return m_leftPoint; }
|
||||
|
||||
inline void setPlateRightPoint(Point param) { m_rightPoint = param; }
|
||||
inline Point getPlateRightPoint() const { return m_rightPoint; }
|
||||
|
||||
inline void setPlateMergeCharRect(Rect param) { m_mergeCharRect = param; }
|
||||
inline Rect getPlateMergeCharRect() const { return m_mergeCharRect; }
|
||||
|
||||
inline void setPlateMaxCharRect(Rect param) { m_maxCharRect = param; }
|
||||
inline Rect getPlateMaxCharRect() const { return m_maxCharRect; }
|
||||
|
||||
inline void setPlatDistVec(Vec2i param) { m_distVec = param; }
|
||||
inline Vec2i getPlateDistVec() const { return m_distVec; }
|
||||
|
||||
inline void setOstuLevel(double param) { m_ostuLevel = param; }
|
||||
inline double getOstuLevel() const { return m_ostuLevel; }
|
||||
|
||||
inline void setMserCharacter(const std::vector<CCharacter>& param) { m_mserCharVec = param; }
|
||||
inline void addMserCharacter(CCharacter param) { m_mserCharVec.push_back(param); }
|
||||
inline std::vector<CCharacter> getCopyOfMserCharacters() { return m_mserCharVec; }
|
||||
|
||||
inline void setReutCharacter(const std::vector<CCharacter>& param) { m_reutCharVec = param; }
|
||||
inline void addReutCharacter(CCharacter param) { m_reutCharVec.push_back(param); }
|
||||
inline std::vector<CCharacter> getCopyOfReutCharacters() { return m_reutCharVec; }
|
||||
|
||||
bool operator < (const CPlate& plate) const { return (m_score < plate.m_score); }
|
||||
bool operator < (const CPlate& plate) { return (m_score < plate.m_score); }
|
||||
|
||||
private:
|
||||
//! plate mat
|
||||
Mat m_plateMat;
|
||||
|
||||
//! plate rect
|
||||
RotatedRect m_platePos;
|
||||
|
||||
//! plate license
|
||||
String m_plateStr;
|
||||
|
||||
//! plate locate type
|
||||
LocateType m_locateType;
|
||||
|
||||
//! plate color type
|
||||
Color m_plateColor;
|
||||
|
||||
//! scale ratio
|
||||
float m_scale;
|
||||
|
||||
//! plate likely
|
||||
double m_score;
|
||||
|
||||
//! avg ostu level
|
||||
double m_ostuLevel;
|
||||
|
||||
//! middle line
|
||||
Vec4f m_line;
|
||||
|
||||
//! left point and right point;
|
||||
Point m_leftPoint;
|
||||
Point m_rightPoint;
|
||||
|
||||
Rect m_mergeCharRect;
|
||||
Rect m_maxCharRect;
|
||||
|
||||
std::vector<CCharacter> m_mserCharVec;
|
||||
std::vector<CCharacter> m_slwdCharVec;
|
||||
|
||||
std::vector<CCharacter> m_ostuCharVec;
|
||||
std::vector<CCharacter> m_reutCharVec;
|
||||
|
||||
int m_charCount;
|
||||
|
||||
//! chinese mat;
|
||||
Mat m_chineseMat;
|
||||
|
||||
//! chinese key;
|
||||
String m_chineseKey;
|
||||
|
||||
//! distVec
|
||||
Vec2i m_distVec;
|
||||
};
|
||||
|
||||
} /*! \namespace easypr*/
|
||||
|
||||
#endif // EASYPR_CORE_PLATE_H_
|
||||
@ -0,0 +1,125 @@
|
||||
#ifndef EASYPR_CORE_PLATEDETECT_H_
|
||||
#define EASYPR_CORE_PLATEDETECT_H_
|
||||
|
||||
#include "easypr/core/plate_locate.h"
|
||||
#include "easypr/core/plate_judge.h"
|
||||
|
||||
namespace easypr {
|
||||
|
||||
class CPlateDetect {
|
||||
public:
|
||||
CPlateDetect();
|
||||
|
||||
~CPlateDetect();
|
||||
|
||||
/** @brief Plate detect in an image.
|
||||
|
||||
The function detects plate in an image. It can use sobel, color, and character method or the combinations of them.
|
||||
|
||||
@param src Source image.
|
||||
@param resultVec Destination vector of CPlate.
|
||||
@param type Detect type. (eg. PR_DETECT_SOBEL + PR_DETECT_COLOR)
|
||||
@param showDetectArea
|
||||
@param index
|
||||
*/
|
||||
int plateDetect(Mat src, std::vector<CPlate> &resultVec, int type,
|
||||
bool showDetectArea, int img_index = 0);
|
||||
|
||||
|
||||
/** @brief Plate detect in an image.
|
||||
|
||||
The function detects plate in an image. It can use sobel, color, and character method or the combinations of them.
|
||||
Use default m_type, it can use setDetectType() to set it;
|
||||
|
||||
@param src Source image.
|
||||
@param resultVec Destination vector of CPlate.
|
||||
@param index
|
||||
*/
|
||||
int plateDetect(Mat src, std::vector<CPlate> &resultVec, int img_index = 0);
|
||||
|
||||
void LoadSVM(std::string s);
|
||||
|
||||
inline void setPDLifemode(bool param) { m_plateLocate->setLifemode(param); }
|
||||
|
||||
inline void setPDDebug(bool param) {
|
||||
m_plateLocate->setDebug(param);
|
||||
setDetectShow(param);
|
||||
}
|
||||
|
||||
inline bool getPDDebug() { return m_plateLocate->getDebug(); }
|
||||
|
||||
inline void setDetectType(int param) { m_type = param; }
|
||||
|
||||
inline void setGaussianBlurSize(int param) {
|
||||
m_plateLocate->setGaussianBlurSize(param);
|
||||
}
|
||||
|
||||
inline int getGaussianBlurSize() const {
|
||||
return m_plateLocate->getGaussianBlurSize();
|
||||
}
|
||||
|
||||
inline void setMorphSizeWidth(int param) {
|
||||
m_plateLocate->setMorphSizeWidth(param);
|
||||
}
|
||||
|
||||
inline int getMorphSizeWidth() const {
|
||||
return m_plateLocate->getMorphSizeWidth();
|
||||
}
|
||||
|
||||
inline void setMorphSizeHeight(int param) {
|
||||
m_plateLocate->setMorphSizeHeight(param);
|
||||
}
|
||||
|
||||
inline int getMorphSizeHeight() const {
|
||||
return m_plateLocate->getMorphSizeHeight();
|
||||
}
|
||||
|
||||
inline void setVerifyError(float param) {
|
||||
m_plateLocate->setVerifyError(param);
|
||||
}
|
||||
|
||||
inline float getVerifyError() const {
|
||||
return m_plateLocate->getVerifyError();
|
||||
}
|
||||
|
||||
inline void setVerifyAspect(float param) {
|
||||
m_plateLocate->setVerifyAspect(param);
|
||||
}
|
||||
|
||||
inline float getVerifyAspect() const {
|
||||
return m_plateLocate->getVerifyAspect();
|
||||
}
|
||||
|
||||
inline void setVerifyMin(int param) { m_plateLocate->setVerifyMin(param); }
|
||||
|
||||
inline void setVerifyMax(int param) { m_plateLocate->setVerifyMax(param); }
|
||||
|
||||
inline void setJudgeAngle(int param) { m_plateLocate->setJudgeAngle(param); }
|
||||
|
||||
inline void setMaxPlates(int param) { m_maxPlates = param; }
|
||||
|
||||
inline int getMaxPlates() const { return m_maxPlates; }
|
||||
|
||||
inline void setDetectShow(bool param) { m_showDetect = param; }
|
||||
inline bool getDetectShow() const { return m_showDetect; }
|
||||
|
||||
private:
|
||||
|
||||
int m_maxPlates;
|
||||
|
||||
//SceneMode m_mode;
|
||||
|
||||
CPlateLocate* m_plateLocate;
|
||||
|
||||
int m_type;
|
||||
|
||||
static std::string m_pathSvm;
|
||||
|
||||
// show the detect result image
|
||||
bool m_showDetect;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // EASYPR_CORE_PLATEDETECT_H_
|
||||
@ -0,0 +1,36 @@
|
||||
#ifndef EASYPR_CORE_PLATEJUDGE_H_
|
||||
#define EASYPR_CORE_PLATEJUDGE_H_
|
||||
|
||||
#include "easypr/core/plate.hpp"
|
||||
#include "easypr/core/feature.h"
|
||||
|
||||
namespace easypr {
|
||||
|
||||
class PlateJudge {
|
||||
public:
|
||||
static PlateJudge* instance();
|
||||
void LoadModel(std::string path);
|
||||
|
||||
int plateJudgeUsingNMS(const std::vector<CPlate>&, std::vector<CPlate>&, int maxPlates = 5);
|
||||
int plateSetScore(CPlate& plate);
|
||||
|
||||
int plateJudge(const Mat& plateMat);
|
||||
int plateJudge(const std::vector<Mat> &inVec,
|
||||
std::vector<Mat> &resultVec);
|
||||
int plateJudge(const std::vector<CPlate> &inVec,
|
||||
std::vector<CPlate> &resultVec);
|
||||
|
||||
private:
|
||||
// singleton
|
||||
PlateJudge();
|
||||
|
||||
static PlateJudge* instance_;
|
||||
|
||||
svmCallback extractFeature;
|
||||
|
||||
cv::Ptr<ml::SVM> svm_;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EASYPR_CORE_PLATEJUDGE_H_
|
||||
@ -0,0 +1,141 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name: plate_locate Header
|
||||
// Version: 1.2
|
||||
// Date: 2014-09-19
|
||||
// MDate: 2014-09-29
|
||||
// MDate: 2015-03-13
|
||||
// Author: liuruoze
|
||||
// Copyright: liuruoze
|
||||
// Reference: Mastering OpenCV with Practical Computer Vision Projects
|
||||
// Reference: CSDN Bloger taotao1233
|
||||
// Desciption:
|
||||
// Defines CPlateLocate
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#ifndef EASYPR_CORE_PLATELOCATE_H_
|
||||
#define EASYPR_CORE_PLATELOCATE_H_
|
||||
|
||||
#include "easypr/core/plate.hpp"
|
||||
|
||||
/*! \namespace easypr
|
||||
Namespace where all the C++ EasyPR functionality resides
|
||||
*/
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace easypr {
|
||||
|
||||
class CPlateLocate {
|
||||
public:
|
||||
CPlateLocate();
|
||||
|
||||
int sobelFrtSearch(const Mat& src, std::vector<Rect_<float>>& outRects);
|
||||
int sobelSecSearch(Mat& bound, Point2f refpoint,
|
||||
std::vector<RotatedRect>& outRects);
|
||||
int sobelSecSearchPart(Mat& bound, Point2f refpoint,
|
||||
std::vector<RotatedRect>& outRects);
|
||||
|
||||
int deskew(const Mat& src, const Mat& src_b,
|
||||
std::vector<RotatedRect>& inRects, std::vector<CPlate>& outPlates,
|
||||
bool useDeteleArea = true, Color color = UNKNOWN);
|
||||
|
||||
bool isdeflection(const Mat& in, const double angle, double& slope);
|
||||
|
||||
int sobelOper(const Mat& in, Mat& out, int blurSize, int morphW, int morphH);
|
||||
|
||||
|
||||
bool rotation(Mat& in, Mat& out, const Size rect_size, const Point2f center,
|
||||
const double angle);
|
||||
|
||||
void affine(const Mat& in, Mat& out, const double slope);
|
||||
|
||||
int plateColorLocate(Mat src, std::vector<CPlate>& candPlates, int index = 0);
|
||||
int plateSobelLocate(Mat src, std::vector<CPlate>& candPlates, int index = 0);
|
||||
int sobelOperT(const Mat& in, Mat& out, int blurSize, int morphW, int morphH);
|
||||
|
||||
int plateMserLocate(Mat src, std::vector<CPlate>& candPlates, int index = 0);
|
||||
|
||||
|
||||
int colorSearch(const Mat& src, const Color r, Mat& out,
|
||||
std::vector<RotatedRect>& outRects);
|
||||
|
||||
int mserSearch(const Mat &src, vector<Mat>& out,
|
||||
vector<vector<CPlate>>& out_plateVec, bool usePlateMser, vector<vector<RotatedRect>>& out_plateRRect,
|
||||
int img_index = 0, bool showDebug = false);
|
||||
|
||||
int plateLocate(Mat, std::vector<Mat>&, int = 0);
|
||||
int plateLocate(Mat, std::vector<CPlate>&, int = 0);
|
||||
|
||||
bool verifySizes(RotatedRect mr);
|
||||
|
||||
void setLifemode(bool param);
|
||||
|
||||
inline void setGaussianBlurSize(int param) { m_GaussianBlurSize = param; }
|
||||
inline int getGaussianBlurSize() const { return m_GaussianBlurSize; }
|
||||
|
||||
inline void setMorphSizeWidth(int param) { m_MorphSizeWidth = param; }
|
||||
inline int getMorphSizeWidth() const { return m_MorphSizeWidth; }
|
||||
|
||||
inline void setMorphSizeHeight(int param) { m_MorphSizeHeight = param; }
|
||||
inline int getMorphSizeHeight() const { return m_MorphSizeHeight; }
|
||||
|
||||
inline void setVerifyError(float param) { m_error = param; }
|
||||
inline float getVerifyError() const { return m_error; }
|
||||
inline void setVerifyAspect(float param) { m_aspect = param; }
|
||||
inline float getVerifyAspect() const { return m_aspect; }
|
||||
|
||||
inline void setVerifyMin(int param) { m_verifyMin = param; }
|
||||
inline void setVerifyMax(int param) { m_verifyMax = param; }
|
||||
|
||||
inline void setJudgeAngle(int param) { m_angle = param; }
|
||||
|
||||
inline void setDebug(bool param) { m_debug = param; }
|
||||
|
||||
|
||||
inline bool getDebug() { return m_debug; }
|
||||
|
||||
|
||||
static const int DEFAULT_GAUSSIANBLUR_SIZE = 5;
|
||||
static const int SOBEL_SCALE = 1;
|
||||
static const int SOBEL_DELTA = 0;
|
||||
static const int SOBEL_DDEPTH = CV_16S;
|
||||
static const int SOBEL_X_WEIGHT = 1;
|
||||
static const int SOBEL_Y_WEIGHT = 0;
|
||||
static const int DEFAULT_MORPH_SIZE_WIDTH = 17; // 17
|
||||
static const int DEFAULT_MORPH_SIZE_HEIGHT = 3; // 3
|
||||
|
||||
|
||||
static const int WIDTH = 136;
|
||||
static const int HEIGHT = 36;
|
||||
static const int TYPE = CV_8UC3;
|
||||
|
||||
|
||||
static const int DEFAULT_VERIFY_MIN = 1; // 3
|
||||
static const int DEFAULT_VERIFY_MAX = 24; // 20
|
||||
|
||||
static const int DEFAULT_ANGLE = 60; // 30
|
||||
|
||||
|
||||
static const int DEFAULT_DEBUG = 1;
|
||||
|
||||
protected:
|
||||
|
||||
int m_GaussianBlurSize;
|
||||
|
||||
int m_MorphSizeWidth;
|
||||
int m_MorphSizeHeight;
|
||||
|
||||
|
||||
float m_error;
|
||||
float m_aspect;
|
||||
int m_verifyMin;
|
||||
int m_verifyMax;
|
||||
|
||||
int m_angle;
|
||||
|
||||
|
||||
bool m_debug;
|
||||
};
|
||||
|
||||
} /*! \namespace easypr*/
|
||||
|
||||
#endif // EASYPR_CORE_PLATELOCATE_H_
|
||||
@ -0,0 +1,54 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name: plate_recognize Header
|
||||
// Version: 1.0
|
||||
// Date: 2014-09-28
|
||||
// Author: liuruoze
|
||||
// Copyright: liuruoze
|
||||
// Reference: Mastering OpenCV with Practical Computer Vision Projects
|
||||
// Reference: CSDN Bloger taotao1233
|
||||
// Desciption:
|
||||
// Defines CPlateRecognize
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#ifndef EASYPR_CORE_PLATERECOGNIZE_H_
|
||||
#define EASYPR_CORE_PLATERECOGNIZE_H_
|
||||
|
||||
#include "easypr/core/plate_detect.h"
|
||||
#include "easypr/core/chars_recognise.h"
|
||||
|
||||
/*! \namespace easypr
|
||||
Namespace where all the C++ EasyPR functionality resides
|
||||
*/
|
||||
namespace easypr {
|
||||
|
||||
class CPlateRecognize : public CPlateDetect, public CCharsRecognise {
|
||||
public:
|
||||
CPlateRecognize();
|
||||
|
||||
int plateRecognize(const Mat& src, std::vector<CPlate> &plateVec, int img_index = 0);
|
||||
int plateRecognize(const Mat& src, std::vector<std::string> &licenseVec);
|
||||
|
||||
inline void setLifemode(bool param) { CPlateDetect::setPDLifemode(param); }
|
||||
inline void setDetectType(int param) { CPlateDetect::setDetectType(param); }
|
||||
|
||||
inline void setResultShow(bool param) { m_showResult = param; }
|
||||
inline bool getResultShow() const { return m_showResult; }
|
||||
inline void setDetectShow(bool param) { CPlateDetect::setDetectShow(param); }
|
||||
inline void setDebug(bool param) { setResultShow(param); }
|
||||
|
||||
void LoadSVM(std::string path);
|
||||
void LoadANN(std::string path);
|
||||
void LoadChineseANN(std::string path);
|
||||
|
||||
//v1.6 added
|
||||
void LoadGrayChANN(std::string path);
|
||||
void LoadChineseMapping(std::string path);
|
||||
|
||||
private:
|
||||
// show the detect and recognition result image
|
||||
bool m_showResult;
|
||||
DISABLE_ASSIGN_AND_COPY(CPlateRecognize);
|
||||
};
|
||||
|
||||
} /* \namespace easypr */
|
||||
|
||||
#endif // EASYPR_CORE_PLATERECOGNIZE_H_
|
||||
@ -0,0 +1,43 @@
|
||||
#ifndef EASYPR_TRAIN_ANNCHTRAIN_H_
|
||||
#define EASYPR_TRAIN_ANNCHTRAIN_H_
|
||||
|
||||
#include "easypr/train/train.h"
|
||||
#include "easypr/util/kv.h"
|
||||
#include "easypr/core/feature.h"
|
||||
#include <memory>
|
||||
|
||||
namespace easypr {
|
||||
|
||||
class AnnChTrain : public ITrain {
|
||||
public:
|
||||
explicit AnnChTrain(const char* chars_folder, const char* xml);
|
||||
|
||||
virtual void train();
|
||||
|
||||
virtual void test();
|
||||
|
||||
std::pair<std::string, std::string> identifyGrayChinese(cv::Mat input);
|
||||
|
||||
inline void setNumberForCount(int n) {
|
||||
m_number_for_count = n;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual cv::Ptr<cv::ml::TrainData> tdata();
|
||||
|
||||
void trainVal(size_t number_for_count = 100);
|
||||
|
||||
cv::Ptr<cv::ml::ANN_MLP> ann_;
|
||||
const char* ann_xml_;
|
||||
const char* chars_folder_;
|
||||
|
||||
std::shared_ptr<Kv> kv_;
|
||||
int type;
|
||||
|
||||
int m_number_for_count;
|
||||
|
||||
annCallback extractFeature;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EASYPR_TRAIN_ANNCHTRAIN_H_
|
||||
@ -0,0 +1,35 @@
|
||||
#ifndef EASYPR_TRAIN_ANNTRAIN_H_
|
||||
#define EASYPR_TRAIN_ANNTRAIN_H_
|
||||
|
||||
#include "easypr/train/train.h"
|
||||
#include "easypr/util/kv.h"
|
||||
#include <memory>
|
||||
|
||||
namespace easypr {
|
||||
|
||||
class AnnTrain : public ITrain {
|
||||
public:
|
||||
explicit AnnTrain(const char* chars_folder, const char* xml);
|
||||
|
||||
virtual void train();
|
||||
|
||||
virtual void test();
|
||||
|
||||
std::pair<std::string, std::string> identifyChinese(cv::Mat input);
|
||||
std::pair<std::string, std::string> identify(cv::Mat input);
|
||||
|
||||
private:
|
||||
virtual cv::Ptr<cv::ml::TrainData> tdata();
|
||||
|
||||
cv::Ptr<cv::ml::TrainData> sdata(size_t number_for_count = 100);
|
||||
|
||||
cv::Ptr<cv::ml::ANN_MLP> ann_;
|
||||
const char* ann_xml_;
|
||||
const char* chars_folder_;
|
||||
|
||||
std::shared_ptr<Kv> kv_;
|
||||
int type;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EASYPR_TRAIN_ANNTRAIN_H_
|
||||
@ -0,0 +1,27 @@
|
||||
#ifndef EASYPR_CREATE_DATA_H_
|
||||
#define EASYPR_CREATE_DATA_H_
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include "easypr/config.h"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
/*! \namespace easypr
|
||||
Namespace where all the C++ EasyPR functionality resides
|
||||
*/
|
||||
namespace easypr {
|
||||
|
||||
// shift an image
|
||||
Mat translateImg(Mat img, int offsetx, int offsety, int bk = 0);
|
||||
// rotate an image
|
||||
Mat rotateImg(Mat source, float angle, int bk = 0);
|
||||
|
||||
// crop the image
|
||||
Mat cropImg(Mat src, int x, int y, int shift, int bk = 0);
|
||||
|
||||
Mat generateSyntheticImage(const Mat& image, int use_swap = 1);
|
||||
|
||||
} /*! \namespace easypr*/
|
||||
|
||||
#endif // EASYPR_CREATE_DATA_H_
|
||||
@ -0,0 +1,42 @@
|
||||
#ifndef EASYPR_TRAIN_SVMTRAIN_H_
|
||||
#define EASYPR_TRAIN_SVMTRAIN_H_
|
||||
|
||||
#include "easypr/train/train.h"
|
||||
#include <vector>
|
||||
#include "easypr/config.h"
|
||||
#include "easypr/core/feature.h"
|
||||
|
||||
namespace easypr {
|
||||
|
||||
//int svmTrain(bool dividePrepared, bool trainPrepared);
|
||||
|
||||
class SvmTrain : public ITrain {
|
||||
public:
|
||||
typedef struct {
|
||||
std::string file;
|
||||
SvmLabel label;
|
||||
} TrainItem;
|
||||
|
||||
SvmTrain(const char* plates_folder, const char* xml);
|
||||
|
||||
virtual void train();
|
||||
|
||||
virtual void test();
|
||||
|
||||
private:
|
||||
void prepare();
|
||||
|
||||
virtual cv::Ptr<cv::ml::TrainData> tdata();
|
||||
|
||||
cv::Ptr<cv::ml::SVM> svm_;
|
||||
const char* plates_folder_;
|
||||
const char* svm_xml_;
|
||||
std::vector<TrainItem> train_file_list_;
|
||||
std::vector<TrainItem> test_file_list_;
|
||||
|
||||
svmCallback extractFeature;
|
||||
bool isPrepared = true;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EASYPR_TRAIN_SVMTRAIN_H_
|
||||
@ -0,0 +1,23 @@
|
||||
#ifndef EASYPR_TRAIN_TRAIN_H_
|
||||
#define EASYPR_TRAIN_TRAIN_H_
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
namespace easypr {
|
||||
|
||||
class ITrain {
|
||||
public:
|
||||
ITrain();
|
||||
|
||||
virtual ~ITrain();
|
||||
|
||||
virtual void train() = 0;
|
||||
|
||||
virtual void test() = 0;
|
||||
|
||||
private:
|
||||
virtual cv::Ptr<cv::ml::TrainData> tdata() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EASYPR_TRAIN_TRAIN_H_
|
||||
@ -0,0 +1,29 @@
|
||||
#ifndef EASYPR_UTIL_KV_H_
|
||||
#define EASYPR_UTIL_KV_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace easypr {
|
||||
|
||||
class Kv {
|
||||
public:
|
||||
Kv();
|
||||
|
||||
void load(const std::string &file);
|
||||
|
||||
std::string get(const std::string &key);
|
||||
|
||||
void add(const std::string &key, const std::string &value);
|
||||
|
||||
void remove(const std::string &key);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> data_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // EASYPR_UTIL_KV_H_
|
||||
@ -0,0 +1,356 @@
|
||||
/***********************
|
||||
* This file is a packed library of
|
||||
* ProgramOptions(http://github.com/Micooz/ProgramOptions).
|
||||
* ProgramOptions is a library for generating and parsing command line.
|
||||
***********************/
|
||||
|
||||
#ifndef UTIL_PROGRAM_OPTIONS_H
|
||||
#define UTIL_PROGRAM_OPTIONS_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <initializer_list>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DEPRECATED(func) func __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
#define DEPRECATED(func) __declspec(deprecated) func
|
||||
#endif
|
||||
|
||||
namespace program_options {
|
||||
|
||||
class Row {
|
||||
public:
|
||||
Row();
|
||||
|
||||
enum Field { kShort, kLong, kDefault, kDescription };
|
||||
|
||||
typedef std::initializer_list<Field> Order;
|
||||
|
||||
// getter
|
||||
|
||||
inline std::string oshort() const { return option_short; }
|
||||
|
||||
inline std::string olong() const { return option_long; }
|
||||
|
||||
inline std::string value() const { return default_value; }
|
||||
|
||||
inline std::string desc() const { return description; }
|
||||
|
||||
inline bool required() const { return require_value; }
|
||||
|
||||
// setter
|
||||
|
||||
inline void oshort(const std::string& oshort) { option_short = oshort; }
|
||||
|
||||
inline void olong(const std::string& olong) { option_long = olong; }
|
||||
|
||||
inline void value(const std::string& value) { default_value = value; }
|
||||
|
||||
inline void desc(const std::string& desc) { description = desc; }
|
||||
|
||||
inline void required(bool required) { require_value = required; }
|
||||
|
||||
private:
|
||||
bool require_value;
|
||||
std::string option_short;
|
||||
std::string option_long;
|
||||
std::string default_value;
|
||||
std::string description;
|
||||
};
|
||||
|
||||
class Subroutine {
|
||||
public:
|
||||
typedef std::vector<Row> Usages;
|
||||
typedef std::initializer_list<const char*> TemplateValue;
|
||||
typedef std::vector<TemplateValue> TemplateValues;
|
||||
|
||||
Subroutine();
|
||||
|
||||
Subroutine(const char* name, const char* description);
|
||||
|
||||
inline void add_usage_line(const Row& row) { usages_.push_back(row); }
|
||||
|
||||
inline void add_usage_line(const TemplateValue& row) {
|
||||
templates_.push_back(row);
|
||||
}
|
||||
|
||||
inline void set_first_line(const char* line) { first_line_ = line; }
|
||||
|
||||
inline void set_description(const char* desc) { description_ = desc; }
|
||||
|
||||
inline void set_template(const char* tstr, const Row::Order& order) {
|
||||
template_str_ = tstr;
|
||||
order_ = order;
|
||||
}
|
||||
|
||||
// getters
|
||||
|
||||
inline std::string to_string() {
|
||||
std::stringstream ss;
|
||||
ss << *this;
|
||||
return std::move(ss.str());
|
||||
}
|
||||
|
||||
inline std::string get_name() const { return name_; }
|
||||
|
||||
inline const char* get_description() const { return description_; }
|
||||
|
||||
inline const char* get_first_line() const { return first_line_; }
|
||||
|
||||
inline Usages::iterator begin() { return usages_.begin(); }
|
||||
|
||||
inline Usages::iterator end() { return usages_.end(); }
|
||||
|
||||
inline size_t size() { return usages_.size(); }
|
||||
|
||||
inline Row& at(size_t i) { return usages_.at(i); }
|
||||
|
||||
inline const Usages& get_usage() const { return usages_; }
|
||||
|
||||
inline static const char* get_default_name() { return "EmptySubroutine"; }
|
||||
|
||||
private:
|
||||
friend std::ostream& operator<<(std::ostream& out, Subroutine& subroutine);
|
||||
|
||||
void print_with_row(std::ostream& out);
|
||||
|
||||
void print_with_template(std::ostream& out);
|
||||
|
||||
Usages usages_;
|
||||
TemplateValues templates_;
|
||||
const char* first_line_;
|
||||
const char* description_;
|
||||
std::string name_;
|
||||
std::string template_str_;
|
||||
Row::Order order_;
|
||||
};
|
||||
|
||||
class Parser;
|
||||
|
||||
class Generator {
|
||||
public:
|
||||
typedef std::map<std::string, Subroutine*> SubroutineCollection;
|
||||
|
||||
Generator();
|
||||
|
||||
~Generator();
|
||||
|
||||
// begin a new usage generate process and
|
||||
// create the first line that you will see in the result.
|
||||
// if you don't want to create the first line,
|
||||
// it's ok to create your usage lines without calling make_usage() first.
|
||||
Generator& make_usage(const char* first_line);
|
||||
|
||||
Parser* make_parser();
|
||||
|
||||
// generate usage lines for a subroutine.
|
||||
Generator& add_subroutine(const char* name);
|
||||
|
||||
Generator& add_subroutine(const char* name, const char* description);
|
||||
|
||||
// get pairs of subroutine name and its description.
|
||||
std::map<std::string, std::string> get_subroutine_list();
|
||||
|
||||
// generate and return the result as std::string
|
||||
inline std::string to_string() {
|
||||
std::stringstream ss;
|
||||
ss << *this;
|
||||
return std::move(ss.str());
|
||||
}
|
||||
|
||||
// add an usage line, it doesn't require a value
|
||||
inline Generator& operator()(const char* option, const char* description) {
|
||||
this->add_usage_line(option, "", description);
|
||||
(get_subroutine()->end() - 1)->required(false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// add an usage line, it requires a value(may has a default value)
|
||||
inline Generator& operator()(const char* option, const char* default_value,
|
||||
const char* description) {
|
||||
this->add_usage_line(option, default_value, description);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// this method is for subroutine usage printing.
|
||||
// e.g., cout << generator("subroutine_name");
|
||||
inline Subroutine& operator()(const char* name) {
|
||||
assert(subroutines_.find(name) != subroutines_.end());
|
||||
return *subroutines_.at(name);
|
||||
}
|
||||
|
||||
inline Generator& make_template(const char* template_str,
|
||||
const Row::Order& order) {
|
||||
get_subroutine()->set_template(template_str, order);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
inline Subroutine* get_subroutine() {
|
||||
return subroutines_.at(current_subroutine_);
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, Generator& generator);
|
||||
|
||||
// add a usage line.
|
||||
// if delimiter doesn't exist, return false
|
||||
bool add_usage_line(const char* option, const char* default_value,
|
||||
const char* description);
|
||||
|
||||
const char kDelimiter = ',';
|
||||
SubroutineCollection subroutines_;
|
||||
std::string current_subroutine_;
|
||||
Parser* parser_;
|
||||
};
|
||||
|
||||
class ParseError : public std::exception {
|
||||
public:
|
||||
explicit ParseError(const std::string& msg);
|
||||
|
||||
const char* what() const throw();
|
||||
|
||||
~ParseError() throw();
|
||||
|
||||
private:
|
||||
std::string _msg;
|
||||
};
|
||||
|
||||
class ParseItem {
|
||||
public:
|
||||
ParseItem(const std::string& value);
|
||||
|
||||
/*
|
||||
* dynamic type cast, support base data types including std::string
|
||||
*/
|
||||
template <typename T>
|
||||
T as() {
|
||||
T r;
|
||||
std::stringstream buf;
|
||||
buf << value_;
|
||||
buf >> r;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* alias of as<std::string>()
|
||||
*/
|
||||
inline std::string val() const { return value_; }
|
||||
|
||||
/*
|
||||
* get C string directly
|
||||
*/
|
||||
inline const char* c_str() const { return value_.c_str(); }
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
typedef std::vector<std::string> ParameterList;
|
||||
typedef std::map<std::string, ParseItem*> ParseResult;
|
||||
|
||||
Parser();
|
||||
|
||||
/*
|
||||
* release memory allocated in parse()
|
||||
*/
|
||||
~Parser();
|
||||
|
||||
/*
|
||||
* parse the command line by given argc and argv
|
||||
*/
|
||||
ParseResult* parse(const int argc, const char** argv);
|
||||
|
||||
/*
|
||||
* parse the command line by given command string
|
||||
*/
|
||||
ParseResult* parse(const char* command_line);
|
||||
|
||||
/*
|
||||
* check whether a certain option exist
|
||||
*/
|
||||
bool has(const char* key);
|
||||
|
||||
/*
|
||||
* check whether a sequence of options exist
|
||||
* example: has_or(3, "he", "or", "she");
|
||||
*/
|
||||
DEPRECATED(bool has_or(int n, ...)) {
|
||||
va_list keys;
|
||||
va_start(keys, n);
|
||||
while (n--) {
|
||||
const char* key = va_arg(keys, const char*);
|
||||
if (this->has(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
va_end(keys);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* check whether a sequence of options exist
|
||||
* example: has_and(3, "he", "and", "she");
|
||||
*/
|
||||
DEPRECATED(bool has_and(int n, ...)) {
|
||||
va_list keys;
|
||||
va_start(keys, n);
|
||||
while (n--) {
|
||||
const char* key = va_arg(keys, const char*);
|
||||
if (!this->has(key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
va_end(keys);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* check whether a sequence of options exist using std::initializer_list
|
||||
* example: has_or({"he", "or", "she"});
|
||||
*/
|
||||
bool has_or(std::initializer_list<const char*> options);
|
||||
|
||||
/*
|
||||
* check whether a sequence of options exist using std::initializer_list
|
||||
* example: has_and({"he", "and", "she"});
|
||||
*/
|
||||
bool has_and(std::initializer_list<const char*> options);
|
||||
|
||||
/*
|
||||
* get the specified option value
|
||||
*/
|
||||
ParseItem* get(const std::string& key);
|
||||
|
||||
inline void set_usage_subroutines(
|
||||
const Generator::SubroutineCollection* subroutines) {
|
||||
subroutines_ = subroutines;
|
||||
}
|
||||
|
||||
inline std::string get_subroutine_name() const { return subroutine_name_; }
|
||||
|
||||
private:
|
||||
bool init(const int argc, const char** argv);
|
||||
|
||||
void cleanup();
|
||||
|
||||
void set_addition();
|
||||
|
||||
const Generator::SubroutineCollection* subroutines_;
|
||||
std::string subroutine_name_;
|
||||
int argc_;
|
||||
ParameterList args_;
|
||||
ParseResult* pr_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // UTIL_PROGRAM_OPTIONS_H
|
||||
@ -0,0 +1,99 @@
|
||||
#ifndef PROGRAM_OPTIONS_SWITCH_HPP_
|
||||
#define PROGRAM_OPTIONS_SWITCH_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
namespace program_options {
|
||||
|
||||
/**
|
||||
* @brief The Switch template class.
|
||||
* @param Ty The target type.
|
||||
*/
|
||||
template <typename Ty>
|
||||
class Switch {
|
||||
public:
|
||||
typedef std::function<void(void)> Scope;
|
||||
typedef std::map<const Ty, Scope> Reflections;
|
||||
|
||||
Switch() : has_others_scope_(false) {}
|
||||
|
||||
explicit Switch(const Ty& target)
|
||||
: target_(target), has_others_scope_(false) {}
|
||||
|
||||
/**
|
||||
* @brief Create a case block with an expression and a callback function.
|
||||
* @param _case The case expression, variable is allowed.
|
||||
* @param callback The callback function, can be a lambda expression.
|
||||
* @return The current Switch instance.
|
||||
*/
|
||||
Switch& found(const Ty& _case, const Scope& callback) {
|
||||
reflections_[_case] = callback;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a default block with a callback function,
|
||||
* if no cases matched, this block will be called.
|
||||
* @param callback
|
||||
*/
|
||||
inline void others(const Scope& callback) {
|
||||
has_others_scope_ = true;
|
||||
others_ = callback;
|
||||
this->done();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finish the cases,
|
||||
* others() will call this method automatically.
|
||||
*/
|
||||
inline void done() {
|
||||
auto kv = reflections_.find(target_);
|
||||
if (kv != reflections_.end()) {
|
||||
// found
|
||||
auto scope = kv->second;
|
||||
scope();
|
||||
} else if (has_others_scope_) {
|
||||
// not found, call others
|
||||
others_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Combine the cases to this Switch from another Switch.
|
||||
* Note that this two Switch should be the same template.
|
||||
* @param _switch Another Switch instance.
|
||||
* @return
|
||||
*/
|
||||
inline Switch& combine(const Switch& _switch) {
|
||||
for (auto kv : _switch.reflections()) {
|
||||
this->reflections_[kv.first] = kv.second;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the case-callback pairs.
|
||||
* @return
|
||||
*/
|
||||
inline Reflections reflections() const { return reflections_; }
|
||||
|
||||
private:
|
||||
const Ty& target_;
|
||||
bool has_others_scope_;
|
||||
Scope others_;
|
||||
Reflections reflections_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Define which expression does the Switch match.
|
||||
* @param expression
|
||||
* @return
|
||||
*/
|
||||
template <typename Ty>
|
||||
Switch<Ty> select(const Ty& expression) {
|
||||
return Switch<Ty>(expression);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PROGRAM_OPTIONS_SWITCH_HPP_
|
||||
@ -0,0 +1,144 @@
|
||||
#ifndef EASYPR_UTIL_UTIL_H_
|
||||
#define EASYPR_UTIL_UTIL_H_
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "opencv2/core/core.hpp"
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#define OS_WINDOWS
|
||||
#elif defined(__APPLE__) || defined(APPLE)
|
||||
#define OS_UNIX
|
||||
#elif defined(__linux__) || defined(linux)
|
||||
#define OS_LINUX
|
||||
#endif
|
||||
|
||||
#ifndef SAFE_RELEASE
|
||||
#define SAFE_RELEASE(p) \
|
||||
if ((p)) { \
|
||||
delete (p); \
|
||||
(p) = NULL; \
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace easypr {
|
||||
class Utils {
|
||||
public:
|
||||
static long getTimestamp();
|
||||
|
||||
/*
|
||||
* Get file name from a given path
|
||||
* bool postfix: including the postfix
|
||||
*/
|
||||
static std::string getFileName(const std::string &path,
|
||||
const bool postfix = false);
|
||||
|
||||
/*
|
||||
* Split the given string into segements by a delimiter
|
||||
*/
|
||||
static std::vector<std::string> splitString(const std::string &str,
|
||||
const char delimiter);
|
||||
|
||||
/*
|
||||
* returns the smaller of the two numbers
|
||||
*/
|
||||
template<typename T>
|
||||
static T min(const T &v1, const T &v2) {
|
||||
return (v1 < v2) ? v1 : v2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get files from a given folder
|
||||
* all: including all sub-folders
|
||||
*/
|
||||
static std::vector<std::string> getFiles(const std::string &folder,
|
||||
const bool all = true);
|
||||
|
||||
/*
|
||||
* Print string lines to std::out from an array of const char*,
|
||||
* this function is used for displaying command tips.
|
||||
* lines: should be end with (const char*)NULL.
|
||||
*/
|
||||
static void print_str_lines(const char** lines) {
|
||||
int index = 0;
|
||||
while (lines[index++]) {
|
||||
std::cout << lines[index - 1] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print string lines using {"string1", "string2"},
|
||||
* this is a easier way benefit from C++11.
|
||||
*/
|
||||
static void print_str_lines(const std::initializer_list<const char*> &lines) {
|
||||
for (auto line : lines) {
|
||||
std::cout << line << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read and print by line.
|
||||
*/
|
||||
static void print_file_lines(const std::string &file) {
|
||||
std::ifstream fs(file);
|
||||
if (fs.good()) {
|
||||
while (!fs.eof()) {
|
||||
std::string line;
|
||||
std::getline(fs, line);
|
||||
#ifdef OS_WINDOWS
|
||||
line = utf8_to_gbk(line.c_str());
|
||||
#endif
|
||||
std::cout << line << std::endl;
|
||||
}
|
||||
fs.close();
|
||||
} else {
|
||||
std::cerr << "cannot open file: " << file << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static unsigned int levenshtein_distance(const T &s1, const T &s2) {
|
||||
const size_t len1 = s1.size(), len2 = s2.size();
|
||||
std::vector<unsigned int> col(len2 + 1), prevCol(len2 + 1);
|
||||
|
||||
for (unsigned int i = 0; i < prevCol.size(); i++) prevCol[i] = i;
|
||||
for (unsigned int i = 0; i < len1; i++) {
|
||||
col[0] = i + 1;
|
||||
for (unsigned int j = 0; j < len2; j++)
|
||||
col[j + 1] = easypr::Utils::min(
|
||||
easypr::Utils::min(prevCol[1 + j] + 1, col[j] + 1),
|
||||
prevCol[j] + (s1[i] == s2[j] ? 0 : 1));
|
||||
col.swap(prevCol);
|
||||
}
|
||||
return prevCol[len2];
|
||||
}
|
||||
|
||||
/*
|
||||
* Create multi-level directories by given folder.
|
||||
*/
|
||||
static bool mkdir(const std::string folder);
|
||||
|
||||
/*
|
||||
* Make sure the destination folder exists,
|
||||
* if not, create it, then call cv::imwrite.
|
||||
*/
|
||||
static bool imwrite(const std::string &file, const cv::Mat &image);
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
static std::string utf8_to_gbk(const char* utf8);
|
||||
#endif
|
||||
|
||||
private:
|
||||
/*
|
||||
* Get the last slash from a path, compatible with Windows and *unix.
|
||||
*/
|
||||
static std::size_t get_last_slash(const std::string &path);
|
||||
};
|
||||
|
||||
typedef Utils utils;
|
||||
|
||||
} // namespace easypr
|
||||
|
||||
#endif // EASYPR_UTIL_UTIL_H_
|
||||
@ -0,0 +1,24 @@
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
#define CV_VERSION_ID CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define cvLIB(name) "opencv_" name CV_VERSION_ID "d"
|
||||
#else
|
||||
#define cvLIB(name) "opencv_" name CV_VERSION_ID
|
||||
#endif
|
||||
|
||||
#pragma comment( lib, cvLIB("core") )
|
||||
#pragma comment( lib, cvLIB("imgproc") )
|
||||
#pragma comment( lib, cvLIB("highgui") )
|
||||
#pragma comment( lib, cvLIB("flann") )
|
||||
#pragma comment( lib, cvLIB("features2d") )
|
||||
#pragma comment( lib, cvLIB("calib3d") )
|
||||
#pragma comment( lib, cvLIB("gpu") )
|
||||
#pragma comment( lib, cvLIB("legacy") )
|
||||
#pragma comment( lib, cvLIB("ml") )
|
||||
#pragma comment( lib, cvLIB("objdetect") )
|
||||
#pragma comment( lib, cvLIB("ts") )
|
||||
#pragma comment( lib, cvLIB("video") )
|
||||
#pragma comment( lib, cvLIB("contrib") )
|
||||
#pragma comment( lib, cvLIB("nonfree") )
|
||||
@ -0,0 +1,31 @@
|
||||
zh_cuan 川
|
||||
zh_gan1 甘
|
||||
zh_hei 黑
|
||||
zh_jin 津
|
||||
zh_liao 辽
|
||||
zh_min 闽
|
||||
zh_qiong 琼
|
||||
zh_sx 晋
|
||||
zh_xin 新
|
||||
zh_yue 粤
|
||||
zh_zhe 浙
|
||||
zh_e 鄂
|
||||
zh_gui 贵
|
||||
zh_hu 沪
|
||||
zh_jing 京
|
||||
zh_lu 鲁
|
||||
zh_ning 宁
|
||||
zh_shan 陕
|
||||
zh_wan 皖
|
||||
zh_yu 豫
|
||||
zh_yun 云
|
||||
zh_gan 赣
|
||||
zh_gui1 桂
|
||||
zh_ji 冀
|
||||
zh_jl 吉
|
||||
zh_meng 蒙
|
||||
zh_qing 青
|
||||
zh_su 苏
|
||||
zh_xiang 湘
|
||||
zh_yu1 渝
|
||||
zh_zang 藏
|
||||
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 359 KiB |
|
After Width: | Height: | Size: 399 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 330 KiB |
|
After Width: | Height: | Size: 453 B |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 323 KiB |
|
After Width: | Height: | Size: 461 KiB |
|
After Width: | Height: | Size: 207 KiB |
|
After Width: | Height: | Size: 237 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 200 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 397 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 172 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 186 KiB |
|
After Width: | Height: | Size: 247 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 48 KiB |