mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
Merge branch 4.x
This commit is contained in:
@@ -235,34 +235,30 @@ Mat Dictionary::getBitsFromByteList(const Mat &byteList, int markerSize, int rot
|
||||
CV_Assert(byteList.channels() >= 4);
|
||||
CV_Assert(rotationId >= 0 && rotationId < 4);
|
||||
|
||||
Mat bits(markerSize, markerSize, CV_8UC1, Scalar::all(0));
|
||||
|
||||
unsigned char base2List[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
|
||||
Mat bits = Mat::zeros(markerSize, markerSize, CV_8UC1);
|
||||
unsigned char *bitsPtr = bits.ptr();
|
||||
|
||||
// Use a base offset for the selected rotation
|
||||
int nbytes = (bits.cols * bits.rows + 8 - 1) / 8; // integer ceil
|
||||
int base = rotationId * nbytes;
|
||||
int currentByteIdx = 0;
|
||||
unsigned char currentByte = byteList.ptr()[base + currentByteIdx];
|
||||
int currentBit = 0;
|
||||
const unsigned char *currentBytePtr = byteList.ptr() + base;
|
||||
const unsigned char *currentBytePtrEnd = currentBytePtr + bits.total() / 8;
|
||||
|
||||
for(int row = 0; row < bits.rows; row++) {
|
||||
for(int col = 0; col < bits.cols; col++) {
|
||||
if(currentByte >= base2List[currentBit]) {
|
||||
bits.at<unsigned char>(row, col) = 1;
|
||||
currentByte -= base2List[currentBit];
|
||||
}
|
||||
currentBit++;
|
||||
if(currentBit == 8) {
|
||||
currentByteIdx++;
|
||||
currentByte = byteList.ptr()[base + currentByteIdx];
|
||||
// if not enough bits for one more byte, we are in the end
|
||||
// update bit position accordingly
|
||||
if(8 * (currentByteIdx + 1) > (int)bits.total())
|
||||
currentBit = 8 * (currentByteIdx + 1) - (int)bits.total();
|
||||
else
|
||||
currentBit = 0; // ok, bits enough for next byte
|
||||
}
|
||||
for(;currentBytePtr < currentBytePtrEnd; ++currentBytePtr) {
|
||||
unsigned char currentByte = *currentBytePtr;
|
||||
for(int mask = 1 << 7; mask != 0; mask >>= 1) {
|
||||
if (currentByte & mask) *bitsPtr = 1;
|
||||
++bitsPtr;
|
||||
}
|
||||
}
|
||||
// if not enough bits for one more byte, we are in the end
|
||||
// update bit position accordingly
|
||||
if (bits.total() % 8 != 0) {
|
||||
unsigned char currentByte = *currentBytePtrEnd;
|
||||
int mask = 1 << ((bits.total() % 8) - 1);
|
||||
for(; mask != 0; mask >>= 1) {
|
||||
if (currentByte & mask) *bitsPtr = 1;
|
||||
++bitsPtr;
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
|
||||
@@ -414,7 +414,12 @@ void CharucoDetector::detectDiamonds(InputArray image, OutputArrayOfArrays _diam
|
||||
|
||||
// stores if the detected markers have been assigned or not to a diamond
|
||||
vector<bool> assigned(_markerIds.total(), false);
|
||||
if(_markerIds.total() < 4ull) return; // a diamond need at least 4 markers
|
||||
if(_markerIds.total() < 4ull)
|
||||
{
|
||||
if (_diamondCorners.needed()) _diamondCorners.release();
|
||||
if (_diamondIds.needed()) _diamondIds.release();
|
||||
return; // a diamond need at least 4 markers
|
||||
}
|
||||
|
||||
// convert input image to grey
|
||||
Mat grey;
|
||||
@@ -522,16 +527,27 @@ void CharucoDetector::detectDiamonds(InputArray image, OutputArrayOfArrays _diam
|
||||
|
||||
if(diamondIds.size() > 0ull) {
|
||||
// parse output
|
||||
Mat(diamondIds).copyTo(_diamondIds);
|
||||
if (_diamondIds.needed())
|
||||
{
|
||||
Mat(diamondIds).copyTo(_diamondIds);
|
||||
}
|
||||
|
||||
_diamondCorners.create((int)diamondCorners.size(), 1, CV_32FC2);
|
||||
for(unsigned int i = 0; i < diamondCorners.size(); i++) {
|
||||
_diamondCorners.create(4, 1, CV_32FC2, i, true);
|
||||
for(int j = 0; j < 4; j++) {
|
||||
_diamondCorners.getMat(i).at<Point2f>(j) = diamondCorners[i][j];
|
||||
if (_diamondCorners.needed())
|
||||
{
|
||||
_diamondCorners.create((int)diamondCorners.size(), 1, CV_32FC2);
|
||||
for(unsigned int i = 0; i < diamondCorners.size(); i++) {
|
||||
_diamondCorners.create(4, 1, CV_32FC2, i, true);
|
||||
for(int j = 0; j < 4; j++) {
|
||||
_diamondCorners.getMat(i).at<Point2f>(j) = diamondCorners[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_diamondCorners.needed()) _diamondCorners.release();
|
||||
if (_diamondIds.needed()) _diamondIds.release();
|
||||
}
|
||||
}
|
||||
|
||||
void drawDetectedCornersCharuco(InputOutputArray _image, InputArray _charucoCorners,
|
||||
|
||||
@@ -705,6 +705,27 @@ TEST(Charuco, testmatchImagePoints)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Charuco, detectDiamondsClearsOutputsWithLessThanFourMarkers)
|
||||
{
|
||||
aruco::CharucoBoard board(Size(3, 3), 1.f, 0.5f, aruco::getPredefinedDictionary(aruco::DICT_4X4_50));
|
||||
aruco::CharucoDetector detector(board);
|
||||
|
||||
vector<vector<Point2f>> markerCorners = {
|
||||
{Point2f(10.f, 10.f), Point2f(20.f, 10.f), Point2f(20.f, 20.f), Point2f(10.f, 20.f)},
|
||||
{Point2f(30.f, 10.f), Point2f(40.f, 10.f), Point2f(40.f, 20.f), Point2f(30.f, 20.f)},
|
||||
{Point2f(10.f, 30.f), Point2f(20.f, 30.f), Point2f(20.f, 40.f), Point2f(10.f, 40.f)}
|
||||
};
|
||||
vector<int> markerIds = {0, 1, 2};
|
||||
|
||||
vector<vector<Point2f>> diamondCorners = {{Point2f(1.f, 1.f), Point2f(2.f, 1.f), Point2f(2.f, 2.f), Point2f(1.f, 2.f)}};
|
||||
vector<Vec4i> diamondIds = {Vec4i(0, 1, 2, 3)};
|
||||
|
||||
detector.detectDiamonds(Mat(), diamondCorners, diamondIds, markerCorners, markerIds);
|
||||
|
||||
EXPECT_TRUE(diamondCorners.empty());
|
||||
EXPECT_TRUE(diamondIds.empty());
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<int> CharucoDraw;
|
||||
INSTANTIATE_TEST_CASE_P(/**/, CharucoDraw, testing::Values(CV_8UC2, CV_8SC2, CV_16UC2, CV_16SC2, CV_32SC2, CV_32FC2, CV_64FC2));
|
||||
TEST_P(CharucoDraw, testDrawDetected) {
|
||||
|
||||
Reference in New Issue
Block a user