|
|
|
@ -58,14 +58,14 @@ FrameProcessor::~FrameProcessor() |
|
|
|
|
bool CalibProcessor::detectAndParseChessboard(const cv::Mat &frame) |
|
|
|
|
{ |
|
|
|
|
int chessBoardFlags = cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE | cv::CALIB_CB_FAST_CHECK; |
|
|
|
|
bool isTemplateFound = cv::findChessboardCorners(frame, mBoardSize, mCurrentImagePoints, chessBoardFlags); |
|
|
|
|
bool isTemplateFound = cv::findChessboardCorners(frame, mBoardSizeInnerCorners, mCurrentImagePoints, chessBoardFlags); |
|
|
|
|
|
|
|
|
|
if (isTemplateFound) { |
|
|
|
|
cv::Mat viewGray; |
|
|
|
|
cv::cvtColor(frame, viewGray, cv::COLOR_BGR2GRAY); |
|
|
|
|
cv::cornerSubPix(viewGray, mCurrentImagePoints, cv::Size(11,11), |
|
|
|
|
cv::Size(-1,-1), cv::TermCriteria( cv::TermCriteria::EPS+cv::TermCriteria::COUNT, 30, 0.1 )); |
|
|
|
|
cv::drawChessboardCorners(frame, mBoardSize, cv::Mat(mCurrentImagePoints), isTemplateFound); |
|
|
|
|
cv::drawChessboardCorners(frame, mBoardSizeInnerCorners, cv::Mat(mCurrentImagePoints), isTemplateFound); |
|
|
|
|
mTemplateLocations.insert(mTemplateLocations.begin(), mCurrentImagePoints[0]); |
|
|
|
|
} |
|
|
|
|
return isTemplateFound; |
|
|
|
@ -101,20 +101,20 @@ bool CalibProcessor::detectAndParseChAruco(const cv::Mat &frame) |
|
|
|
|
|
|
|
|
|
bool CalibProcessor::detectAndParseCircles(const cv::Mat &frame) |
|
|
|
|
{ |
|
|
|
|
bool isTemplateFound = findCirclesGrid(frame, mBoardSize, mCurrentImagePoints, cv::CALIB_CB_SYMMETRIC_GRID, mBlobDetectorPtr); |
|
|
|
|
bool isTemplateFound = findCirclesGrid(frame, mBoardSizeUnits, mCurrentImagePoints, cv::CALIB_CB_SYMMETRIC_GRID, mBlobDetectorPtr); |
|
|
|
|
if(isTemplateFound) { |
|
|
|
|
mTemplateLocations.insert(mTemplateLocations.begin(), mCurrentImagePoints[0]); |
|
|
|
|
cv::drawChessboardCorners(frame, mBoardSize, cv::Mat(mCurrentImagePoints), isTemplateFound); |
|
|
|
|
cv::drawChessboardCorners(frame, mBoardSizeUnits, cv::Mat(mCurrentImagePoints), isTemplateFound); |
|
|
|
|
} |
|
|
|
|
return isTemplateFound; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool CalibProcessor::detectAndParseACircles(const cv::Mat &frame) |
|
|
|
|
{ |
|
|
|
|
bool isTemplateFound = findCirclesGrid(frame, mBoardSize, mCurrentImagePoints, cv::CALIB_CB_ASYMMETRIC_GRID, mBlobDetectorPtr); |
|
|
|
|
bool isTemplateFound = findCirclesGrid(frame, mBoardSizeUnits, mCurrentImagePoints, cv::CALIB_CB_ASYMMETRIC_GRID, mBlobDetectorPtr); |
|
|
|
|
if(isTemplateFound) { |
|
|
|
|
mTemplateLocations.insert(mTemplateLocations.begin(), mCurrentImagePoints[0]); |
|
|
|
|
cv::drawChessboardCorners(frame, mBoardSize, cv::Mat(mCurrentImagePoints), isTemplateFound); |
|
|
|
|
cv::drawChessboardCorners(frame, mBoardSizeUnits, cv::Mat(mCurrentImagePoints), isTemplateFound); |
|
|
|
|
} |
|
|
|
|
return isTemplateFound; |
|
|
|
|
} |
|
|
|
@ -125,18 +125,18 @@ bool CalibProcessor::detectAndParseDualACircles(const cv::Mat &frame) |
|
|
|
|
|
|
|
|
|
cv::Mat invertedView; |
|
|
|
|
cv::bitwise_not(frame, invertedView); |
|
|
|
|
bool isWhiteGridFound = cv::findCirclesGrid(frame, mBoardSize, mCurrentImagePoints, cv::CALIB_CB_ASYMMETRIC_GRID, mBlobDetectorPtr); |
|
|
|
|
bool isWhiteGridFound = cv::findCirclesGrid(frame, mBoardSizeUnits, mCurrentImagePoints, cv::CALIB_CB_ASYMMETRIC_GRID, mBlobDetectorPtr); |
|
|
|
|
if(!isWhiteGridFound) |
|
|
|
|
return false; |
|
|
|
|
bool isBlackGridFound = cv::findCirclesGrid(invertedView, mBoardSize, blackPointbuf, cv::CALIB_CB_ASYMMETRIC_GRID, mBlobDetectorPtr); |
|
|
|
|
bool isBlackGridFound = cv::findCirclesGrid(invertedView, mBoardSizeUnits, blackPointbuf, cv::CALIB_CB_ASYMMETRIC_GRID, mBlobDetectorPtr); |
|
|
|
|
|
|
|
|
|
if(!isBlackGridFound) |
|
|
|
|
{ |
|
|
|
|
mCurrentImagePoints.clear(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
cv::drawChessboardCorners(frame, mBoardSize, cv::Mat(mCurrentImagePoints), isWhiteGridFound); |
|
|
|
|
cv::drawChessboardCorners(frame, mBoardSize, cv::Mat(blackPointbuf), isBlackGridFound); |
|
|
|
|
cv::drawChessboardCorners(frame, mBoardSizeUnits, cv::Mat(mCurrentImagePoints), isWhiteGridFound); |
|
|
|
|
cv::drawChessboardCorners(frame, mBoardSizeUnits, cv::Mat(blackPointbuf), isBlackGridFound); |
|
|
|
|
mCurrentImagePoints.insert(mCurrentImagePoints.end(), blackPointbuf.begin(), blackPointbuf.end()); |
|
|
|
|
mTemplateLocations.insert(mTemplateLocations.begin(), mCurrentImagePoints[0]); |
|
|
|
|
|
|
|
|
@ -151,14 +151,14 @@ void CalibProcessor::saveFrameData() |
|
|
|
|
switch(mBoardType) |
|
|
|
|
{ |
|
|
|
|
case Chessboard: |
|
|
|
|
objectPoints.reserve(mBoardSize.height*mBoardSize.width); |
|
|
|
|
for( int i = 0; i < mBoardSize.height; ++i ) |
|
|
|
|
for( int j = 0; j < mBoardSize.width; ++j ) |
|
|
|
|
objectPoints.reserve(mBoardSizeInnerCorners.height*mBoardSizeInnerCorners.width); |
|
|
|
|
for( int i = 0; i < mBoardSizeInnerCorners.height; ++i ) |
|
|
|
|
for( int j = 0; j < mBoardSizeInnerCorners.width; ++j ) |
|
|
|
|
objectPoints.push_back(cv::Point3f(j*mSquareSize, i*mSquareSize, 0)); |
|
|
|
|
mCalibData->imagePoints.push_back(mCurrentImagePoints); |
|
|
|
|
mCalibData->objectPoints.push_back(objectPoints); |
|
|
|
|
break; |
|
|
|
|
case chAruco: |
|
|
|
|
case ChArUco: |
|
|
|
|
mCalibData->allCharucoCorners.push_back(mCurrentCharucoCorners); |
|
|
|
|
mCalibData->allCharucoIds.push_back(mCurrentCharucoIds); |
|
|
|
|
|
|
|
|
@ -168,38 +168,38 @@ void CalibProcessor::saveFrameData() |
|
|
|
|
mCalibData->objectPoints.push_back(objectPoints); |
|
|
|
|
break; |
|
|
|
|
case CirclesGrid: |
|
|
|
|
objectPoints.reserve(mBoardSize.height*mBoardSize.width); |
|
|
|
|
for( int i = 0; i < mBoardSize.height; i++ ) |
|
|
|
|
for( int j = 0; j < mBoardSize.width; j++ ) |
|
|
|
|
objectPoints.reserve(mBoardSizeUnits.height*mBoardSizeUnits.width); |
|
|
|
|
for( int i = 0; i < mBoardSizeUnits.height; i++ ) |
|
|
|
|
for( int j = 0; j < mBoardSizeUnits.width; j++ ) |
|
|
|
|
objectPoints.push_back(cv::Point3f(j*mSquareSize, i*mSquareSize, 0)); |
|
|
|
|
mCalibData->imagePoints.push_back(mCurrentImagePoints); |
|
|
|
|
mCalibData->objectPoints.push_back(objectPoints); |
|
|
|
|
break; |
|
|
|
|
case AcirclesGrid: |
|
|
|
|
objectPoints.reserve(mBoardSize.height*mBoardSize.width); |
|
|
|
|
for( int i = 0; i < mBoardSize.height; i++ ) |
|
|
|
|
for( int j = 0; j < mBoardSize.width; j++ ) |
|
|
|
|
objectPoints.reserve(mBoardSizeUnits.height*mBoardSizeUnits.width); |
|
|
|
|
for( int i = 0; i < mBoardSizeUnits.height; i++ ) |
|
|
|
|
for( int j = 0; j < mBoardSizeUnits.width; j++ ) |
|
|
|
|
objectPoints.push_back(cv::Point3f((2*j + i % 2)*mSquareSize, i*mSquareSize, 0)); |
|
|
|
|
mCalibData->imagePoints.push_back(mCurrentImagePoints); |
|
|
|
|
mCalibData->objectPoints.push_back(objectPoints); |
|
|
|
|
break; |
|
|
|
|
case DoubleAcirclesGrid: |
|
|
|
|
{ |
|
|
|
|
float gridCenterX = (2*((float)mBoardSize.width - 1) + 1)*mSquareSize + mTemplDist / 2; |
|
|
|
|
float gridCenterY = (mBoardSize.height - 1)*mSquareSize / 2; |
|
|
|
|
objectPoints.reserve(2*mBoardSize.height*mBoardSize.width); |
|
|
|
|
float gridCenterX = (2*((float)mBoardSizeUnits.width - 1) + 1)*mSquareSize + mTemplDist / 2; |
|
|
|
|
float gridCenterY = (mBoardSizeUnits.height - 1)*mSquareSize / 2; |
|
|
|
|
objectPoints.reserve(2*mBoardSizeUnits.height*mBoardSizeUnits.width); |
|
|
|
|
|
|
|
|
|
//white part
|
|
|
|
|
for( int i = 0; i < mBoardSize.height; i++ ) |
|
|
|
|
for( int j = 0; j < mBoardSize.width; j++ ) |
|
|
|
|
for( int i = 0; i < mBoardSizeUnits.height; i++ ) |
|
|
|
|
for( int j = 0; j < mBoardSizeUnits.width; j++ ) |
|
|
|
|
objectPoints.push_back( |
|
|
|
|
cv::Point3f(-float((2*j + i % 2)*mSquareSize + mTemplDist + |
|
|
|
|
(2*(mBoardSize.width - 1) + 1)*mSquareSize - gridCenterX), |
|
|
|
|
(2*(mBoardSizeUnits.width - 1) + 1)*mSquareSize - gridCenterX), |
|
|
|
|
-float(i*mSquareSize) - gridCenterY, |
|
|
|
|
0)); |
|
|
|
|
//black part
|
|
|
|
|
for( int i = 0; i < mBoardSize.height; i++ ) |
|
|
|
|
for( int j = 0; j < mBoardSize.width; j++ ) |
|
|
|
|
for( int i = 0; i < mBoardSizeUnits.height; i++ ) |
|
|
|
|
for( int j = 0; j < mBoardSizeUnits.width; j++ ) |
|
|
|
|
objectPoints.push_back(cv::Point3f(-float((2*j + i % 2)*mSquareSize - gridCenterX), |
|
|
|
|
-float(i*mSquareSize) - gridCenterY, 0)); |
|
|
|
|
|
|
|
|
@ -261,7 +261,8 @@ bool CalibProcessor::checkLastFrame() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CalibProcessor::CalibProcessor(cv::Ptr<calibrationData> data, captureParameters &capParams) : |
|
|
|
|
mCalibData(data), mBoardType(capParams.board), mBoardSize(capParams.boardSize) |
|
|
|
|
mCalibData(data), mBoardType(capParams.board), mBoardSizeUnits(capParams.boardSizeUnits), |
|
|
|
|
mBoardSizeInnerCorners(capParams.boardSizeInnerCorners) |
|
|
|
|
{ |
|
|
|
|
mCapuredFrames = 0; |
|
|
|
|
mNeededFramesNum = capParams.calibrationStep; |
|
|
|
@ -277,10 +278,18 @@ CalibProcessor::CalibProcessor(cv::Ptr<calibrationData> data, captureParameters |
|
|
|
|
|
|
|
|
|
switch(mBoardType) |
|
|
|
|
{ |
|
|
|
|
case chAruco: |
|
|
|
|
mArucoDictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PredefinedDictionaryType(capParams.charucoDictName)); |
|
|
|
|
mCharucoBoard = cv::makePtr<cv::aruco::CharucoBoard>(cv::Size(mBoardSize.width + 1, mBoardSize.height + 1), capParams.charucoSquareLength, |
|
|
|
|
capParams.charucoMarkerSize, mArucoDictionary); |
|
|
|
|
case ChArUco: |
|
|
|
|
if (capParams.charucoDictFile != "None") { |
|
|
|
|
std::string filename = capParams.charucoDictFile; |
|
|
|
|
cv::FileStorage dict_file(filename, cv::FileStorage::Mode::READ); |
|
|
|
|
cv::FileNode fn(dict_file.root()); |
|
|
|
|
mArucoDictionary.readDictionary(fn); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
mArucoDictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PredefinedDictionaryType(capParams.charucoDictName)); |
|
|
|
|
} |
|
|
|
|
mCharucoBoard = cv::makePtr<cv::aruco::CharucoBoard>(cv::Size(mBoardSizeUnits.width, mBoardSizeUnits.height), capParams.charucoSquareLength, |
|
|
|
|
capParams.charucoMarkerSize, mArucoDictionary); |
|
|
|
|
detector = cv::makePtr<cv::aruco::CharucoDetector>(cv::aruco::CharucoDetector(*mCharucoBoard, charucoParameters)); |
|
|
|
|
break; |
|
|
|
|
case CirclesGrid: |
|
|
|
@ -311,7 +320,7 @@ cv::Mat CalibProcessor::processFrame(const cv::Mat &frame) |
|
|
|
|
case Chessboard: |
|
|
|
|
isTemplateFound = detectAndParseChessboard(frameCopy); |
|
|
|
|
break; |
|
|
|
|
case chAruco: |
|
|
|
|
case ChArUco: |
|
|
|
|
isTemplateFound = detectAndParseChAruco(frameCopy); |
|
|
|
|
break; |
|
|
|
|
case CirclesGrid: |
|
|
|
@ -391,7 +400,7 @@ void ShowProcessor::drawBoard(cv::Mat &img, cv::InputArray points) |
|
|
|
|
|
|
|
|
|
void ShowProcessor::drawGridPoints(const cv::Mat &frame) |
|
|
|
|
{ |
|
|
|
|
if(mBoardType != chAruco) |
|
|
|
|
if(mBoardType != ChArUco) |
|
|
|
|
for(std::vector<std::vector<cv::Point2f> >::iterator it = mCalibdata->imagePoints.begin(); it != mCalibdata->imagePoints.end(); ++it) |
|
|
|
|
for(std::vector<cv::Point2f>::iterator pointIt = (*it).begin(); pointIt != (*it).end(); ++pointIt) |
|
|
|
|
cv::circle(frame, *pointIt, POINT_SIZE, cv::Scalar(0, 255, 0), 1, cv::LINE_AA); |
|
|
|
@ -513,7 +522,7 @@ void ShowProcessor::updateBoardsView() |
|
|
|
|
if(mVisMode == Window) { |
|
|
|
|
cv::Size originSize = mCalibdata->imageSize; |
|
|
|
|
cv::Mat altGridView = cv::Mat::zeros((int)(originSize.height*mGridViewScale), (int)(originSize.width*mGridViewScale), CV_8UC3); |
|
|
|
|
if(mBoardType != chAruco) |
|
|
|
|
if(mBoardType != ChArUco) |
|
|
|
|
for(std::vector<std::vector<cv::Point2f> >::iterator it = mCalibdata->imagePoints.begin(); it != mCalibdata->imagePoints.end(); ++it) |
|
|
|
|
if(mBoardType != DoubleAcirclesGrid) |
|
|
|
|
drawBoard(altGridView, *it); |
|
|
|
|