mirror of
https://github.com/opencv/opencv.git
synced 2025-06-09 02:23:23 +08:00
Merge pull request #23807 from mshabunin:barcode-test
objdetect: updated barcode test
This commit is contained in:
commit
a9d547dfee
@ -4,116 +4,129 @@
|
|||||||
|
|
||||||
#include "test_precomp.hpp"
|
#include "test_precomp.hpp"
|
||||||
#include "opencv2/objdetect/barcode.hpp"
|
#include "opencv2/objdetect/barcode.hpp"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
namespace opencv_test{namespace{
|
namespace opencv_test{namespace{
|
||||||
|
|
||||||
typedef std::vector<std::string> stringvec;
|
typedef std::set<string> StringSet;
|
||||||
typedef std::map<std::string, std::string> datasetType;
|
|
||||||
|
|
||||||
inline stringvec explode(const std::string &s, const char &c)
|
// Convert ';'-separated strings to a set
|
||||||
|
inline static StringSet toSet(const string &line)
|
||||||
{
|
{
|
||||||
std::string buff;
|
StringSet res;
|
||||||
stringvec v;
|
string::size_type it = 0, ti;
|
||||||
|
while (true)
|
||||||
for (auto n:s)
|
|
||||||
{
|
{
|
||||||
if (n != c) { buff += n; }
|
ti = line.find(';', it);
|
||||||
else if (n == c && !buff.empty())
|
if (ti == string::npos)
|
||||||
{
|
{
|
||||||
v.push_back(buff);
|
res.insert(string(line, it, line.size() - it));
|
||||||
buff = "";
|
break;
|
||||||
}
|
}
|
||||||
|
res.insert(string(line, it, ti - it));
|
||||||
|
it = ti + 1;
|
||||||
}
|
}
|
||||||
if (!buff.empty()) { v.push_back(buff); }
|
return res;
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline datasetType buildDataSet(std::string result_file_path)
|
// Convert vector of strings to a set
|
||||||
|
inline static StringSet toSet(const vector<string> &lines)
|
||||||
{
|
{
|
||||||
std::ifstream result_file;
|
StringSet res;
|
||||||
datasetType dataset;
|
for (const string & line : lines)
|
||||||
result_file.open(result_file_path);
|
res.insert(line);
|
||||||
std::string line;
|
return res;
|
||||||
if (result_file.is_open())
|
}
|
||||||
|
|
||||||
|
// Get all keys of a map in a vector
|
||||||
|
template<typename T, typename V>
|
||||||
|
inline static vector<T> getKeys(const map<T, V> &m)
|
||||||
|
{
|
||||||
|
vector<T> res;
|
||||||
|
for (const auto & it : m)
|
||||||
|
res.push_back(it.first);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BarcodeResult
|
||||||
|
{
|
||||||
|
string type;
|
||||||
|
string data;
|
||||||
|
};
|
||||||
|
|
||||||
|
map<string, BarcodeResult> testResults {
|
||||||
|
{ "single/book.jpg", {"EAN_13", "9787115279460"} },
|
||||||
|
{ "single/bottle_1.jpg", {"EAN_13", "6922255451427"} },
|
||||||
|
{ "single/bottle_2.jpg", {"EAN_13", "6921168509256"} },
|
||||||
|
{ "multiple/4_barcodes.jpg", {"EAN_13;EAN_13;EAN_13;EAN_13", "9787564350840;9783319200064;9787118081473;9787122276124"} }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef testing::TestWithParam< string > BarcodeDetector_main;
|
||||||
|
|
||||||
|
TEST_P(BarcodeDetector_main, interface)
|
||||||
|
{
|
||||||
|
const string fname = GetParam();
|
||||||
|
const string image_path = findDataFile(string("barcode/") + fname);
|
||||||
|
const StringSet expected_lines = toSet(testResults[fname].data);
|
||||||
|
const StringSet expected_types = toSet(testResults[fname].type);
|
||||||
|
const size_t expected_count = expected_lines.size(); // assume codes are unique
|
||||||
|
// TODO: verify points location
|
||||||
|
|
||||||
|
Mat img = imread(image_path);
|
||||||
|
ASSERT_FALSE(img.empty()) << "Can't read image: " << image_path;
|
||||||
|
|
||||||
|
barcode::BarcodeDetector det;
|
||||||
|
vector<Point2f> points;
|
||||||
|
vector<string> types;
|
||||||
|
vector<string> lines;
|
||||||
|
|
||||||
|
// common interface (single)
|
||||||
{
|
{
|
||||||
while (std::getline(result_file, line))
|
bool res = det.detect(img, points);
|
||||||
{
|
ASSERT_TRUE(res);
|
||||||
stringvec result = explode(line, ',');
|
EXPECT_EQ(expected_count * 4, points.size());
|
||||||
std::string filename = result[0];
|
|
||||||
if (dataset.find(filename) == dataset.end())
|
|
||||||
{
|
|
||||||
dataset[filename] = result[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result_file.close();
|
|
||||||
return dataset;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline datasetType initValidation(std::string path)
|
|
||||||
{
|
|
||||||
const std::string valid_path = findDataFile(path);
|
|
||||||
return buildDataSet(valid_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
TEST(BARCODE_BarcodeDetector_single, regression)
|
|
||||||
{
|
|
||||||
const std::string root = "barcode/single/";
|
|
||||||
datasetType validation = initValidation(root + "result.csv");
|
|
||||||
auto bardet = barcode::BarcodeDetector();
|
|
||||||
datasetType::iterator iterator = validation.begin();
|
|
||||||
while (iterator != validation.end())
|
|
||||||
{
|
{
|
||||||
std::string img_name = iterator->first;
|
string res = det.decode(img, points);
|
||||||
std::string result = iterator->second;
|
ASSERT_FALSE(res.empty());
|
||||||
std::string image_path = findDataFile(root + img_name);
|
EXPECT_EQ(1u, expected_lines.count(res));
|
||||||
Mat img = imread(image_path);
|
|
||||||
EXPECT_FALSE(img.empty()) << "Can't read image: " << image_path;
|
|
||||||
std::vector<cv::Point2f> points;
|
|
||||||
std::vector<std::string> infos;
|
|
||||||
std::vector<std::string> formats;
|
|
||||||
bardet.detectAndDecodeWithType(img, infos, formats, points);
|
|
||||||
EXPECT_FALSE(points.empty()) << "Nothing detected: " << image_path;
|
|
||||||
bool is_correct = false;
|
|
||||||
for (const auto &ans : infos)
|
|
||||||
{
|
|
||||||
if (ans == result)
|
|
||||||
{
|
|
||||||
is_correct = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPECT_TRUE(is_correct) << "No results for " << img_name;
|
|
||||||
iterator++;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BARCODE_BarcodeDetector_detect_multi, detect_regression)
|
// common interface (multi)
|
||||||
{
|
|
||||||
const std::string root = "barcode/multiple/";
|
|
||||||
datasetType validation = initValidation(root + "result.csv");
|
|
||||||
auto bardet = barcode::BarcodeDetector();
|
|
||||||
datasetType::iterator iterator = validation.begin();
|
|
||||||
while (iterator != validation.end())
|
|
||||||
{
|
{
|
||||||
std::string img = iterator->first;
|
bool res = det.detectMulti(img, points);
|
||||||
size_t expect_corners_size = std::stoi(iterator->second);
|
ASSERT_TRUE(res);
|
||||||
std::string image_path = findDataFile(root + img);
|
EXPECT_EQ(expected_count * 4, points.size());
|
||||||
Mat src = imread(image_path);
|
}
|
||||||
EXPECT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
|
||||||
|
|
||||||
std::vector<Point> corners;
|
{
|
||||||
bardet.detectMulti(src, corners);
|
bool res = det.decodeMulti(img, points, lines);
|
||||||
EXPECT_EQ(corners.size(), expect_corners_size) << "Can't detect all barcodes: " << img;
|
ASSERT_TRUE(res);
|
||||||
iterator++;
|
EXPECT_EQ(expected_lines, toSet(lines));
|
||||||
|
}
|
||||||
|
|
||||||
|
// specific interface
|
||||||
|
{
|
||||||
|
bool res = det.decodeWithType(img, points, lines, types);
|
||||||
|
ASSERT_TRUE(res);
|
||||||
|
EXPECT_EQ(expected_types, toSet(types));
|
||||||
|
EXPECT_EQ(expected_lines, toSet(lines));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
bool res = det.detectAndDecodeWithType(img, lines, types, points);
|
||||||
|
ASSERT_TRUE(res);
|
||||||
|
EXPECT_EQ(expected_types, toSet(types));
|
||||||
|
EXPECT_EQ(expected_lines, toSet(lines));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BARCODE_BarcodeDetector_basic, not_found_barcode)
|
INSTANTIATE_TEST_CASE_P(/**/, BarcodeDetector_main, testing::ValuesIn(getKeys(testResults)));
|
||||||
|
|
||||||
|
TEST(BarcodeDetector_base, invalid)
|
||||||
{
|
{
|
||||||
auto bardet = barcode::BarcodeDetector();
|
auto bardet = barcode::BarcodeDetector();
|
||||||
std::vector<Point> corners;
|
std::vector<Point> corners;
|
||||||
|
Loading…
Reference in New Issue
Block a user