mirror of
https://github.com/kerberos-io/openalpr-base.git
synced 2025-10-06 07:37:00 +08:00
Added character bounding box and confidence to API output
This commit is contained in:
@@ -28,20 +28,29 @@
|
|||||||
namespace alpr
|
namespace alpr
|
||||||
{
|
{
|
||||||
|
|
||||||
struct AlprPlate
|
|
||||||
{
|
|
||||||
std::string characters;
|
|
||||||
float overall_confidence;
|
|
||||||
|
|
||||||
bool matches_template;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AlprCoordinate
|
struct AlprCoordinate
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AlprChar
|
||||||
|
{
|
||||||
|
AlprCoordinate corners[4];
|
||||||
|
float confidence;
|
||||||
|
std::string character;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AlprPlate
|
||||||
|
{
|
||||||
|
std::string characters;
|
||||||
|
float overall_confidence;
|
||||||
|
|
||||||
|
std::vector<AlprChar> character_details;
|
||||||
|
bool matches_template;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class AlprRegionOfInterest
|
class AlprRegionOfInterest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -209,6 +209,19 @@ namespace alpr
|
|||||||
aplate.characters = ppResults[pp].letters;
|
aplate.characters = ppResults[pp].letters;
|
||||||
aplate.overall_confidence = ppResults[pp].totalscore;
|
aplate.overall_confidence = ppResults[pp].totalscore;
|
||||||
aplate.matches_template = ppResults[pp].matchesTemplate;
|
aplate.matches_template = ppResults[pp].matchesTemplate;
|
||||||
|
|
||||||
|
// Grab detailed results for each character
|
||||||
|
for (unsigned int c_idx = 0; c_idx < ppResults[pp].letter_details.size(); c_idx++)
|
||||||
|
{
|
||||||
|
AlprChar character_details;
|
||||||
|
character_details.character = ppResults[pp].letter_details[c_idx].letter;
|
||||||
|
character_details.confidence = ppResults[pp].letter_details[c_idx].totalscore;
|
||||||
|
cv::Rect char_rect = pipeline_data.charRegions[ppResults[pp].letter_details[c_idx].charposition];
|
||||||
|
std::vector<AlprCoordinate> charpoints = getCharacterPoints(char_rect, &pipeline_data );
|
||||||
|
for (int cpt = 0; cpt < 4; cpt++)
|
||||||
|
character_details.corners[cpt] = charpoints[cpt];
|
||||||
|
aplate.character_details.push_back(character_details);
|
||||||
|
}
|
||||||
plateResult.topNPlates.push_back(aplate);
|
plateResult.topNPlates.push_back(aplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,6 +233,7 @@ namespace alpr
|
|||||||
bestPlate.characters = plateResult.topNPlates[bestPlateIndex].characters;
|
bestPlate.characters = plateResult.topNPlates[bestPlateIndex].characters;
|
||||||
bestPlate.matches_template = plateResult.topNPlates[bestPlateIndex].matches_template;
|
bestPlate.matches_template = plateResult.topNPlates[bestPlateIndex].matches_template;
|
||||||
bestPlate.overall_confidence = plateResult.topNPlates[bestPlateIndex].overall_confidence;
|
bestPlate.overall_confidence = plateResult.topNPlates[bestPlateIndex].overall_confidence;
|
||||||
|
bestPlate.character_details = plateResult.topNPlates[bestPlateIndex].character_details;
|
||||||
|
|
||||||
plateResult.bestPlate = bestPlate;
|
plateResult.bestPlate = bestPlate;
|
||||||
}
|
}
|
||||||
@@ -277,6 +291,7 @@ namespace alpr
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < response.results.plates.size(); i++)
|
for (unsigned int i = 0; i < response.results.plates.size(); i++)
|
||||||
{
|
{
|
||||||
|
// Draw a box around the license plate
|
||||||
for (int z = 0; z < 4; z++)
|
for (int z = 0; z < 4; z++)
|
||||||
{
|
{
|
||||||
AlprCoordinate* coords = response.results.plates[i].plate_points;
|
AlprCoordinate* coords = response.results.plates[i].plate_points;
|
||||||
@@ -284,6 +299,16 @@ namespace alpr
|
|||||||
Point p2(coords[(z + 1) % 4].x, coords[(z + 1) % 4].y);
|
Point p2(coords[(z + 1) % 4].x, coords[(z + 1) % 4].y);
|
||||||
line(img, p1, p2, Scalar(255,0,255), 2);
|
line(img, p1, p2, Scalar(255,0,255), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw the individual character boxes
|
||||||
|
for (int q = 0; q < response.results.plates[0].bestPlate.character_details.size(); q++)
|
||||||
|
{
|
||||||
|
AlprChar details = response.results.plates[0].bestPlate.character_details[q];
|
||||||
|
line(img, Point(details.corners[0].x, details.corners[0].y), Point(details.corners[1].x, details.corners[1].y), Scalar(0,255,0), 1);
|
||||||
|
line(img, Point(details.corners[1].x, details.corners[1].y), Point(details.corners[2].x, details.corners[2].y), Scalar(0,255,0), 1);
|
||||||
|
line(img, Point(details.corners[2].x, details.corners[2].y), Point(details.corners[3].x, details.corners[3].y), Scalar(0,255,0), 1);
|
||||||
|
line(img, Point(details.corners[3].x, details.corners[3].y), Point(details.corners[0].x, details.corners[0].y), Scalar(0,255,0), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -561,5 +586,47 @@ namespace alpr
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<AlprCoordinate> AlprImpl::getCharacterPoints(cv::Rect char_rect, PipelineData* pipeline_data ) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Point2f> points;
|
||||||
|
points.push_back(Point2f(char_rect.x, char_rect.y));
|
||||||
|
points.push_back(Point2f(char_rect.x + char_rect.width, char_rect.y));
|
||||||
|
points.push_back(Point2f(char_rect.x + char_rect.width, char_rect.y + char_rect.height));
|
||||||
|
points.push_back(Point2f(char_rect.x, char_rect.y + char_rect.height));
|
||||||
|
|
||||||
|
Mat img = pipeline_data->colorImg;
|
||||||
|
Mat debugImg(img.size(), img.type());
|
||||||
|
img.copyTo(debugImg);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Point2f> crop_corners;
|
||||||
|
crop_corners.push_back(Point2f(0,0));
|
||||||
|
crop_corners.push_back(Point2f(pipeline_data->crop_gray.cols,0));
|
||||||
|
crop_corners.push_back(Point2f(pipeline_data->crop_gray.cols,pipeline_data->crop_gray.rows));
|
||||||
|
crop_corners.push_back(Point2f(0,pipeline_data->crop_gray.rows));
|
||||||
|
|
||||||
|
// Transform the points from the cropped region (skew corrected license plate region) back to the original image
|
||||||
|
cv::Mat transmtx = cv::getPerspectiveTransform(crop_corners, pipeline_data->plate_corners);
|
||||||
|
cv::perspectiveTransform(points, points, transmtx);
|
||||||
|
|
||||||
|
// If using prewarp, remap the points to the original image
|
||||||
|
points = prewarp->projectPoints(points, true);
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<AlprCoordinate> cornersvector;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
AlprCoordinate coord;
|
||||||
|
coord.x = round(points[i].x);
|
||||||
|
coord.y = round(points[i].y);
|
||||||
|
cornersvector.push_back(coord);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cornersvector;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -107,6 +107,7 @@ namespace alpr
|
|||||||
bool detectRegion;
|
bool detectRegion;
|
||||||
std::string defaultRegion;
|
std::string defaultRegion;
|
||||||
|
|
||||||
|
std::vector<AlprCoordinate> getCharacterPoints(cv::Rect char_rect, PipelineData* pipeline_data);
|
||||||
std::vector<cv::Rect> convertRects(std::vector<AlprRegionOfInterest> regionsOfInterest);
|
std::vector<cv::Rect> convertRects(std::vector<AlprRegionOfInterest> regionsOfInterest);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -411,12 +411,18 @@ namespace alpr
|
|||||||
for (int z = 0; z < prevletters.size(); z++)
|
for (int z = 0; z < prevletters.size(); z++)
|
||||||
{
|
{
|
||||||
if (prevletters[z].letter != SKIP_CHAR)
|
if (prevletters[z].letter != SKIP_CHAR)
|
||||||
|
{
|
||||||
possibility.letters = possibility.letters + prevletters[z].letter;
|
possibility.letters = possibility.letters + prevletters[z].letter;
|
||||||
|
possibility.letter_details.push_back(prevletters[z]);
|
||||||
|
}
|
||||||
possibility.totalscore = possibility.totalscore + prevletters[z].totalscore;
|
possibility.totalscore = possibility.totalscore + prevletters[z].totalscore;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (letters[charPos][i].letter != SKIP_CHAR)
|
if (letters[charPos][i].letter != SKIP_CHAR)
|
||||||
|
{
|
||||||
possibility.letters = possibility.letters + letters[charPos][i].letter;
|
possibility.letters = possibility.letters + letters[charPos][i].letter;
|
||||||
|
possibility.letter_details.push_back(letters[charPos][i]);
|
||||||
|
}
|
||||||
possibility.totalscore = possibility.totalscore +letters[charPos][i].totalscore;
|
possibility.totalscore = possibility.totalscore +letters[charPos][i].totalscore;
|
||||||
|
|
||||||
allPossibilities.push_back(possibility);
|
allPossibilities.push_back(possibility);
|
||||||
|
@@ -48,6 +48,7 @@ namespace alpr
|
|||||||
std::string letters;
|
std::string letters;
|
||||||
float totalscore;
|
float totalscore;
|
||||||
bool matchesTemplate;
|
bool matchesTemplate;
|
||||||
|
std::vector<Letter> letter_details;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool wordCompare( const PPResult &left, const PPResult &right );
|
bool wordCompare( const PPResult &left, const PPResult &right );
|
||||||
|
Reference in New Issue
Block a user