mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Merge branch 4.x
This commit is contained in:
@@ -13,32 +13,39 @@ namespace aruco {
|
||||
//! @{
|
||||
|
||||
|
||||
/** @brief Dictionary/Set of markers, it contains the inner codification
|
||||
/** @brief Dictionary is a set of unique ArUco markers of the same size
|
||||
*
|
||||
* BytesList contains the marker codewords where:
|
||||
* `bytesList` storing as 2-dimensions Mat with 4-th channels (CV_8UC4 type was used) and contains the marker codewords where:
|
||||
* - bytesList.rows is the dictionary size
|
||||
* - each marker is encoded using `nbytes = ceil(markerSize*markerSize/8.)`
|
||||
* - each marker is encoded using `nbytes = ceil(markerSize*markerSize/8.)` bytes
|
||||
* - each row contains all 4 rotations of the marker, so its length is `4*nbytes`
|
||||
*
|
||||
* `bytesList.ptr(i)[k*nbytes + j]` is then the j-th byte of i-th marker, in its k-th rotation.
|
||||
* - the byte order in the bytesList[i] row:
|
||||
* `//bytes without rotation/bytes with rotation 1/bytes with rotation 2/bytes with rotation 3//`
|
||||
* So `bytesList.ptr(i)[k*nbytes + j]` is the j-th byte of i-th marker, in its k-th rotation.
|
||||
* @note Python bindings generate matrix with shape of bytesList `dictionary_size x nbytes x 4`,
|
||||
* but it should be indexed like C++ version. Python example for j-th byte of i-th marker, in its k-th rotation:
|
||||
* `aruco_dict.bytesList[id].ravel()[k*nbytes + j]`
|
||||
*/
|
||||
class CV_EXPORTS_W_SIMPLE Dictionary {
|
||||
|
||||
public:
|
||||
CV_PROP_RW Mat bytesList; // marker code information
|
||||
CV_PROP_RW int markerSize; // number of bits per dimension
|
||||
CV_PROP_RW int maxCorrectionBits; // maximum number of bits that can be corrected
|
||||
|
||||
CV_PROP_RW Mat bytesList; ///< marker code information. See class description for more details
|
||||
CV_PROP_RW int markerSize; ///< number of bits per dimension
|
||||
CV_PROP_RW int maxCorrectionBits; ///< maximum number of bits that can be corrected
|
||||
|
||||
CV_WRAP Dictionary();
|
||||
|
||||
/** @brief Basic ArUco dictionary constructor
|
||||
*
|
||||
* @param bytesList bits for all ArUco markers in dictionary see memory layout in the class description
|
||||
* @param _markerSize ArUco marker size in units
|
||||
* @param maxcorr maximum number of bits that can be corrected
|
||||
*/
|
||||
CV_WRAP Dictionary(const Mat &bytesList, int _markerSize, int maxcorr = 0);
|
||||
|
||||
|
||||
|
||||
/** @brief Read a new dictionary from FileNode.
|
||||
*
|
||||
* Dictionary format:\n
|
||||
* Dictionary example in YAML format:\n
|
||||
* nmarkers: 35\n
|
||||
* markersize: 6\n
|
||||
* maxCorrectionBits: 5\n
|
||||
@@ -54,13 +61,13 @@ class CV_EXPORTS_W_SIMPLE Dictionary {
|
||||
|
||||
/** @brief Given a matrix of bits. Returns whether if marker is identified or not.
|
||||
*
|
||||
* It returns by reference the correct id (if any) and the correct rotation
|
||||
* Returns reference to the marker id in the dictionary (if any) and its rotation.
|
||||
*/
|
||||
CV_WRAP bool identify(const Mat &onlyBits, CV_OUT int &idx, CV_OUT int &rotation, double maxCorrectionRate) const;
|
||||
|
||||
/** @brief Returns the distance of the input bits to the specific id.
|
||||
/** @brief Returns Hamming distance of the input bits to the specific id.
|
||||
*
|
||||
* If allRotations is true, the four posible bits rotation are considered
|
||||
* If `allRotations` flag is set, the four posible marker rotations are considered
|
||||
*/
|
||||
CV_WRAP int getDistanceToId(InputArray bits, int id, bool allRotations = true) const;
|
||||
|
||||
@@ -70,7 +77,7 @@ class CV_EXPORTS_W_SIMPLE Dictionary {
|
||||
CV_WRAP void generateImageMarker(int id, int sidePixels, OutputArray _img, int borderBits = 1) const;
|
||||
|
||||
|
||||
/** @brief Transform matrix of bits to list of bytes in the 4 rotations
|
||||
/** @brief Transform matrix of bits to list of bytes with 4 marker rotations
|
||||
*/
|
||||
CV_WRAP static Mat getByteListFromBits(const Mat &bits);
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
*/
|
||||
CV_WRAP void detectDiamonds(InputArray image, OutputArrayOfArrays diamondCorners, OutputArray diamondIds,
|
||||
InputOutputArrayOfArrays markerCorners = noArray(),
|
||||
InputOutputArrayOfArrays markerIds = noArray()) const;
|
||||
InputOutputArray markerIds = noArray()) const;
|
||||
protected:
|
||||
struct CharucoDetectorImpl;
|
||||
Ptr<CharucoDetectorImpl> charucoDetectorImpl;
|
||||
|
||||
@@ -238,6 +238,27 @@ class aruco_objdetect_test(NewOpenCVTests):
|
||||
self.assertEqual(charucoIds[i], i)
|
||||
np.testing.assert_allclose(gold_corners, charucoCorners.reshape(-1, 2), 0.01, 0.1)
|
||||
|
||||
def test_detect_diamonds(self):
|
||||
aruco_dict = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_6X6_250)
|
||||
board_size = (3, 3)
|
||||
board = cv.aruco.CharucoBoard(board_size, 1.0, .8, aruco_dict)
|
||||
charuco_detector = cv.aruco.CharucoDetector(board)
|
||||
cell_size = 120
|
||||
|
||||
image = board.generateImage((cell_size*board_size[0], cell_size*board_size[1]))
|
||||
|
||||
list_gold_corners = [(cell_size, cell_size), (2*cell_size, cell_size), (2*cell_size, 2*cell_size),
|
||||
(cell_size, 2*cell_size)]
|
||||
gold_corners = np.array(list_gold_corners, dtype=np.float32)
|
||||
|
||||
diamond_corners, diamond_ids, marker_corners, marker_ids = charuco_detector.detectDiamonds(image)
|
||||
|
||||
self.assertEqual(diamond_ids.size, 4)
|
||||
self.assertEqual(marker_ids.size, 4)
|
||||
for i in range(0, 4):
|
||||
self.assertEqual(diamond_ids[0][0][i], i)
|
||||
np.testing.assert_allclose(gold_corners, np.array(diamond_corners, dtype=np.float32).reshape(-1, 2), 0.01, 0.1)
|
||||
|
||||
# check no segfault when cameraMatrix or distCoeffs are not initialized
|
||||
def test_charuco_no_segfault_params(self):
|
||||
dictionary = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_4X4_1000)
|
||||
|
||||
@@ -23,6 +23,54 @@ struct CharucoDetector::CharucoDetectorImpl {
|
||||
arucoDetector(_arucoDetector)
|
||||
{}
|
||||
|
||||
bool checkBoard(InputArrayOfArrays markerCorners, InputArray markerIds, InputArray charucoCorners, InputArray charucoIds) {
|
||||
vector<Mat> mCorners;
|
||||
markerCorners.getMatVector(mCorners);
|
||||
Mat mIds = markerIds.getMat();
|
||||
|
||||
Mat chCorners = charucoCorners.getMat();
|
||||
Mat chIds = charucoIds.getMat();
|
||||
|
||||
vector<vector<int> > nearestMarkerIdx = board.getNearestMarkerIdx();
|
||||
vector<Point2f> distance(board.getNearestMarkerIdx().size(), Point2f(0.f, std::numeric_limits<float>::max()));
|
||||
// distance[i].x: max distance from the i-th charuco corner to charuco corner-forming markers.
|
||||
// The two charuco corner-forming markers of i-th charuco corner are defined in getNearestMarkerIdx()[i]
|
||||
// distance[i].y: min distance from the charuco corner to other markers.
|
||||
for (size_t i = 0ull; i < chIds.total(); i++) {
|
||||
int chId = chIds.ptr<int>(0)[i];
|
||||
Point2f charucoCorner(chCorners.ptr<Point2f>(0)[i]);
|
||||
for (size_t j = 0ull; j < mIds.total(); j++) {
|
||||
int idMaker = mIds.ptr<int>(0)[j];
|
||||
Point2f centerMarker((mCorners[j].ptr<Point2f>(0)[0] + mCorners[j].ptr<Point2f>(0)[1] +
|
||||
mCorners[j].ptr<Point2f>(0)[2] + mCorners[j].ptr<Point2f>(0)[3]) / 4.f);
|
||||
float dist = sqrt(normL2Sqr<float>(centerMarker - charucoCorner));
|
||||
// check distance from the charuco corner to charuco corner-forming markers
|
||||
if (nearestMarkerIdx[chId][0] == idMaker || nearestMarkerIdx[chId][1] == idMaker) {
|
||||
int nearestCornerId = nearestMarkerIdx[chId][0] == idMaker ? board.getNearestMarkerCorners()[chId][0] : board.getNearestMarkerCorners()[chId][1];
|
||||
Point2f nearestCorner = mCorners[j].ptr<Point2f>(0)[nearestCornerId];
|
||||
float distToNearest = sqrt(normL2Sqr<float>(nearestCorner - charucoCorner));
|
||||
distance[chId].x = max(distance[chId].x, distToNearest);
|
||||
// check that nearestCorner is nearest point
|
||||
{
|
||||
Point2f mid1 = (mCorners[j].ptr<Point2f>(0)[(nearestCornerId + 1) % 4]+nearestCorner)*0.5f;
|
||||
Point2f mid2 = (mCorners[j].ptr<Point2f>(0)[(nearestCornerId + 3) % 4]+nearestCorner)*0.5f;
|
||||
float tmpDist = min(sqrt(normL2Sqr<float>(mid1 - charucoCorner)), sqrt(normL2Sqr<float>(mid2 - charucoCorner)));
|
||||
if (tmpDist < distToNearest)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// check distance from the charuco corner to other markers
|
||||
else
|
||||
distance[chId].y = min(distance[chId].y, dist);
|
||||
}
|
||||
// if distance from the charuco corner to charuco corner-forming markers more then distance from the charuco corner to other markers,
|
||||
// then a false board is found.
|
||||
if (distance[chId].x > 0.f && distance[chId].y < std::numeric_limits<float>::max() && distance[chId].x > distance[chId].y)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Calculate the maximum window sizes for corner refinement for each charuco corner based on the distance
|
||||
* to their closest markers */
|
||||
vector<Size> getMaximumSubPixWindowSizes(InputArrayOfArrays markerCorners, InputArray markerIds,
|
||||
@@ -246,6 +294,31 @@ struct CharucoDetector::CharucoDetectorImpl {
|
||||
Mat(filteredCharucoIds).copyTo(_filteredCharucoIds);
|
||||
return (int)_filteredCharucoIds.total();
|
||||
}
|
||||
|
||||
void detectBoard(InputArray image, OutputArray charucoCorners, OutputArray charucoIds,
|
||||
InputOutputArrayOfArrays markerCorners, InputOutputArray markerIds) {
|
||||
CV_Assert((markerCorners.empty() && markerIds.empty() && !image.empty()) || (markerCorners.total() == markerIds.total()));
|
||||
vector<vector<Point2f>> tmpMarkerCorners;
|
||||
vector<int> tmpMarkerIds;
|
||||
InputOutputArrayOfArrays _markerCorners = markerCorners.needed() ? markerCorners : tmpMarkerCorners;
|
||||
InputOutputArray _markerIds = markerIds.needed() ? markerIds : tmpMarkerIds;
|
||||
|
||||
if (markerCorners.empty() && markerIds.empty()) {
|
||||
vector<vector<Point2f> > rejectedMarkers;
|
||||
arucoDetector.detectMarkers(image, _markerCorners, _markerIds, rejectedMarkers);
|
||||
if (charucoParameters.tryRefineMarkers)
|
||||
arucoDetector.refineDetectedMarkers(image, board, _markerCorners, _markerIds, rejectedMarkers);
|
||||
}
|
||||
// if camera parameters are avaible, use approximated calibration
|
||||
if(!charucoParameters.cameraMatrix.empty())
|
||||
interpolateCornersCharucoApproxCalib(_markerCorners, _markerIds, image, charucoCorners, charucoIds);
|
||||
// else use local homography
|
||||
else
|
||||
interpolateCornersCharucoLocalHom(_markerCorners, _markerIds, image, charucoCorners, charucoIds);
|
||||
// to return a charuco corner, its closest aruco markers should have been detected
|
||||
filterCornersWithoutMinMarkers(charucoCorners, charucoIds, _markerIds, charucoCorners, charucoIds);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CharucoDetector::CharucoDetector(const CharucoBoard &board, const CharucoParameters &charucoParams,
|
||||
@@ -288,34 +361,15 @@ void CharucoDetector::setRefineParameters(const RefineParameters& refineParamete
|
||||
|
||||
void CharucoDetector::detectBoard(InputArray image, OutputArray charucoCorners, OutputArray charucoIds,
|
||||
InputOutputArrayOfArrays markerCorners, InputOutputArray markerIds) const {
|
||||
CV_Assert((markerCorners.empty() && markerIds.empty() && !image.empty()) || (markerCorners.total() == markerIds.total()));
|
||||
vector<vector<Point2f>> tmpMarkerCorners;
|
||||
vector<int> tmpMarkerIds;
|
||||
InputOutputArrayOfArrays _markerCorners = markerCorners.needed() ? markerCorners : tmpMarkerCorners;
|
||||
InputOutputArray _markerIds = markerIds.needed() ? markerIds : tmpMarkerIds;
|
||||
|
||||
if (markerCorners.empty() && markerIds.empty()) {
|
||||
vector<vector<Point2f> > rejectedMarkers;
|
||||
charucoDetectorImpl->arucoDetector.detectMarkers(image, _markerCorners, _markerIds, rejectedMarkers);
|
||||
if (charucoDetectorImpl->charucoParameters.tryRefineMarkers)
|
||||
charucoDetectorImpl->arucoDetector.refineDetectedMarkers(image, charucoDetectorImpl->board, _markerCorners,
|
||||
_markerIds, rejectedMarkers);
|
||||
charucoDetectorImpl->detectBoard(image, charucoCorners, charucoIds, markerCorners, markerIds);
|
||||
if (charucoDetectorImpl->checkBoard(markerCorners, markerIds, charucoCorners, charucoIds) == false) {
|
||||
charucoCorners.release();
|
||||
charucoIds.release();
|
||||
}
|
||||
// if camera parameters are avaible, use approximated calibration
|
||||
if(!charucoDetectorImpl->charucoParameters.cameraMatrix.empty())
|
||||
charucoDetectorImpl->interpolateCornersCharucoApproxCalib(_markerCorners, _markerIds, image, charucoCorners,
|
||||
charucoIds);
|
||||
// else use local homography
|
||||
else
|
||||
charucoDetectorImpl->interpolateCornersCharucoLocalHom(_markerCorners, _markerIds, image, charucoCorners,
|
||||
charucoIds);
|
||||
// to return a charuco corner, its closest aruco markers should have been detected
|
||||
charucoDetectorImpl->filterCornersWithoutMinMarkers(charucoCorners, charucoIds, _markerIds, charucoCorners,
|
||||
charucoIds);
|
||||
}
|
||||
|
||||
void CharucoDetector::detectDiamonds(InputArray image, OutputArrayOfArrays _diamondCorners, OutputArray _diamondIds,
|
||||
InputOutputArrayOfArrays inMarkerCorners, InputOutputArrayOfArrays inMarkerIds) const {
|
||||
InputOutputArrayOfArrays inMarkerCorners, InputOutputArray inMarkerIds) const {
|
||||
CV_Assert(getBoard().getChessboardSize() == Size(3, 3));
|
||||
CV_Assert((inMarkerCorners.empty() && inMarkerIds.empty() && !image.empty()) || (inMarkerCorners.total() == inMarkerIds.total()));
|
||||
|
||||
@@ -416,7 +470,7 @@ void CharucoDetector::detectDiamonds(InputArray image, OutputArrayOfArrays _diam
|
||||
// interpolate the charuco corners of the diamond
|
||||
vector<Point2f> currentMarkerCorners;
|
||||
Mat aux;
|
||||
detectBoard(grey, currentMarkerCorners, aux, currentMarker, currentMarkerId);
|
||||
charucoDetectorImpl->detectBoard(grey, currentMarkerCorners, aux, currentMarker, currentMarkerId);
|
||||
|
||||
// if everything is ok, save the diamond
|
||||
if(currentMarkerCorners.size() > 0ull) {
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
|
||||
#include "../../precomp.hpp"
|
||||
#include "super_scale.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/core/utils/logger.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace barcode {
|
||||
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
|
||||
constexpr static float MAX_SCALE = 4.0f;
|
||||
|
||||
int SuperScale::init(const std::string &proto_path, const std::string &model_path)
|
||||
@@ -71,7 +74,26 @@ int SuperScale::superResolutionScale(const Mat &src, Mat &dst)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else // HAVE_OPENCV_DNN
|
||||
|
||||
int SuperScale::init(const std::string &proto_path, const std::string &model_path)
|
||||
{
|
||||
CV_UNUSED(proto_path);
|
||||
CV_UNUSED(model_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SuperScale::processImageScale(const Mat &src, Mat &dst, float scale, const bool & isEnabled, int sr_max_size)
|
||||
{
|
||||
CV_UNUSED(sr_max_size);
|
||||
if (isEnabled)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "objdetect/barcode: SuperScaling disabled - OpenCV has been built without DNN support");
|
||||
}
|
||||
resize(src, dst, Size(), scale, scale, INTER_CUBIC);
|
||||
}
|
||||
#endif // HAVE_OPENCV_DNN
|
||||
|
||||
} // namespace barcode
|
||||
} // namespace cv
|
||||
|
||||
#endif // HAVE_OPENCV_DNN
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
#define OPENCV_BARCODE_SUPER_SCALE_HPP
|
||||
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
|
||||
#include "opencv2/dnn.hpp"
|
||||
# include "opencv2/dnn.hpp"
|
||||
#endif
|
||||
|
||||
namespace cv {
|
||||
namespace barcode {
|
||||
@@ -26,44 +26,16 @@ public:
|
||||
|
||||
void processImageScale(const Mat &src, Mat &dst, float scale, const bool &use_sr, int sr_max_size = 160);
|
||||
|
||||
#ifdef HAVE_OPENCV_DNN
|
||||
private:
|
||||
dnn::Net srnet_;
|
||||
bool net_loaded_ = false;
|
||||
|
||||
int superResolutionScale(const cv::Mat &src, cv::Mat &dst);
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace barcode
|
||||
} // namespace cv
|
||||
|
||||
#else // HAVE_OPENCV_DNN
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/core/utils/logger.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace barcode {
|
||||
|
||||
class SuperScale
|
||||
{
|
||||
public:
|
||||
int init(const std::string &, const std::string &)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void processImageScale(const Mat &src, Mat &dst, float scale, const bool & isEnabled, int)
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "objdetect/barcode: SuperScaling disabled - OpenCV has been built without DNN support");
|
||||
}
|
||||
resize(src, dst, Size(), scale, scale, INTER_CUBIC);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace barcode
|
||||
} // namespace cv
|
||||
|
||||
#endif // !HAVE_OPENCV_DNN
|
||||
} // namespace barcode
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_BARCODE_SUPER_SCALE_HPP
|
||||
|
||||
@@ -689,4 +689,32 @@ TEST(Charuco, testmatchImagePoints)
|
||||
}
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<cv::Size> CharucoBoard;
|
||||
INSTANTIATE_TEST_CASE_P(/**/, CharucoBoard, testing::Values(Size(3, 2), Size(3, 2), Size(6, 2), Size(2, 6),
|
||||
Size(3, 4), Size(4, 3), Size(7, 3), Size(3, 7)));
|
||||
TEST_P(CharucoBoard, testWrongSizeDetection)
|
||||
{
|
||||
cv::Size boardSize = GetParam();
|
||||
ASSERT_FALSE(boardSize.width == boardSize.height);
|
||||
aruco::CharucoBoard board(boardSize, 1.f, 0.5f, aruco::getPredefinedDictionary(aruco::DICT_4X4_50));
|
||||
|
||||
vector<int> detectedCharucoIds, detectedArucoIds;
|
||||
vector<Point2f> detectedCharucoCorners;
|
||||
vector<vector<Point2f>> detectedArucoCorners;
|
||||
Mat boardImage;
|
||||
board.generateImage(boardSize*40, boardImage);
|
||||
|
||||
swap(boardSize.width, boardSize.height);
|
||||
aruco::CharucoDetector detector(aruco::CharucoBoard(boardSize, 1.f, 0.5f, aruco::getPredefinedDictionary(aruco::DICT_4X4_50)));
|
||||
// try detect board with wrong size
|
||||
detector.detectBoard(boardImage, detectedCharucoCorners, detectedCharucoIds, detectedArucoCorners, detectedArucoIds);
|
||||
|
||||
// aruco markers must be found
|
||||
ASSERT_EQ(detectedArucoIds.size(), board.getIds().size());
|
||||
ASSERT_EQ(detectedArucoCorners.size(), board.getIds().size());
|
||||
// charuco corners should not be found in board with wrong size
|
||||
ASSERT_TRUE(detectedCharucoCorners.empty());
|
||||
ASSERT_TRUE(detectedCharucoIds.empty());
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -10,6 +10,9 @@ void check_qr(const string& root, const string& name_current_image, const string
|
||||
const std::vector<Point>& corners,
|
||||
const std::vector<string>& decoded_info, const int max_pixel_error,
|
||||
bool isMulti = false) {
|
||||
#ifndef HAVE_QUIRC
|
||||
CV_UNUSED(decoded_info);
|
||||
#endif
|
||||
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;
|
||||
|
||||
@@ -374,8 +374,8 @@ TEST_P(Objdetect_QRCode_Multi, regression)
|
||||
qrcode = QRCodeDetectorAruco();
|
||||
}
|
||||
std::vector<Point> corners;
|
||||
#ifdef HAVE_QUIRC
|
||||
std::vector<cv::String> decoded_info;
|
||||
#ifdef HAVE_QUIRC
|
||||
std::vector<Mat> straight_barcode;
|
||||
EXPECT_TRUE(qrcode.detectAndDecodeMulti(src, decoded_info, corners, straight_barcode));
|
||||
ASSERT_FALSE(corners.empty());
|
||||
@@ -538,7 +538,6 @@ TEST(Objdetect_QRCode_detect_flipped, regression_23249)
|
||||
|
||||
for(const auto &flipped_image : flipped_images){
|
||||
const std::string &image_name = flipped_image.first;
|
||||
const std::string &expect_msg = flipped_image.second;
|
||||
|
||||
std::string image_path = findDataFile(root + image_name);
|
||||
Mat src = imread(image_path);
|
||||
@@ -551,6 +550,7 @@ TEST(Objdetect_QRCode_detect_flipped, regression_23249)
|
||||
EXPECT_TRUE(!corners.empty());
|
||||
std::string decoded_msg;
|
||||
#ifdef HAVE_QUIRC
|
||||
const std::string &expect_msg = flipped_image.second;
|
||||
EXPECT_NO_THROW(decoded_msg = qrcode.decode(src, corners, straight_barcode));
|
||||
ASSERT_FALSE(straight_barcode.empty()) << "Can't decode qrimage.";
|
||||
EXPECT_EQ(expect_msg, decoded_msg);
|
||||
|
||||
Reference in New Issue
Block a user