mirror of
https://github.com/opencv/opencv.git
synced 2024-12-18 11:28:02 +08:00
Merge pull request #17889 from ZhengQiushi:my_3.4
QR code (encoding process) * add qrcode encoder * qr encoder fixes * qr encoder: fix api and realization * fixed qr encoder, added eci and kanji modes * trigger CI * qr encoder constructor fixes Co-authored-by: APrigarina <ann73617@gmail.com>
This commit is contained in:
parent
8041ab8a61
commit
3e51448ef0
@ -670,6 +670,69 @@ public:
|
||||
void groupRectangles(std::vector<cv::Rect>& rectList, std::vector<double>& weights, int groupThreshold, double eps) const;
|
||||
};
|
||||
|
||||
class CV_EXPORTS_W QRCodeEncoder {
|
||||
protected:
|
||||
QRCodeEncoder(); // use ::create()
|
||||
public:
|
||||
virtual ~QRCodeEncoder();
|
||||
|
||||
enum EncodeMode {
|
||||
MODE_AUTO = -1,
|
||||
MODE_NUMERIC = 1, // 0b0001
|
||||
MODE_ALPHANUMERIC = 2, // 0b0010
|
||||
MODE_BYTE = 4, // 0b0100
|
||||
MODE_ECI = 7, // 0b0111
|
||||
MODE_KANJI = 8, // 0b1000
|
||||
MODE_STRUCTURED_APPEND = 3 // 0b0011
|
||||
};
|
||||
|
||||
enum CorrectionLevel {
|
||||
CORRECT_LEVEL_L = 0,
|
||||
CORRECT_LEVEL_M = 1,
|
||||
CORRECT_LEVEL_Q = 2,
|
||||
CORRECT_LEVEL_H = 3
|
||||
};
|
||||
|
||||
enum ECIEncodings {
|
||||
ECI_UTF8 = 26
|
||||
};
|
||||
|
||||
/** @brief QR code encoder parameters.
|
||||
@param version The optional version of QR code (by default - maximum possible depending on
|
||||
the length of the string).
|
||||
@param correction_level The optional level of error correction (by default - the lowest).
|
||||
@param mode The optional encoding mode - Numeric, Alphanumeric, Byte, Kanji, ECI or Structured Append.
|
||||
@param structure_number The optional number of QR codes to generate in Structured Append mode.
|
||||
*/
|
||||
struct CV_EXPORTS_W_SIMPLE Params
|
||||
{
|
||||
CV_WRAP Params();
|
||||
CV_PROP_RW int version;
|
||||
CV_PROP_RW CorrectionLevel correction_level;
|
||||
CV_PROP_RW EncodeMode mode;
|
||||
CV_PROP_RW int structure_number;
|
||||
};
|
||||
|
||||
/** @brief Constructor
|
||||
@param parameters QR code encoder parameters QRCodeEncoder::Params
|
||||
*/
|
||||
static CV_WRAP
|
||||
Ptr<QRCodeEncoder> create(const QRCodeEncoder::Params& parameters = QRCodeEncoder::Params());
|
||||
|
||||
/** @brief Generates QR code from input string.
|
||||
@param encoded_info Input string to encode.
|
||||
@param qrcode Generated QR code.
|
||||
*/
|
||||
CV_WRAP virtual void encode(const String& encoded_info, OutputArray qrcode) = 0;
|
||||
|
||||
/** @brief Generates QR code from input string in Structured Append mode. The encoded message is splitting over a number of QR codes.
|
||||
@param encoded_info Input string to encode.
|
||||
@param qrcodes Vector of generated QR codes.
|
||||
*/
|
||||
CV_WRAP virtual void encodeStructuredAppend(const String& encoded_info, OutputArrayOfArrays qrcodes) = 0;
|
||||
|
||||
};
|
||||
|
||||
class CV_EXPORTS_W QRCodeDetector
|
||||
{
|
||||
public:
|
||||
|
3
modules/objdetect/misc/python/pyopencv_objdetect.hpp
Normal file
3
modules/objdetect/misc/python/pyopencv_objdetect.hpp
Normal file
@ -0,0 +1,3 @@
|
||||
#ifdef HAVE_OPENCV_OBJDETECT
|
||||
typedef QRCodeEncoder::Params QRCodeEncoder_Params;
|
||||
#endif
|
1265
modules/objdetect/src/qrcode_encoder.cpp
Normal file
1265
modules/objdetect/src/qrcode_encoder.cpp
Normal file
File diff suppressed because it is too large
Load Diff
860
modules/objdetect/src/qrcode_encoder_table.inl.hpp
Normal file
860
modules/objdetect/src/qrcode_encoder_table.inl.hpp
Normal file
@ -0,0 +1,860 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2021, Intel Corporation, all rights reserved.
|
||||
//
|
||||
// This is .hpp file included from qrcode_encoder.cpp
|
||||
|
||||
namespace cv {
|
||||
|
||||
const int MAX_ALIGNMENT = 7;
|
||||
const int MODES = 4;
|
||||
const int ERROR_CORR_LEVELS = 4;
|
||||
const int MAX_VERSION = 40;
|
||||
|
||||
struct BlockParams
|
||||
{
|
||||
int ecc_codewords;
|
||||
int num_blocks_in_G1;
|
||||
int data_codewords_in_G1;
|
||||
int num_blocks_in_G2;
|
||||
int data_codewords_in_G2;
|
||||
};
|
||||
|
||||
struct VersionInfo
|
||||
{
|
||||
int total_codewords;
|
||||
int alignment_pattern[MAX_ALIGNMENT];
|
||||
BlockParams ecc[ERROR_CORR_LEVELS];
|
||||
};
|
||||
|
||||
/** numeric_mode;
|
||||
alpha_mode;
|
||||
byte_mode;
|
||||
kanji mode;
|
||||
*/
|
||||
struct ECLevelCapacity
|
||||
{
|
||||
int encoding_modes[MODES];
|
||||
};
|
||||
struct CharacterCapacity
|
||||
{
|
||||
ECLevelCapacity ec_level[ERROR_CORR_LEVELS];
|
||||
};
|
||||
const CharacterCapacity version_capacity_database[MAX_VERSION + 1] =
|
||||
{
|
||||
{
|
||||
{
|
||||
{0, 1, 0, 0},
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{41, 25, 17, 10},
|
||||
{34, 20, 14, 8},
|
||||
{27, 16, 11, 7},
|
||||
{17, 10, 7 , 4}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{77, 47, 32, 20},
|
||||
{63, 38, 26, 16},
|
||||
{48, 29, 20, 12},
|
||||
{34, 20, 14, 8}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{127, 77, 53, 32},
|
||||
{101, 61, 42, 26},
|
||||
{77, 47, 32, 20},
|
||||
{58, 35, 24, 15}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{187, 114, 78, 48},
|
||||
{149, 90, 62, 38},
|
||||
{111, 67, 46, 28},
|
||||
{82, 50, 34, 21}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{255, 154, 106, 65},
|
||||
{202, 122, 84, 52},
|
||||
{144, 87, 60, 37},
|
||||
{106, 64, 44, 27}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{322, 195, 134, 82},
|
||||
{255, 154, 106, 65},
|
||||
{178, 108, 74, 45},
|
||||
{139, 84 , 58, 36}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{370, 224, 154, 95},
|
||||
{293, 178, 122, 75},
|
||||
{207, 125, 86, 53},
|
||||
{154, 93 , 64, 39}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{461, 279, 192, 118},
|
||||
{365, 221, 152, 93},
|
||||
{259, 157, 108, 66},
|
||||
{202, 122, 84, 52}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{552, 335, 230, 141},
|
||||
{432, 262, 180, 111},
|
||||
{312, 189, 130, 80},
|
||||
{235, 143, 98, 60}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{652, 395, 271, 167},
|
||||
{513, 311, 213, 131},
|
||||
{364, 221, 151, 93},
|
||||
{288, 174, 119, 74}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{772, 468, 321, 198},
|
||||
{604, 366, 251, 155},
|
||||
{427, 259, 177, 109},
|
||||
{331, 200, 137, 85}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{883, 535, 367, 226},
|
||||
{691, 419, 287, 177},
|
||||
{489, 296, 203, 125},
|
||||
{374, 227, 155, 96}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{1022, 619, 425, 262},
|
||||
{796, 483, 331, 204},
|
||||
{580, 352, 241, 149},
|
||||
{427, 259, 177, 109}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{1101, 667, 458, 282},
|
||||
{871, 528, 362, 223},
|
||||
{621, 376, 258, 159},
|
||||
{468, 283, 194, 120}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{1250, 758, 520, 320},
|
||||
{991, 600, 412, 254},
|
||||
{703, 426, 292, 180},
|
||||
{530, 321, 220, 136}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{1408, 854, 586, 361},
|
||||
{1082, 656, 450, 277},
|
||||
{775, 470, 322, 198},
|
||||
{602, 365, 250, 154}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{1548, 938, 644, 397},
|
||||
{1212, 734, 504, 310},
|
||||
{876, 531, 364, 224},
|
||||
{674, 408, 280, 173}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{1725, 1046, 718, 442},
|
||||
{1346, 816, 560, 345},
|
||||
{948, 574, 394, 243},
|
||||
{746, 452, 310, 191}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{1903, 1153, 792, 488},
|
||||
{1500, 909, 624, 384},
|
||||
{1063, 644, 442, 272},
|
||||
{813, 493, 338, 208}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{2061, 1249, 858, 528},
|
||||
{1600, 970, 666, 410},
|
||||
{1159, 702, 482, 297},
|
||||
{919, 557, 382, 235}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{2232, 1352, 929, 572},
|
||||
{1708, 1035, 711, 438},
|
||||
{1224, 742, 509, 314},
|
||||
{969, 587, 403, 248}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{2409, 1460, 1003, 618},
|
||||
{1872, 1134, 779, 480},
|
||||
{1358, 823, 565, 348},
|
||||
{1056, 640, 439, 270}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{2620, 1588, 1091, 672},
|
||||
{2059, 1248, 857, 528},
|
||||
{1468, 890, 611, 376},
|
||||
{1108, 672, 461, 284}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{2812, 1704, 1171, 721},
|
||||
{2188, 1326, 911, 561},
|
||||
{1588, 963, 661, 407},
|
||||
{1228, 744, 511, 315}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{3057, 1853, 1273, 784},
|
||||
{2395, 1451, 997, 614},
|
||||
{1718, 1041, 715, 440},
|
||||
{1286, 779, 535, 330}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{3283, 1990, 1367, 842},
|
||||
{2544, 1542, 1059, 652},
|
||||
{1804, 1094, 751, 462},
|
||||
{1425, 864, 593, 365}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{3517, 2132, 1465, 902},
|
||||
{2701, 1637, 1125, 692},
|
||||
{1933, 1172, 805, 496},
|
||||
{1501, 910, 625, 385}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{3669, 2223, 1528, 940},
|
||||
{2857, 1732, 1190, 732},
|
||||
{2085, 1263, 868, 534},
|
||||
{1581, 958, 658, 405}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{3909, 2369, 1628, 1002},
|
||||
{3035, 1839, 1264, 778},
|
||||
{2181, 1322, 908, 559},
|
||||
{1677, 1016, 698, 430}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{4158, 2520, 1732, 1066},
|
||||
{3289, 1994, 1370, 843},
|
||||
{2358, 1429, 982, 604},
|
||||
{1782, 1080, 742, 457}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{4417, 2677, 1840, 1132},
|
||||
{3486, 2113, 1452, 894},
|
||||
{2473, 1499, 1030, 634},
|
||||
{1897, 1150, 790, 486}
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
{
|
||||
{4686, 2840, 1952, 1201},
|
||||
{3693, 2238, 1538, 947},
|
||||
{2670, 1618, 1112, 684},
|
||||
{2022, 1226, 842, 518}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{4965, 3009, 2068, 1273},
|
||||
{3909, 2369, 1628, 1002},
|
||||
{2805, 1700, 1168, 719},
|
||||
{2157, 1307, 898, 553}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{5253, 3183, 2188, 1347},
|
||||
{4134, 2506, 1722, 1060},
|
||||
{2949, 1787, 1228, 756},
|
||||
{2301, 1394, 958 , 590}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{5529, 3351, 2303, 1417},
|
||||
{4343, 2632, 1809, 1113},
|
||||
{3081, 1867, 1283, 790},
|
||||
{2361, 1431, 983, 605}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{5836, 3537, 2431, 1496},
|
||||
{4588, 2780, 1911, 1176},
|
||||
{3244, 1966, 1351, 832},
|
||||
{2524, 1530, 1051, 647}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{6153, 3729, 2563, 1577},
|
||||
{4775, 2894, 1989, 1224},
|
||||
{3417, 2071, 1423, 876},
|
||||
{2625, 1591, 1093, 673}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{6479, 3927, 2699, 1661},
|
||||
{5039, 3054, 2099, 1292},
|
||||
{3599, 2181, 1499, 923},
|
||||
{2735, 1658, 1139, 701}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{6743, 4087, 2809, 1729},
|
||||
{5313, 3220, 2213, 1362},
|
||||
{3791, 2298, 1579, 972},
|
||||
{2927, 1774, 1219, 750}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
{7089, 4296, 2953, 1817},
|
||||
{5596, 3391, 2331, 1435},
|
||||
{3993, 2420, 1663, 1024},
|
||||
{3057, 1852, 1273, 784}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const VersionInfo version_info_database[MAX_VERSION + 1] =
|
||||
{
|
||||
{ /* Version 0 */
|
||||
0,
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
{
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
{ /* Version 1 */
|
||||
26,
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
{
|
||||
{7, 1, 19, 0, 0},
|
||||
{10, 1, 16, 0, 0},
|
||||
{13, 1, 13, 0, 0},
|
||||
{17, 1, 9, 0, 0}
|
||||
}
|
||||
},
|
||||
{ /* Version 2 */
|
||||
44,
|
||||
{6, 18, 0, 0, 0, 0, 0},
|
||||
{
|
||||
{10, 1, 34, 0, 0},
|
||||
{16, 1, 28, 0, 0},
|
||||
{22, 1, 22, 0, 0},
|
||||
{28, 1, 16, 0, 0}
|
||||
}
|
||||
},
|
||||
{ /* Version 3 */
|
||||
70,
|
||||
{6, 22, 0, 0, 0, 0, 0},
|
||||
{
|
||||
{15, 1, 55, 0, 0},
|
||||
{26, 1, 44, 0, 0},
|
||||
{18, 2, 17, 0, 0},
|
||||
{22, 2, 13, 0, 0}
|
||||
}
|
||||
},
|
||||
{ /* Version 4 */
|
||||
100,
|
||||
{6, 26, 0,0,0,0,0},
|
||||
{
|
||||
{20, 1, 80, 0, 0},
|
||||
{18, 2, 32, 0, 0},
|
||||
{26, 2, 24, 0, 0},
|
||||
{16, 4, 9 , 0, 0}
|
||||
}
|
||||
},
|
||||
{ /* Version 5 */
|
||||
134,
|
||||
{6, 30, 0, 0, 0, 0, 0},
|
||||
{
|
||||
{26, 1, 108, 0, 0},
|
||||
{24, 2, 43, 0, 0},
|
||||
{18, 2, 15, 2, 16},
|
||||
{22, 2, 11, 2, 12}
|
||||
}
|
||||
},
|
||||
{ /* Version 6 */
|
||||
172,
|
||||
{6, 34, 0, 0, 0, 0, 0},
|
||||
{
|
||||
{18, 2, 68, 0, 0},
|
||||
{16, 4, 27, 0, 0},
|
||||
{24, 4, 19, 0, 0},
|
||||
{28, 4, 15, 0, 0}
|
||||
}
|
||||
},
|
||||
{ /* Version 7 */
|
||||
196,
|
||||
{6, 22, 38, 0, 0, 0, 0},
|
||||
{
|
||||
{20, 2, 78, 0, 0},
|
||||
{18, 4, 31, 0, 0},
|
||||
{18, 2, 14, 4, 15},
|
||||
{26, 4, 13, 1, 14}
|
||||
}
|
||||
},
|
||||
{ /* Version 8 */
|
||||
242,
|
||||
{6, 24, 42, 0, 0, 0, 0},
|
||||
{
|
||||
{24, 2, 97, 0, 0},
|
||||
{22, 2, 38, 2, 39},
|
||||
{22, 4, 18, 2, 19},
|
||||
{26, 4, 14, 2, 15}
|
||||
}
|
||||
},
|
||||
{ /* Version 9 */
|
||||
292,
|
||||
{6, 26, 46, 0, 0, 0, 0},
|
||||
{
|
||||
{30, 2, 116, 0, 0},
|
||||
{22, 3, 36, 2, 37},
|
||||
{20, 4, 16, 4, 17},
|
||||
{24, 4, 12, 4, 13}
|
||||
}
|
||||
},
|
||||
{ /* Version 10 */
|
||||
346,
|
||||
{6, 28, 50, 0, 0, 0, 0},
|
||||
{
|
||||
{18, 2, 68, 2, 69},
|
||||
{26, 4, 43, 1, 44},
|
||||
{24, 6, 19, 2, 20},
|
||||
{28, 6, 15, 2, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 11 */
|
||||
404,
|
||||
{6, 30, 54, 0, 0, 0, 0},
|
||||
{
|
||||
{20, 4, 81, 0, 0},
|
||||
{30, 1, 50, 4, 51},
|
||||
{28, 4, 22, 4, 23},
|
||||
{24, 3, 12, 8, 13}
|
||||
}
|
||||
},
|
||||
{ /* Version 12 */
|
||||
466,
|
||||
{6, 32, 58, 0, 0, 0, 0},
|
||||
{
|
||||
{24, 2, 92, 2, 93},
|
||||
{22, 6, 36, 2, 37},
|
||||
{26, 4, 20, 6, 21},
|
||||
{28, 7, 14, 4, 15}
|
||||
}
|
||||
},
|
||||
{ /* Version 13 */
|
||||
532,
|
||||
{6, 34, 62, 0, 0, 0, 0},
|
||||
{
|
||||
{26, 4, 107, 0, 0},
|
||||
{22, 8, 37, 1, 38},
|
||||
{24, 8, 20, 4, 21},
|
||||
{22, 12, 11, 4, 12}
|
||||
}
|
||||
},
|
||||
{ /* Version 14 */
|
||||
581,
|
||||
{6, 26, 46, 66, 0, 0, 0},
|
||||
{
|
||||
{30, 3, 115, 1, 116},
|
||||
{24, 4, 40, 5, 41},
|
||||
{20, 11, 16, 5, 17},
|
||||
{24, 11, 12, 5, 13}
|
||||
}
|
||||
},
|
||||
{ /* Version 15 */
|
||||
655,
|
||||
{6, 26, 48, 70, 0, 0, 0},
|
||||
{
|
||||
{22, 5, 87, 1, 88},
|
||||
{24, 5, 41, 5, 42},
|
||||
{30, 5, 24, 7, 25},
|
||||
{24, 11, 12, 7, 13}
|
||||
}
|
||||
},
|
||||
{ /* Version 16 */
|
||||
733,
|
||||
{6, 26, 50, 74, 0, 0, 0},
|
||||
{
|
||||
{24, 5, 98, 1, 99},
|
||||
{28, 7, 45, 3, 46},
|
||||
{24, 15, 19, 2, 20},
|
||||
{30, 3, 15, 13, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 17 */
|
||||
815,
|
||||
{6, 30, 54, 78, 0, 0, 0},
|
||||
{
|
||||
{28, 1, 107, 5, 108},
|
||||
{28, 10, 46, 1, 47},
|
||||
{28, 1, 22, 15, 23},
|
||||
{28, 2, 14, 17, 15}
|
||||
}
|
||||
},
|
||||
{ /* Version 18 */
|
||||
901,
|
||||
{6, 30, 56, 82, 0, 0, 0},
|
||||
{
|
||||
{30, 5, 120, 1, 121},
|
||||
{26, 9, 43, 4, 44},
|
||||
{28, 17, 22, 1, 23},
|
||||
{28, 2, 14, 19, 15}
|
||||
}
|
||||
},
|
||||
{ /* Version 19 */
|
||||
991,
|
||||
{6, 30, 58, 86, 0, 0, 0},
|
||||
{
|
||||
{28, 3, 113, 4, 114},
|
||||
{26, 3, 44, 11, 45},
|
||||
{26, 17, 21, 4, 22},
|
||||
{26, 9, 13, 16, 14}
|
||||
}
|
||||
},
|
||||
{ /* Version 20 */
|
||||
1085,
|
||||
{6, 34, 62, 90, 0, 0, 0},
|
||||
{
|
||||
{28, 3, 107, 5, 108},
|
||||
{26, 3, 41, 13, 42},
|
||||
{30, 15, 24, 5, 25},
|
||||
{28, 15, 15, 10, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 21 */
|
||||
1156,
|
||||
{6, 28, 50, 72, 92, 0, 0},
|
||||
{
|
||||
{28, 4, 116, 4, 117},
|
||||
{26, 17, 42, 0, 0},
|
||||
{28, 17, 22, 6, 23},
|
||||
{30, 19, 16, 6, 17}
|
||||
}
|
||||
},
|
||||
{ /* Version 22 */
|
||||
1258,
|
||||
{6, 26, 50, 74, 98, 0, 0},
|
||||
{
|
||||
{28, 2, 111, 7, 112},
|
||||
{28, 17, 46, 0, 0},
|
||||
{30, 7, 24, 16, 25},
|
||||
{24, 34, 13, 0, 0}
|
||||
}
|
||||
},
|
||||
{ /* Version 23 */
|
||||
1364,
|
||||
{6, 30, 54, 78, 102, 0, 0},
|
||||
{
|
||||
{30, 4, 121,5, 122},
|
||||
{28, 4, 47, 14, 48},
|
||||
{30, 11, 24, 14, 25},
|
||||
{30, 16, 15, 14, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 24 */
|
||||
1474,
|
||||
{6, 28, 54, 80, 106, 0, 0},
|
||||
{
|
||||
{30, 6, 117,4, 118},
|
||||
{28, 6, 45, 14, 46},
|
||||
{30, 11, 24, 16, 25},
|
||||
{30, 30, 16, 2, 17}
|
||||
}
|
||||
},
|
||||
{ /* Version 25 */
|
||||
1588,
|
||||
{6, 32, 58, 84, 110, 0, 0},
|
||||
{
|
||||
{26, 8, 106, 4, 107},
|
||||
{28, 8, 47, 13, 48},
|
||||
{30, 7, 24, 22, 25},
|
||||
{30, 22, 15, 13, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 26 */
|
||||
1706,
|
||||
{6, 30, 58, 86, 114, 0, 0},
|
||||
{
|
||||
{28, 10, 114, 2, 115},
|
||||
{28, 19, 46, 4, 47},
|
||||
{28, 28, 22, 6, 23},
|
||||
{30, 33, 16, 4, 17}
|
||||
}
|
||||
},
|
||||
{ /* Version 27 */
|
||||
1828,
|
||||
{6, 34, 62, 90, 118, 0, 0},
|
||||
{
|
||||
{30, 8, 122, 4, 123},
|
||||
{28, 22, 45, 3, 46},
|
||||
{30, 8, 23, 26, 24},
|
||||
{30, 12, 15, 28, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 28 */
|
||||
1921,
|
||||
{6, 26, 50, 74, 98, 122, 0},
|
||||
{
|
||||
{30, 3, 117, 10, 118},
|
||||
{28, 3, 45, 23, 46},
|
||||
{30, 4, 24, 31, 25},
|
||||
{30, 11, 15, 31, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 29 */
|
||||
2051,
|
||||
{6, 30, 54, 78, 102, 126, 0},
|
||||
{
|
||||
{30, 7, 116, 7, 117},
|
||||
{28, 21, 45, 7, 46},
|
||||
{30, 1, 23, 37, 24},
|
||||
{30, 19, 15, 26, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 30 */
|
||||
2185,
|
||||
{6, 26, 52, 78, 104, 130, 0},
|
||||
{
|
||||
{30, 5, 115, 10, 116},
|
||||
{28, 19, 47, 10, 48},
|
||||
{30, 15, 24, 25, 25},
|
||||
{30, 23, 15, 25, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 31 */
|
||||
2323,
|
||||
{6, 30, 56, 82, 108, 134, 0},
|
||||
{
|
||||
{30, 13, 115, 3, 116},
|
||||
{28, 2, 46, 29, 47},
|
||||
{30, 42, 24, 1, 25},
|
||||
{30, 23, 15, 28, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 32 */
|
||||
2465,
|
||||
{6, 34, 60, 86, 112, 138, 0},
|
||||
{
|
||||
{30, 17, 115, 0, 0},
|
||||
{28, 10, 46, 23, 47},
|
||||
{30, 10, 24, 35, 25},
|
||||
{30, 19, 15, 35, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 33 */
|
||||
2611,
|
||||
{6, 30, 58, 86, 114, 142, 0},
|
||||
{
|
||||
{30, 17, 115, 1, 116},
|
||||
{28, 14, 46, 21, 47},
|
||||
{30, 29, 24, 19, 25},
|
||||
{30, 11, 15, 46, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 34 */
|
||||
2761,
|
||||
{6, 34, 62, 90, 118, 146, 0},
|
||||
{
|
||||
{30, 13, 115, 6, 116},
|
||||
{28, 14, 46, 23, 47},
|
||||
{30, 44, 24, 7, 25},
|
||||
{30, 59, 16, 1, 17}
|
||||
}
|
||||
},
|
||||
{ /* Version 35 */
|
||||
2876,
|
||||
{6, 30, 54, 78, 102, 126, 150},
|
||||
{
|
||||
{30, 12, 121, 7, 122},
|
||||
{28, 12, 47, 26, 48},
|
||||
{30, 39, 24, 14, 25},
|
||||
{30, 22, 15, 41, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 36 */
|
||||
3034,
|
||||
{6, 24, 50, 76, 102, 128, 154},
|
||||
{
|
||||
{30, 6, 121, 14, 122},
|
||||
{28, 6, 47, 34, 48},
|
||||
{30, 46, 24, 10, 25},
|
||||
{30, 2, 15, 64, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 37 */
|
||||
3196,
|
||||
{6, 28, 54, 80, 106, 132, 158},
|
||||
{
|
||||
{30, 17, 122, 4, 123},
|
||||
{28, 29, 46, 14, 47},
|
||||
{30, 49, 24, 10, 25},
|
||||
{30, 24, 15, 46, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 38 */
|
||||
3362,
|
||||
{6, 32, 58, 84, 110, 136, 162},
|
||||
{
|
||||
{30, 4, 122, 18, 123},
|
||||
{28, 13, 46, 32, 47},
|
||||
{30, 48, 24, 14, 25},
|
||||
{30, 42, 15, 32, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 39 */
|
||||
3532,
|
||||
{6, 26, 54, 82, 110, 138, 166},
|
||||
{
|
||||
{30, 20, 117,4, 118},
|
||||
{28, 40, 47, 7, 48},
|
||||
{30, 43, 24, 22, 25},
|
||||
{30, 10, 15, 67, 16}
|
||||
}
|
||||
},
|
||||
{ /* Version 40 */
|
||||
3706,
|
||||
{6, 30, 58, 86, 114, 142, 170},
|
||||
{
|
||||
{30, 19, 118, 6, 119},
|
||||
{28, 18, 47, 31, 48},
|
||||
{30, 34, 24, 34, 25},
|
||||
{30, 20, 15, 61, 16}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const uint8_t gf_exp[256] = {
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
|
||||
0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
|
||||
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9,
|
||||
0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
|
||||
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35,
|
||||
0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
|
||||
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0,
|
||||
0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
|
||||
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc,
|
||||
0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
|
||||
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f,
|
||||
0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
|
||||
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88,
|
||||
0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
|
||||
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93,
|
||||
0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
|
||||
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9,
|
||||
0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
|
||||
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa,
|
||||
0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
|
||||
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e,
|
||||
0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
|
||||
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4,
|
||||
0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
|
||||
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e,
|
||||
0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
|
||||
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef,
|
||||
0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
|
||||
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5,
|
||||
0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
|
||||
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83,
|
||||
0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01
|
||||
};
|
||||
static const uint8_t gf_log[256] = {
|
||||
0x00, 0xff, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6,
|
||||
0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
|
||||
0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81,
|
||||
0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
|
||||
0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21,
|
||||
0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
|
||||
0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9,
|
||||
0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
|
||||
0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd,
|
||||
0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
|
||||
0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd,
|
||||
0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
|
||||
0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e,
|
||||
0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
|
||||
0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b,
|
||||
0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
|
||||
0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d,
|
||||
0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
|
||||
0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c,
|
||||
0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
|
||||
0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd,
|
||||
0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
|
||||
0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e,
|
||||
0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
|
||||
0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76,
|
||||
0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
|
||||
0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa,
|
||||
0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
|
||||
0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51,
|
||||
0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
|
||||
0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8,
|
||||
0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
|
||||
};
|
||||
}
|
433
modules/objdetect/test/test_qrcode_encode.cpp
Normal file
433
modules/objdetect/test/test_qrcode_encode.cpp
Normal file
@ -0,0 +1,433 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
std::string encode_qrcode_images_name[] = {
|
||||
"version1_mode1.png", "version1_mode2.png", "version1_mode4.png",
|
||||
"version2_mode1.png", "version2_mode2.png", "version2_mode4.png",
|
||||
"version3_mode2.png", "version3_mode4.png",
|
||||
"version4_mode4.png"
|
||||
};
|
||||
|
||||
std::string encode_qrcode_eci_images_name[] = {
|
||||
"version1_mode7.png",
|
||||
"version2_mode7.png",
|
||||
"version3_mode7.png",
|
||||
"version4_mode7.png",
|
||||
"version5_mode7.png"
|
||||
};
|
||||
|
||||
const Size fixed_size = Size(200, 200);
|
||||
const float border_width = 2.0;
|
||||
|
||||
int establishCapacity(QRCodeEncoder::EncodeMode mode, int version, int capacity)
|
||||
{
|
||||
int result = 0;
|
||||
capacity *= 8;
|
||||
capacity -= 4;
|
||||
switch (mode)
|
||||
{
|
||||
case QRCodeEncoder::MODE_NUMERIC:
|
||||
{
|
||||
if (version >= 10)
|
||||
capacity -= 12;
|
||||
else
|
||||
capacity -= 10;
|
||||
int tmp = capacity / 10;
|
||||
result = tmp * 3;
|
||||
if (tmp * 10 + 7 <= capacity)
|
||||
result += 2;
|
||||
else if (tmp * 10 + 4 <= capacity)
|
||||
result += 1;
|
||||
break;
|
||||
}
|
||||
case QRCodeEncoder::MODE_ALPHANUMERIC:
|
||||
{
|
||||
if (version < 10)
|
||||
capacity -= 9;
|
||||
else
|
||||
capacity -= 13;
|
||||
int tmp = capacity / 11;
|
||||
result = tmp * 2;
|
||||
if (tmp * 11 + 6 <= capacity)
|
||||
result++;
|
||||
break;
|
||||
}
|
||||
case QRCodeEncoder::MODE_BYTE:
|
||||
{
|
||||
if (version > 9)
|
||||
capacity -= 16;
|
||||
else
|
||||
capacity -= 8;
|
||||
result = capacity / 8;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// #define UPDATE_TEST_DATA
|
||||
#ifdef UPDATE_TEST_DATA
|
||||
|
||||
TEST(Objdetect_QRCode_Encode, generate_test_data)
|
||||
{
|
||||
const std::string root = "qrcode/encode";
|
||||
const std::string dataset_config = findDataFile(root + "/" + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::WRITE);
|
||||
|
||||
file_config << "test_images" << "[";
|
||||
size_t images_count = sizeof(encode_qrcode_images_name) / sizeof(encode_qrcode_images_name[0]);
|
||||
for (size_t i = 0; i < images_count; i++)
|
||||
{
|
||||
file_config << "{:" << "image_name" << encode_qrcode_images_name[i];
|
||||
std::string image_path = findDataFile(root + "/" + encode_qrcode_images_name[i]);
|
||||
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE);
|
||||
Mat straight_barcode;
|
||||
EXPECT_TRUE(!src.empty()) << "Can't read image: " << image_path;
|
||||
|
||||
std::vector<Point2f> corners(4);
|
||||
corners[0] = Point2f(border_width, border_width);
|
||||
corners[1] = Point2f(qrcode.cols * 1.0f - border_width, border_width);
|
||||
corners[2] = Point2f(qrcode.cols * 1.0f - border_width, qrcode.rows * 1.0f - border_width);
|
||||
corners[3] = Point2f(border_width, qrcode.rows * 1.0f - border_width);
|
||||
|
||||
Mat resized_src;
|
||||
resize(qrcode, resized_src, fixed_size, 0, 0, INTER_AREA);
|
||||
float width_ratio = resized_src.cols * 1.0f / qrcode.cols;
|
||||
float height_ratio = resized_src.rows * 1.0f / qrcode.rows;
|
||||
for(size_t j = 0; j < corners.size(); j++)
|
||||
{
|
||||
corners[j].x = corners[j].x * width_ratio;
|
||||
corners[j].y = corners[j].y * height_ratio;
|
||||
}
|
||||
|
||||
std::string decoded_info = "";
|
||||
#ifdef HAVE_QUIRC
|
||||
EXPECT_TRUE(decodeQRCode(resized_src, corners, decoded_info, straight_barcode)) << "The QR code cannot be decoded: " << image_path;
|
||||
#endif
|
||||
file_config << "info" << decoded_info;
|
||||
file_config << "}";
|
||||
}
|
||||
file_config << "]";
|
||||
file_config.release();
|
||||
}
|
||||
#else
|
||||
|
||||
typedef testing::TestWithParam< std::string > Objdetect_QRCode_Encode;
|
||||
TEST_P(Objdetect_QRCode_Encode, regression) {
|
||||
const int pixels_error = 3;
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "qrcode/encode";
|
||||
|
||||
std::string image_path = findDataFile(root + "/" + name_current_image);
|
||||
const std::string dataset_config = findDataFile(root + "/" + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
|
||||
ASSERT_TRUE(file_config.isOpened()) << "Can't read validation data: " << dataset_config;
|
||||
{
|
||||
FileNode images_list = file_config["test_images"];
|
||||
size_t images_count = static_cast<size_t>(images_list.size());
|
||||
ASSERT_GT(images_count, 0u) << "Can't find validation data entries in 'test_images': " << dataset_config;
|
||||
|
||||
for (size_t index = 0; index < images_count; index++)
|
||||
{
|
||||
FileNode config = images_list[(int)index];
|
||||
std::string name_test_image = config["image_name"];
|
||||
if (name_test_image == name_current_image)
|
||||
{
|
||||
std::string original_info = config["info"];
|
||||
Ptr<QRCodeEncoder> encoder = QRCodeEncoder::create();
|
||||
Mat result;
|
||||
encoder->encode(original_info, result);
|
||||
EXPECT_FALSE(result.empty()) << "Can't generate QR code image";
|
||||
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE);
|
||||
Mat straight_barcode;
|
||||
EXPECT_TRUE(!src.empty()) << "Can't read image: " << image_path;
|
||||
|
||||
double diff_norm = cvtest::norm(result - src, NORM_L1);
|
||||
EXPECT_NEAR(diff_norm, 0.0, pixels_error) << "The generated QRcode is not same as test data. The difference: " << diff_norm;
|
||||
|
||||
return; // done
|
||||
}
|
||||
}
|
||||
FAIL() << "Not found results in config file:" << dataset_config
|
||||
<< "\nRe-run tests with enabled UPDATE_ENCODE_TEST_DATA macro to update test data.";
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam< std::string > Objdetect_QRCode_Encode_ECI;
|
||||
TEST_P(Objdetect_QRCode_Encode_ECI, regression) {
|
||||
const int pixels_error = 3;
|
||||
const std::string name_current_image = GetParam();
|
||||
const std::string root = "qrcode/encode";
|
||||
|
||||
std::string image_path = findDataFile(root + "/" + name_current_image);
|
||||
const std::string dataset_config = findDataFile(root + "/" + "dataset_config.json");
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
|
||||
ASSERT_TRUE(file_config.isOpened()) << "Can't read validation data: " << dataset_config;
|
||||
{
|
||||
FileNode images_list = file_config["test_images"];
|
||||
size_t images_count = static_cast<size_t>(images_list.size());
|
||||
ASSERT_GT(images_count, 0u) << "Can't find validation data entries in 'test_images': " << dataset_config;
|
||||
QRCodeEncoder::Params params;
|
||||
params.mode = QRCodeEncoder::MODE_ECI;
|
||||
|
||||
for (size_t index = 0; index < images_count; index++)
|
||||
{
|
||||
FileNode config = images_list[(int)index];
|
||||
std::string name_test_image = config["image_name"];
|
||||
if (name_test_image == name_current_image)
|
||||
{
|
||||
std::string original_info = config["info"];
|
||||
Mat result;
|
||||
Ptr<QRCodeEncoder> encoder = QRCodeEncoder::create(params);
|
||||
encoder->encode(original_info, result);
|
||||
EXPECT_FALSE(result.empty()) << "Can't generate QR code image";
|
||||
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE);
|
||||
Mat straight_barcode;
|
||||
EXPECT_TRUE(!src.empty()) << "Can't read image: " << image_path;
|
||||
|
||||
double diff_norm = cvtest::norm(result - src, NORM_L1);
|
||||
EXPECT_NEAR(diff_norm, 0.0, pixels_error) << "The generated QRcode is not same as test data. The difference: " << diff_norm;
|
||||
|
||||
return; // done
|
||||
}
|
||||
}
|
||||
FAIL() << "Not found results in config file:" << dataset_config
|
||||
<< "\nRe-run tests with enabled UPDATE_ENCODE_TEST_DATA macro to update test data.";
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Encode, testing::ValuesIn(encode_qrcode_images_name));
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Encode_ECI, testing::ValuesIn(encode_qrcode_eci_images_name));
|
||||
|
||||
TEST(Objdetect_QRCode_Encode_Decode, regression)
|
||||
{
|
||||
const std::string root = "qrcode/decode_encode";
|
||||
const int min_version = 1;
|
||||
const int test_max_version = 5;
|
||||
const int max_ec_level = 3;
|
||||
const std::string dataset_config = findDataFile(root + "/" + "symbol_sets.json");
|
||||
const std::string version_config = findDataFile(root + "/" + "capacity.json");
|
||||
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
FileStorage capacity_config(version_config, FileStorage::READ);
|
||||
ASSERT_TRUE(file_config.isOpened()) << "Can't read validation data: " << dataset_config;
|
||||
ASSERT_TRUE(capacity_config.isOpened()) << "Can't read validation data: " << version_config;
|
||||
|
||||
FileNode mode_list = file_config["symbols_sets"];
|
||||
FileNode capacity_list = capacity_config["version_ecc_capacity"];
|
||||
|
||||
size_t mode_count = static_cast<size_t>(mode_list.size());
|
||||
ASSERT_GT(mode_count, 0u) << "Can't find validation data entries in 'test_images': " << dataset_config;
|
||||
|
||||
const int testing_modes = 3;
|
||||
QRCodeEncoder::EncodeMode modes[testing_modes] = {
|
||||
QRCodeEncoder::MODE_NUMERIC,
|
||||
QRCodeEncoder::MODE_ALPHANUMERIC,
|
||||
QRCodeEncoder::MODE_BYTE
|
||||
};
|
||||
|
||||
for (int i = 0; i < testing_modes; i++)
|
||||
{
|
||||
QRCodeEncoder::EncodeMode mode = modes[i];
|
||||
FileNode config = mode_list[i];
|
||||
|
||||
std::string symbol_set = config["symbols_set"];
|
||||
|
||||
for(int version = min_version; version <= test_max_version; version++)
|
||||
{
|
||||
FileNode capa_config = capacity_list[version - 1];
|
||||
for(int level = 0; level <= max_ec_level; level++)
|
||||
{
|
||||
const int cur_capacity = capa_config["ecc_level"][level];
|
||||
|
||||
int true_capacity = establishCapacity(mode, version, cur_capacity);
|
||||
|
||||
std::string input_info = symbol_set;
|
||||
std::random_shuffle(input_info.begin(),input_info.end());
|
||||
int count = 0;
|
||||
if((int)input_info.length() > true_capacity)
|
||||
{
|
||||
input_info = input_info.substr(0, true_capacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((int)input_info.length() != true_capacity)
|
||||
{
|
||||
input_info += input_info.substr(count%(int)input_info.length(), 1);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
QRCodeEncoder::Params params;
|
||||
params.version = version;
|
||||
params.correction_level = static_cast<QRCodeEncoder::CorrectionLevel>(level);
|
||||
params.mode = mode;
|
||||
Ptr<QRCodeEncoder> encoder = QRCodeEncoder::create(params);
|
||||
Mat qrcode;
|
||||
encoder->encode(input_info, qrcode);
|
||||
EXPECT_TRUE(!qrcode.empty()) << "Can't generate this QR image (" << "mode: " << (int)mode <<
|
||||
" version: "<< version <<" error correction level: "<< (int)level <<")";
|
||||
|
||||
std::vector<Point2f> corners(4);
|
||||
corners[0] = Point2f(border_width, border_width);
|
||||
corners[1] = Point2f(qrcode.cols * 1.0f - border_width, border_width);
|
||||
corners[2] = Point2f(qrcode.cols * 1.0f - border_width, qrcode.rows * 1.0f - border_width);
|
||||
corners[3] = Point2f(border_width, qrcode.rows * 1.0f - border_width);
|
||||
|
||||
Mat resized_src;
|
||||
resize(qrcode, resized_src, fixed_size, 0, 0, INTER_AREA);
|
||||
float width_ratio = resized_src.cols * 1.0f / qrcode.cols;
|
||||
float height_ratio = resized_src.rows * 1.0f / qrcode.rows;
|
||||
for(size_t k = 0; k < corners.size(); k++)
|
||||
{
|
||||
corners[k].x = corners[k].x * width_ratio;
|
||||
corners[k].y = corners[k].y * height_ratio;
|
||||
}
|
||||
|
||||
std::string output_info = "";
|
||||
Mat straight_barcode;
|
||||
#ifdef HAVE_QUIRC
|
||||
bool success = decodeQRCode(resized_src, corners, output_info, straight_barcode);
|
||||
EXPECT_TRUE(success) << "The generated QRcode cannot be decoded." << " Mode: " << (int)mode<<
|
||||
" version: " << version << " error correction level: " << (int)level;
|
||||
#endif
|
||||
EXPECT_EQ(input_info, output_info) << "The generated QRcode is not same as test data." << " Mode: " << (int)mode <<
|
||||
" version: " << version << " error correction level: " << (int)level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(Objdetect_QRCode_Encode_Kanji, regression)
|
||||
{
|
||||
QRCodeEncoder::Params params;
|
||||
params.mode = QRCodeEncoder::MODE_KANJI;
|
||||
|
||||
Mat qrcode;
|
||||
|
||||
const int testing_versions = 3;
|
||||
std::string input_infos[testing_versions] = {"\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd\x90\xa2\x8a\x45", // こんにちは世界
|
||||
"\x82\xa8\x95\xa0\x82\xaa\x8b\xf3\x82\xa2\x82\xc4\x82\xa2\x82\xdc\x82\xb7", // お腹が空いています
|
||||
"\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd\x81\x41\x8e\x84\x82\xcd\x8f\xad\x82\xb5\x93\xfa\x96\x7b\x8c\xea\x82\xf0\x98\x62\x82\xb5\x82\xdc\x82\xb7" // こんにちは、私は少し日本語を話します
|
||||
};
|
||||
|
||||
for (int i = 0; i < testing_versions; i++)
|
||||
{
|
||||
std::string input_info = input_infos[i];
|
||||
Ptr<QRCodeEncoder> encoder = QRCodeEncoder::create(params);
|
||||
encoder->encode(input_info, qrcode);
|
||||
|
||||
std::vector<Point2f> corners(4);
|
||||
corners[0] = Point2f(border_width, border_width);
|
||||
corners[1] = Point2f(qrcode.cols * 1.0f - border_width, border_width);
|
||||
corners[2] = Point2f(qrcode.cols * 1.0f - border_width, qrcode.rows * 1.0f - border_width);
|
||||
corners[3] = Point2f(border_width, qrcode.rows * 1.0f - border_width);
|
||||
|
||||
Mat resized_src;
|
||||
resize(qrcode, resized_src, fixed_size, 0, 0, INTER_AREA);
|
||||
float width_ratio = resized_src.cols * 1.0f / qrcode.cols;
|
||||
float height_ratio = resized_src.rows * 1.0f / qrcode.rows;
|
||||
for(size_t j = 0; j < corners.size(); j++)
|
||||
{
|
||||
corners[j].x = corners[j].x * width_ratio;
|
||||
corners[j].y = corners[j].y * height_ratio;
|
||||
}
|
||||
|
||||
Mat straight_barcode;
|
||||
std::string decoded_info = "";
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
EXPECT_TRUE(decodeQRCode(resized_src, corners, decoded_info, straight_barcode)) << "The generated QRcode cannot be decoded.";
|
||||
#endif
|
||||
EXPECT_EQ(input_info, decoded_info);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Objdetect_QRCode_Encode_Decode_Structured_Append, DISABLED_regression)
|
||||
{
|
||||
// disabled since QR decoder probably doesn't support structured append mode qr codes
|
||||
const std::string root = "qrcode/decode_encode";
|
||||
const std::string dataset_config = findDataFile(root + "/" + "symbol_sets.json");
|
||||
const std::string version_config = findDataFile(root + "/" + "capacity.json");
|
||||
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
ASSERT_TRUE(file_config.isOpened()) << "Can't read validation data: " << dataset_config;
|
||||
|
||||
FileNode mode_list = file_config["symbols_sets"];
|
||||
|
||||
size_t mode_count = static_cast<size_t>(mode_list.size());
|
||||
ASSERT_GT(mode_count, 0u) << "Can't find validation data entries in 'test_images': " << dataset_config;
|
||||
|
||||
int modes[] = {1, 2, 4};
|
||||
const int min_stuctures_num = 2;
|
||||
const int max_stuctures_num = 5;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int mode = modes[i];
|
||||
FileNode config = mode_list[i];
|
||||
|
||||
std::string symbol_set = config["symbols_set"];
|
||||
|
||||
std::string input_info = symbol_set;
|
||||
std::random_shuffle(input_info.begin(), input_info.end());
|
||||
|
||||
for (int j = min_stuctures_num; j < max_stuctures_num; j++)
|
||||
{
|
||||
QRCodeEncoder::Params params;
|
||||
params.structure_number = j;
|
||||
Ptr<QRCodeEncoder> encoder = QRCodeEncoder::create(params);
|
||||
vector<Mat> qrcodes;
|
||||
encoder->encodeStructuredAppend(input_info, qrcodes);
|
||||
EXPECT_TRUE(!qrcodes.empty()) << "Can't generate this QR images";
|
||||
|
||||
std::string output_info = "";
|
||||
for (size_t k = 0; k < qrcodes.size(); k++)
|
||||
{
|
||||
Mat qrcode = qrcodes[k];
|
||||
|
||||
std::vector<Point2f> corners(4);
|
||||
corners[0] = Point2f(border_width, border_width);
|
||||
corners[1] = Point2f(qrcode.cols * 1.0f - border_width, border_width);
|
||||
corners[2] = Point2f(qrcode.cols * 1.0f - border_width, qrcode.rows * 1.0f - border_width);
|
||||
corners[3] = Point2f(border_width, qrcode.rows * 1.0f - border_width);
|
||||
|
||||
Mat resized_src;
|
||||
resize(qrcode, resized_src, fixed_size, 0, 0, INTER_AREA);
|
||||
float width_ratio = resized_src.cols * 1.0f / qrcode.cols;
|
||||
float height_ratio = resized_src.rows * 1.0f / qrcode.rows;
|
||||
for(size_t m = 0; m < corners.size(); m++)
|
||||
{
|
||||
corners[m].x = corners[m].x * width_ratio;
|
||||
corners[m].y = corners[m].y * height_ratio;
|
||||
}
|
||||
|
||||
std::string decoded_info = "";
|
||||
Mat straight_barcode;
|
||||
#ifdef HAVE_QUIRC
|
||||
bool success = decodeQRCode(resized_src, corners, decoded_info, straight_barcode);
|
||||
EXPECT_TRUE(success) << "The generated QRcode cannot be decoded." << " Mode: " << mode <<
|
||||
" structures number: " << k << "/" << j;
|
||||
#endif
|
||||
output_info += decoded_info;
|
||||
}
|
||||
EXPECT_EQ(input_info, output_info) << "The generated QRcode is not same as test data." << " Mode: " << mode <<
|
||||
" structures number: " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UPDATE_QRCODE_TEST_DATA
|
||||
|
||||
}} // namespace
|
Loading…
Reference in New Issue
Block a user