1
0
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:
Alexander Smorkalov
2026-04-23 11:00:34 +03:00
38 changed files with 3437 additions and 293 deletions
@@ -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,