mirror of
https://github.com/kerberos-io/openalpr-base.git
synced 2025-10-06 16:27:07 +08:00
Updated detector API to pass in prewarp pointer
This commit is contained in:
@@ -25,7 +25,7 @@ using namespace std;
|
|||||||
namespace alpr
|
namespace alpr
|
||||||
{
|
{
|
||||||
|
|
||||||
Detector::Detector(Config* config)
|
Detector::Detector(Config* config, PreWarp* prewarp) : detector_mask(config, prewarp)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->config = config;
|
||||||
|
|
||||||
|
@@ -50,6 +50,8 @@ namespace alpr
|
|||||||
|
|
||||||
bool loaded;
|
bool loaded;
|
||||||
|
|
||||||
|
DetectorMask detector_mask;
|
||||||
|
|
||||||
std::string get_detector_file();
|
std::string get_detector_file();
|
||||||
|
|
||||||
float computeScaleFactor(int width, int height);
|
float computeScaleFactor(int width, int height);
|
||||||
|
@@ -28,6 +28,7 @@ namespace alpr
|
|||||||
|
|
||||||
DetectorCPU::DetectorCPU(Config* config) : Detector(config) {
|
DetectorCPU::DetectorCPU(Config* config) : Detector(config) {
|
||||||
|
|
||||||
|
DetectorCPU::DetectorCPU(Config* config, PreWarp* prewarp) : Detector(config, prewarp) {
|
||||||
|
|
||||||
|
|
||||||
if( this->plate_cascade.load( get_detector_file() ) )
|
if( this->plate_cascade.load( get_detector_file() ) )
|
||||||
|
@@ -36,7 +36,7 @@ namespace alpr
|
|||||||
|
|
||||||
class DetectorCPU : public Detector {
|
class DetectorCPU : public Detector {
|
||||||
public:
|
public:
|
||||||
DetectorCPU(Config* config);
|
DetectorCPU(Config* config, PreWarp* prewarp);
|
||||||
virtual ~DetectorCPU();
|
virtual ~DetectorCPU();
|
||||||
|
|
||||||
std::vector<PlateRegion> detect(cv::Mat frame, std::vector<cv::Rect> regionsOfInterest);
|
std::vector<PlateRegion> detect(cv::Mat frame, std::vector<cv::Rect> regionsOfInterest);
|
||||||
|
@@ -29,7 +29,7 @@ using namespace std;
|
|||||||
namespace alpr
|
namespace alpr
|
||||||
{
|
{
|
||||||
|
|
||||||
DetectorCUDA::DetectorCUDA(Config* config) : Detector(config) {
|
DetectorCUDA::DetectorCUDA(Config* config, PreWarp* prewarp) : Detector(config, prewarp) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -43,7 +43,7 @@ namespace alpr
|
|||||||
|
|
||||||
class DetectorCUDA : public Detector {
|
class DetectorCUDA : public Detector {
|
||||||
public:
|
public:
|
||||||
DetectorCUDA(Config* config);
|
DetectorCUDA(Config* config, PreWarp* prewarp);
|
||||||
virtual ~DetectorCUDA();
|
virtual ~DetectorCUDA();
|
||||||
|
|
||||||
std::vector<PlateRegion> detect(cv::Mat frame, std::vector<cv::Rect> regionsOfInterest);
|
std::vector<PlateRegion> detect(cv::Mat frame, std::vector<cv::Rect> regionsOfInterest);
|
||||||
|
@@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
namespace alpr
|
namespace alpr
|
||||||
{
|
{
|
||||||
Detector* createDetector(Config* config)
|
Detector* createDetector(Config* config, PreWarp* prewarp)
|
||||||
{
|
{
|
||||||
if (config->detector == DETECTOR_LBP_CPU)
|
if (config->detector == DETECTOR_LBP_CPU)
|
||||||
{
|
{
|
||||||
// CPU mode
|
// CPU mode
|
||||||
return new DetectorCPU(config);
|
return new DetectorCPU(config, prewarp);
|
||||||
}
|
}
|
||||||
else if (config->detector == DETECTOR_LBP_GPU)
|
else if (config->detector == DETECTOR_LBP_GPU)
|
||||||
{
|
{
|
||||||
@@ -19,13 +19,13 @@ namespace alpr
|
|||||||
std::cerr << "Error: GPU detector requested, but GPU extensions are not compiled. " <<
|
std::cerr << "Error: GPU detector requested, but GPU extensions are not compiled. " <<
|
||||||
"Add COMPILE_GPU=1 to the compiler definitions to enable GPU compilation." <<
|
"Add COMPILE_GPU=1 to the compiler definitions to enable GPU compilation." <<
|
||||||
std::endl;
|
std::endl;
|
||||||
return new DetectorCPU(config);
|
return new DetectorCPU(config, prewarp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (config->detector == DETECTOR_LBP_OPENCL)
|
else if (config->detector == DETECTOR_LBP_OPENCL)
|
||||||
{
|
{
|
||||||
#if OPENCV_MAJOR_VERSION == 3
|
#if OPENCV_MAJOR_VERSION == 3
|
||||||
return new DetectorOCL(config);
|
return new DetectorOCL(config, prewarp);
|
||||||
#else
|
#else
|
||||||
std::cerr << "Error: OpenCL acceleration requires OpenCV 3.0. " << std::endl;
|
std::cerr << "Error: OpenCL acceleration requires OpenCV 3.0. " << std::endl;
|
||||||
return new DetectorCPU(config);
|
return new DetectorCPU(config);
|
||||||
@@ -33,12 +33,12 @@ namespace alpr
|
|||||||
}
|
}
|
||||||
else if (config->detector == DETECTOR_MORPH_CPU)
|
else if (config->detector == DETECTOR_MORPH_CPU)
|
||||||
{
|
{
|
||||||
return new DetectorMorph(config);
|
return new DetectorMorph(config, prewarp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "Unknown detector requested. Using LBP CPU" << std::endl;
|
std::cerr << "Unknown detector requested. Using LBP CPU" << std::endl;
|
||||||
return new DetectorCPU(config);
|
return new DetectorCPU(config, prewarp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
namespace alpr
|
namespace alpr
|
||||||
{
|
{
|
||||||
|
|
||||||
Detector* createDetector(Config* config);
|
Detector* createDetector(Config* config, PreWarp* prewarp);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* OPENALPR_DETECTORFACTORY_H */
|
#endif /* OPENALPR_DETECTORFACTORY_H */
|
||||||
|
153
src/openalpr/detection/detectormask.cpp
Normal file
153
src/openalpr/detection/detectormask.cpp
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 OpenALPR Technology, Inc.
|
||||||
|
* Open source Automated License Plate Recognition [http://www.openalpr.com]
|
||||||
|
*
|
||||||
|
* This file is part of OpenALPR.
|
||||||
|
*
|
||||||
|
* OpenALPR is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License
|
||||||
|
* version 3 as published by the Free Software Foundation
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "detectormask.h"
|
||||||
|
#include "prewarp.h"
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace alpr
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
DetectorMask::DetectorMask(Config* config, PreWarp* prewarp) {
|
||||||
|
mask_loaded = false;
|
||||||
|
resized_mask_loaded = false;
|
||||||
|
this->config = config;
|
||||||
|
this->prewarp = prewarp;
|
||||||
|
last_prewarp_hash = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
DetectorMask::~DetectorMask() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DetectorMask::setMask(Mat orig_mask) {
|
||||||
|
this->mask = orig_mask;
|
||||||
|
if (orig_mask.channels() > 2)
|
||||||
|
cvtColor( orig_mask, this->mask, CV_BGR2GRAY );
|
||||||
|
else
|
||||||
|
this->mask = orig_mask;
|
||||||
|
|
||||||
|
// Threshold the mask so that the values are either 0 or 255 (no shades of gray))
|
||||||
|
threshold(this->mask, this->mask, 1, 255, cv::THRESH_BINARY);
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate the biggest rectangle that covers all the whitespace
|
||||||
|
// Rather than using contours, go row by row, column by column until you hit
|
||||||
|
// a white pixel and stop. Should be faster and a little simpler
|
||||||
|
unsigned int top_bound = 0, bottom_bound = 0, left_bound = 0, right_bound = 0;
|
||||||
|
|
||||||
|
cout << mask.col(20).cols << " - " << mask.col(20).rows << endl;
|
||||||
|
for (top_bound = 0; top_bound < mask.rows; top_bound++)
|
||||||
|
if (countNonZero(mask.row(top_bound)) > 0) break;
|
||||||
|
for (bottom_bound = mask.rows - 1; bottom_bound >= 0; bottom_bound--)
|
||||||
|
if (countNonZero(mask.row(bottom_bound)) > 0) break;
|
||||||
|
|
||||||
|
for (left_bound = 0; left_bound < mask.cols; left_bound++)
|
||||||
|
if (countNonZero(mask.col(left_bound)) > 0) break;
|
||||||
|
for (right_bound = mask.rows - 1; right_bound >= 0; right_bound--)
|
||||||
|
if (countNonZero(mask.col(right_bound)) > 0) break;
|
||||||
|
|
||||||
|
if (left_bound >= right_bound || top_bound >= bottom_bound)
|
||||||
|
{
|
||||||
|
cerr << "Invalid mask" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scan_area.x = left_bound;
|
||||||
|
scan_area.y = top_bound;
|
||||||
|
scan_area.width = right_bound - left_bound;
|
||||||
|
scan_area.height = bottom_bound - top_bound;
|
||||||
|
|
||||||
|
// Mat debug(this->mask.size(), mask.type());
|
||||||
|
// this->mask.copyTo(debug);
|
||||||
|
// cvtColor(debug, debug, CV_GRAY2BGR);
|
||||||
|
// rectangle(debug, scan_area, Scalar(0,255,0), 2);
|
||||||
|
// drawAndWait(debug);
|
||||||
|
mask_loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::Size DetectorMask::mask_size() {
|
||||||
|
return mask.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provided a region of interest, truncate it if the mask cuts off a portion of it.
|
||||||
|
// No reason to analyze extra content
|
||||||
|
cv::Rect DetectorMask::getRoiInsideMask(cv::Rect roi) {
|
||||||
|
|
||||||
|
if (prewarp->valid)
|
||||||
|
{
|
||||||
|
cv::Rect warped_scan_area = prewarp->projectRect(scan_area, mask.cols, mask.rows, false);
|
||||||
|
|
||||||
|
Rect roi_intersection = roi & scan_area;
|
||||||
|
return roi_intersection;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Rect roi_intersection = roi & scan_area;
|
||||||
|
return roi_intersection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks if the provided region is partially covered by the mask
|
||||||
|
// If so, it is disqualified
|
||||||
|
bool DetectorMask::region_is_masked(cv::Rect region) {
|
||||||
|
int MIN_WHITENESS = 253;
|
||||||
|
|
||||||
|
// If the mean pixel value over the crop is very white (e.g., > 253 out of 255)
|
||||||
|
// then this is in the white area of the mask and we'll use it
|
||||||
|
Mat mask_crop = mask(region);
|
||||||
|
double mean_value = mean(mask_crop)[0];
|
||||||
|
|
||||||
|
return mean_value >= MIN_WHITENESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat DetectorMask::apply_mask(Mat image) {
|
||||||
|
if (!mask_loaded)
|
||||||
|
return image;
|
||||||
|
|
||||||
|
if (!resized_mask_loaded || last_prewarp_hash != prewarp->toString())
|
||||||
|
{
|
||||||
|
resize(mask, resized_mask, image.size());
|
||||||
|
|
||||||
|
if (prewarp->valid)
|
||||||
|
{
|
||||||
|
resized_mask = prewarp->warpImage(resized_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
last_prewarp_hash = prewarp->toString();
|
||||||
|
|
||||||
|
resized_mask_loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image.size() != resized_mask.size())
|
||||||
|
{
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat response(image.size(), image.type());
|
||||||
|
image.copyTo(response, resized_mask);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
66
src/openalpr/detection/detectormask.h
Normal file
66
src/openalpr/detection/detectormask.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 OpenALPR Technology, Inc.
|
||||||
|
* Open source Automated License Plate Recognition [http://www.openalpr.com]
|
||||||
|
*
|
||||||
|
* This file is part of OpenALPR.
|
||||||
|
*
|
||||||
|
* OpenALPR is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License
|
||||||
|
* version 3 as published by the Free Software Foundation
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPENALPR_DETECTORMASK_H
|
||||||
|
#define OPENALPR_DETECTORMASK_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "opencv2/imgproc/imgproc.hpp"
|
||||||
|
#include "config.h"
|
||||||
|
#include "prewarp.h"
|
||||||
|
|
||||||
|
namespace alpr
|
||||||
|
{
|
||||||
|
|
||||||
|
class DetectorMask {
|
||||||
|
public:
|
||||||
|
|
||||||
|
DetectorMask(Config* config, PreWarp* prewarp);
|
||||||
|
virtual ~DetectorMask();
|
||||||
|
|
||||||
|
void setMask(cv::Mat mask);
|
||||||
|
|
||||||
|
cv::Rect getRoiInsideMask(cv::Rect roi);
|
||||||
|
|
||||||
|
cv::Size mask_size();
|
||||||
|
|
||||||
|
bool region_is_masked(cv::Rect region);
|
||||||
|
|
||||||
|
cv::Mat apply_mask(cv::Mat image);
|
||||||
|
|
||||||
|
bool mask_loaded;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
PreWarp* prewarp;
|
||||||
|
std::string last_prewarp_hash;
|
||||||
|
|
||||||
|
cv::Mat mask;
|
||||||
|
|
||||||
|
cv::Mat resized_mask;
|
||||||
|
bool resized_mask_loaded;
|
||||||
|
|
||||||
|
Config* config;
|
||||||
|
cv::Rect scan_area;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif /* DETECTORMASK_H */
|
||||||
|
|
@@ -24,7 +24,7 @@ using namespace std;
|
|||||||
|
|
||||||
namespace alpr {
|
namespace alpr {
|
||||||
|
|
||||||
DetectorMorph::DetectorMorph(Config* config) : Detector(config) {
|
DetectorMorph::DetectorMorph(Config* config, PreWarp* prewarp) : Detector(config, prewarp) {
|
||||||
|
|
||||||
this->loaded = true;
|
this->loaded = true;
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,7 @@ namespace alpr {
|
|||||||
|
|
||||||
class DetectorMorph : public Detector {
|
class DetectorMorph : public Detector {
|
||||||
public:
|
public:
|
||||||
DetectorMorph(Config* config);
|
DetectorMorph(Config* config, PreWarp* prewarp);
|
||||||
virtual ~DetectorMorph();
|
virtual ~DetectorMorph();
|
||||||
|
|
||||||
std::vector<PlateRegion> detect(cv::Mat frame, std::vector<cv::Rect> regionsOfInterest);
|
std::vector<PlateRegion> detect(cv::Mat frame, std::vector<cv::Rect> regionsOfInterest);
|
||||||
|
@@ -32,7 +32,7 @@ namespace alpr
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
DetectorOCL::DetectorOCL(Config* config) : Detector(config) {
|
DetectorOCL::DetectorOCL(Config* config, PreWarp* prewarp) : Detector(config, prewarp) {
|
||||||
|
|
||||||
tthread::lock_guard<tthread::mutex> guard(ocl_detector_mutex_m);
|
tthread::lock_guard<tthread::mutex> guard(ocl_detector_mutex_m);
|
||||||
|
|
||||||
|
@@ -39,7 +39,7 @@ namespace alpr
|
|||||||
|
|
||||||
class DetectorOCL : public Detector {
|
class DetectorOCL : public Detector {
|
||||||
public:
|
public:
|
||||||
DetectorOCL(Config* config);
|
DetectorOCL(Config* config, PreWarp* prewarp);
|
||||||
virtual ~DetectorOCL();
|
virtual ~DetectorOCL();
|
||||||
|
|
||||||
std::vector<PlateRegion> detect(cv::Mat frame, std::vector<cv::Rect> regionsOfInterest);
|
std::vector<PlateRegion> detect(cv::Mat frame, std::vector<cv::Rect> regionsOfInterest);
|
||||||
|
Reference in New Issue
Block a user