Compare commits

..

No commits in common. "d80e48fb65a4981c49082cf5d15390ffe44a164d" and "d51b0f23a02e8531b25918a9509d45310eb21f48" have entirely different histories.

3 changed files with 133 additions and 179 deletions

View File

@ -29,7 +29,7 @@ void sg_outputCalibK(const char* fileName, cv::Mat& fitMap)
return; return;
} }
void sg_outputCalibKD(const char* fileName, cv::Mat& K, cv::Mat& D, cv::Vec4f& pe) void sg_outputCalibKD(const char* fileName, cv::Mat& K, cv::Mat& D)
{ {
std::ofstream sw(fileName); std::ofstream sw(fileName);
@ -50,20 +50,6 @@ void sg_outputCalibKD(const char* fileName, cv::Mat& K, cv::Mat& D, cv::Vec4f& p
temp[_c] = D.ptr<double>(0)[_c]; temp[_c] = D.ptr<double>(0)[_c];
sprintf_s(dataStr, 250, "%g, %g, %g, %g, %g", temp[0], temp[1], temp[2], temp[3], temp[4]); sprintf_s(dataStr, 250, "%g, %g, %g, %g, %g", temp[0], temp[1], temp[2], temp[3], temp[4]);
sw << dataStr << std::endl; sw << dataStr << std::endl;
//ax+by+cz+d = 0
float a = (float)pe[0];
float b = (float)pe[1];
float c = (float)pe[2];
float d = (float)pe[3];
//将c变成-1转成z=ax+by+c的形式使用3个参数
a = -a / c;
b = -b / c;
d = -d / c;
c = -1;
sprintf_s(dataStr, 250, "%g, %g, %g", a, b, d);
sw << dataStr << std::endl;
sw.close(); sw.close();
return; return;
} }
@ -101,24 +87,6 @@ void sg_readCalibKD(const char* fileName, cv::Mat& K, cv::Mat& D)
return; return;
} }
void saveSubpixData(char* filename, std::vector<cv::Point2f>& subpixPnt)
{
if (subpixPnt.size() < 6)
return;
std::ofstream TXTFile(filename);
char TXTData[250];
int headOffset = 6;
for (int i = 6, i_max = (int)subpixPnt.size(); i < i_max; i++)
{
cv::Point2f a_subPix = subpixPnt[i];
snprintf(TXTData, sizeof(TXTData), "%.5f %.5f", a_subPix.x, a_subPix.y);
TXTFile << TXTData << std::endl;
}
TXTFile.close();
}
typedef struct typedef struct
{ {
int nMin; //< 最小值 int nMin; //< 最小值
@ -162,13 +130,13 @@ int main()
std::cout << "Hello World!\n"; std::cout << "Hello World!\n";
const char* calibDataPath[CALIB_TEST_GROUP] = { const char* calibDataPath[CALIB_TEST_GROUP] = {
"F:\\ShangGu\\ProductDev\\三角光相机\\相机开发\\CamAlgo_git\\camCalib\\camCalibData\\撕裂原理相机标定图像\\", //0 "F:\\ShangGu\\ProductDev\\三角光相机\\相机开发\\CamAlgo\\camCalib\\camCalibData\\撕裂原理相机标定图像\\", //0
"F:\\ShangGu\\ProductDev\\三角光相机\\相机开发\\CamAlgo_git\\camCalib\\camCalibData\\chessboard\\", //1 "F:\\ShangGu\\ProductDev\\三角光相机\\相机开发\\CamAlgo\\camCalib\\camCalibData\\chessboard\\", //1
"F:\\ShangGu\\ProductDev\\三角光相机\\相机开发\\CamAlgo_git\\camCalib\\camCalibData\\circlePoint\\", //2 "F:\\ShangGu\\ProductDev\\三角光相机\\相机开发\\CamAlgo\\camCalib\\camCalibData\\circlePoint\\", //2
"F:\\ShangGu\\ProductDev\\三角光相机\\相机开发\\CamAlgo_git\\camCalib\\camCalibData\\charuCo\\", //3 "F:\\ShangGu\\ProductDev\\三角光相机\\相机开发\\CamAlgo\\camCalib\\camCalibData\\charuCo\\", //3
}; };
const SWdNLRange fileIdx[CALIB_TEST_GROUP] = { const SWdNLRange fileIdx[CALIB_TEST_GROUP] = {
{3,39},{1,33},{1,33},{1,10} {3,39},{1,200},{1,166},{122,141}
}; };
const int boardType[CALIB_TEST_GROUP] = const int boardType[CALIB_TEST_GROUP] =
{ {
@ -180,7 +148,7 @@ int main()
for(int grp = 0; grp < CALIB_TEST_GROUP; grp ++) for(int grp = 0; grp < CALIB_TEST_GROUP; grp ++)
{ {
grp = 1; grp = 2;
int calibType = boardType[grp]; int calibType = boardType[grp];
cv::Size cbPattern; cv::Size cbPattern;
float cbSquareSize; float cbSquareSize;
@ -315,7 +283,9 @@ int main()
std::cout << "Y Mean difference: " << meanVal_y[0] << std::endl; std::cout << "Y Mean difference: " << meanVal_y[0] << std::endl;
//生成矫正图像 //生成矫正图像
for (index = startIndex; index <= endIndex; index++) { index = 3;
for (;; index++) {
char filename[256]; char filename[256];
sprintf_s(filename, "%scalib_%03d.bmp", calibDataPath[grp], index); sprintf_s(filename, "%scalib_%03d.bmp", calibDataPath[grp], index);
cv::Mat srcImg = cv::imread(filename); cv::Mat srcImg = cv::imread(filename);
@ -336,6 +306,10 @@ int main()
cv::imwrite(filename, calibImg); cv::imwrite(filename, calibImg);
} }
//output K and D
char calibKDName[256];
sprintf_s(calibKDName, "%scalib_param_K_D.txt", calibDataPath[grp]);
sg_outputCalibKD(calibKDName, K, D);
#else #else
char calibKDName[256]; char calibKDName[256];
sprintf_s(calibKDName, "%scalib_param_K_D.txt", cbImagePath); sprintf_s(calibKDName, "%scalib_param_K_D.txt", cbImagePath);
@ -380,156 +354,136 @@ int main()
#endif #endif
std::vector<cv::Point3f> all_pts3d; {
for (index = startIndex; index <= endIndex; index++) { std::vector<cv::Point3f> all_pts3d;
char filename[256]; index = 3;
sprintf_s(filename, "%scalib_%03d.bmp", calibDataPath[grp], index); for (;; index++) {
cv::Mat srcImg = cv::imread(filename);
if (srcImg.empty())
break;
cv::Mat img; char filename[256];
cv::rotate(srcImg, img, cv::ROTATE_90_COUNTERCLOCKWISE); sprintf_s(filename, "%scalib_%03d.bmp", calibDataPath[grp], index);
std::vector<cv::Point2f> corners; cv::Mat srcImg = cv::imread(filename);
detectCorners(img, cbPattern, corners); if (srcImg.empty())
if (corners.empty()) break;
continue;
// 创建棋盘格区域的掩码 cv::Mat img;
cv::Mat chessMask = cv::Mat::zeros(img.size(), CV_8UC1); cv::rotate(srcImg, img, cv::ROTATE_90_COUNTERCLOCKWISE);
// 使用多边形近似来填充角点之间的区域 std::vector<cv::Point2f> corners;
// 棋盘格区域需要比角点区域大一圈 detectCorners(img, cbPattern, corners);
std::vector<cv::Point2f> contour_line[4]; if (corners.empty())
for (int i = 0; i < cbPattern.width; i++) continue;
{
cv::Point2f pt_c = corners[i]; // 创建棋盘格区域的掩码
cv::Point2f pt_2 = corners[cbPattern.width + i]; cv::Mat chessMask = cv::Mat::zeros(img.size(), CV_8UC1);
cv::Point2f pt_1; // 使用多边形近似来填充角点之间的区域
pt_1.x = pt_c.x * 2 - pt_2.x; // 棋盘格区域需要比角点区域大一圈
pt_1.y = pt_c.y * 2 - pt_2.y; std::vector<cv::Point2f> contour_line[4];
contour_line[0].push_back(pt_1); for (int i = 0; i < cbPattern.width; i++)
} {
for (int i = 0; i < cbPattern.height; i++) cv::Point2f pt_c = corners[i];
{ cv::Point2f pt_2 = corners[cbPattern.width + i];
cv::Point2f pt_c = corners[i * cbPattern.width + cbPattern.width - 1]; cv::Point2f pt_1;
cv::Point2f pt_2 = corners[i * cbPattern.width + cbPattern.width - 2]; pt_1.x = pt_c.x * 2 - pt_2.x;
cv::Point2f pt_1; pt_1.y = pt_c.y * 2 - pt_2.y;
pt_1.x = pt_c.x * 2 - pt_2.x; contour_line[0].push_back(pt_1);
pt_1.y = pt_c.y * 2 - pt_2.y; }
contour_line[1].push_back(pt_1); for (int i = 0; i < cbPattern.height; i++)
} {
for (int i = cbPattern.width - 1; i >= 0; i--) cv::Point2f pt_c = corners[i * cbPattern.width + cbPattern.width - 1];
{ cv::Point2f pt_2 = corners[i * cbPattern.width + cbPattern.width - 2];
cv::Point2f pt_c = corners[(cbPattern.height - 1) * cbPattern.width + i]; cv::Point2f pt_1;
cv::Point2f pt_2 = corners[(cbPattern.height - 2) * cbPattern.width + i]; pt_1.x = pt_c.x * 2 - pt_2.x;
cv::Point2f pt_1; pt_1.y = pt_c.y * 2 - pt_2.y;
pt_1.x = pt_c.x * 2 - pt_2.x; contour_line[1].push_back(pt_1);
pt_1.y = pt_c.y * 2 - pt_2.y; }
contour_line[2].push_back(pt_1); for (int i = cbPattern.width - 1; i >= 0; i--)
} {
for (int i = cbPattern.height-1; i >= 0; i--) cv::Point2f pt_c = corners[(cbPattern.height - 1) * cbPattern.width + i];
{ cv::Point2f pt_2 = corners[(cbPattern.height - 2) * cbPattern.width + i];
cv::Point2f pt_c = corners[i * cbPattern.width]; cv::Point2f pt_1;
cv::Point2f pt_2 = corners[i * cbPattern.width + 1]; pt_1.x = pt_c.x * 2 - pt_2.x;
cv::Point2f pt_1; pt_1.y = pt_c.y * 2 - pt_2.y;
pt_1.x = pt_c.x * 2 - pt_2.x; contour_line[2].push_back(pt_1);
pt_1.y = pt_c.y * 2 - pt_2.y; }
contour_line[3].push_back(pt_1); for (int i = cbPattern.height-1; i >= 0; i--)
} {
std::vector<cv::Point> contours; cv::Point2f pt_c = corners[i * cbPattern.width];
//生成轮廓点 cv::Point2f pt_2 = corners[i * cbPattern.width + 1];
for (int n = 0; n < 4; n++) cv::Point2f pt_1;
{ pt_1.x = pt_c.x * 2 - pt_2.x;
int num = contour_line[n].size(); pt_1.y = pt_c.y * 2 - pt_2.y;
for (int i = 0; i < num; i++) contour_line[3].push_back(pt_1);
contours.push_back(contour_line[n][i]); }
cv::Point2f pt_c = contour_line[n][num - 1]; std::vector<cv::Point> contours;
cv::Point2f pt_2 = contour_line[n][num - 2]; //生成轮廓点
cv::Point2f pt_1; for (int n = 0; n < 4; n++)
pt_1.x = pt_c.x * 2 - pt_2.x; {
pt_1.y = pt_c.y * 2 - pt_2.y; int num = contour_line[n].size();
contours.push_back(pt_1); for (int i = 0; i < num; i++)
} contours.push_back(contour_line[n][i]);
// 使用 fillPoly 填充多边形 cv::Point2f pt_c = contour_line[n][num - 1];
cv::Scalar color(255); // 红色 cv::Point2f pt_2 = contour_line[n][num - 2];
cv::fillPoly(chessMask, contours, color); cv::Point2f pt_1;
pt_1.x = pt_c.x * 2 - pt_2.x;
pt_1.y = pt_c.y * 2 - pt_2.y;
contours.push_back(pt_1);
}
// 使用 fillPoly 填充多边形
cv::Scalar color(255); // 红色
cv::fillPoly(chessMask, contours, color);
#if 1 #if 1
sprintf_s(filename, "%schessMask_%03d.png", calibDataPath[grp], index); sprintf_s(filename, "%schessMask_%03d.png", calibDataPath[grp], index);
cv::imwrite(filename, chessMask); cv::imwrite(filename, chessMask);
#endif #endif
cv::Vec4f pe; cv::Vec4f pe;
fitChessboardPlane(corners, K, D, cbPattern, cbSquareSize, pe); fitChessboardPlane(corners, K, D, cbPattern, cbSquareSize, pe);
sprintf_s(filename, "%slaser_%03d.bmp", calibDataPath[grp], index); sprintf_s(filename, "%slaser_%03d.bmp", calibDataPath[grp], index);
cv::Mat srcLaserImg = cv::imread(filename); cv::Mat srcLaserImg = cv::imread(filename);
if (srcLaserImg.empty()) if (srcLaserImg.empty())
break; break;
cv::Mat laserImg_unMask; cv::Mat laserImg_unMask;
cv::rotate(srcLaserImg, laserImg_unMask, cv::ROTATE_90_COUNTERCLOCKWISE); cv::rotate(srcLaserImg, laserImg_unMask, cv::ROTATE_90_COUNTERCLOCKWISE);
//与Mask相与保证待处理的激光线在标定板上 //与Mask相与保证待处理的激光线在标定板上
cv::Mat laserImg; cv::Mat laserImg;
cv::bitwise_and(laserImg_unMask, laserImg_unMask, laserImg, chessMask); cv::bitwise_and(laserImg_unMask, laserImg_unMask, laserImg, chessMask);
#if 1 #if 1
sprintf_s(filename, "%slaser_rotate_mask_%03d.png", calibDataPath[grp], index); sprintf_s(filename, "%slaser_rotate_mask_%03d.png", calibDataPath[grp], index);
cv::imwrite(filename, laserImg); cv::imwrite(filename, laserImg);
cv::Mat calibImg;
remap(laserImg,
calibImg,
mapGen_x,
mapGen_y,
cv::INTER_LINEAR,
cv::BORDER_CONSTANT,
cv::Scalar(0, 0, 0));
sprintf_s(filename, "%slaser_%03d_calib.bmp", calibDataPath[grp], index);
cv::imwrite(filename, calibImg);
#endif #endif
std::vector<cv::Point2f> pts2d = detectLaserLine(laserImg); std::vector<cv::Point2f> pts2d = detectLaserLine(laserImg);
//显示亚像素点 //显示亚像素点
cv::Mat enlargeImg; cv::Mat enlargeImg;
if (laserImg.channels() == 1) if (laserImg.channels() == 1)
laserImg.convertTo(enlargeImg, cv::COLOR_GRAY2BGR); laserImg.convertTo(enlargeImg, cv::COLOR_GRAY2BGR);
else else
enlargeImg = laserImg.clone(); enlargeImg = laserImg.clone();
cv::Size objSize = laserImg.size(); cv::Size objSize = laserImg.size();
objSize.width = objSize.width * 5; objSize.width = objSize.width * 5;
cv::resize(enlargeImg, enlargeImg, objSize, 0, 0, cv::INTER_NEAREST); cv::resize(enlargeImg, enlargeImg, objSize, 0, 0, cv::INTER_NEAREST);
if (pts2d.size() > 0) for (int i = 0, i_max = pts2d.size(); i < i_max; i++)
{ {
sprintf_s(filename, "%slaser_rotate_enlarge_%03d_subpixData.txt", calibDataPath[grp], index); cv::Point2f a_subPix = pts2d[i];
saveSubpixData(filename, pts2d); a_subPix.x += 0.5;
} int row = (int)(a_subPix.y + 0.5);
for (int i = 0, i_max = (int)pts2d.size(); i < i_max; i++) int col = (int)(a_subPix.x * 5 + 0.5);
{ enlargeImg.at<cv::Vec3b>(row, col)[0] = 0;
cv::Point2f a_subPix = pts2d[i]; enlargeImg.at<cv::Vec3b>(row, col)[1] = 0;
int row = (int)(a_subPix.y + 0.5); enlargeImg.at<cv::Vec3b>(row, col)[2] = 255;
int col = (int)(a_subPix.x * 5 + 0.5); }
enlargeImg.at<cv::Vec3b>(row, col)[0] = 0; sprintf_s(filename, "%slaser_rotate_enlarge_%03d_subpix.png", calibDataPath[grp], index);
enlargeImg.at<cv::Vec3b>(row, col)[1] = 0; cv::imwrite(filename, enlargeImg);
enlargeImg.at<cv::Vec3b>(row, col)[2] = 255; std::vector<cv::Point3f> pts3d = project2DTo3D(pts2d, pe, K, D);
}
sprintf_s(filename, "%slaser_rotate_enlarge_%03d_subpix.png", calibDataPath[grp], index);
cv::imwrite(filename, enlargeImg);
std::vector<cv::Point3f> pts3d = project2DTo3D(pts2d, pe, K, D);
#if 1
//保存3D点
#endif all_pts3d.insert(all_pts3d.end(), pts3d.begin(), pts3d.end());
all_pts3d.insert(all_pts3d.end(), pts3d.begin(), pts3d.end()); }
cv::Vec4f pe = fitPlaneToPoints(all_pts3d);
std::cout << "pe: " << pe << std::endl;
} }
cv::Vec4f pe = fitPlaneToPoints(all_pts3d);
std::cout << "pe: " << pe << std::endl;
//output K and D
char calibKDName[256];
sprintf_s(calibKDName, "%scalib_param_K_D.txt", calibDataPath[grp]);
sg_outputCalibKD(calibKDName, K, D, pe);
} }
return 0; return 0;

View File

@ -436,7 +436,7 @@ void computePointSubpix(
if ((subpix.x >= 0) && (subpix.y >= 0)) if ((subpix.x >= 0) && (subpix.y >= 0))
{ {
subpix.x += 0.5; //图像中的像素位置表示的是像素是左下角而此处像素坐标是指向像素中间位置所以有0.5像素差 subpix.x += 0.5; //图像中的像素位置表示的是像素是左下角而此处像素坐标是指向像素中间位置所以有0.5像素差
subpix.y -= 0.5; //此处图像的Y坐标系方向与通常坐标系的方向相反 subpix.x -= 0.5; //此处图像的Y坐标系方向与通常坐标系的方向相反
posSubpix.push_back(subpix); posSubpix.push_back(subpix);
doSubPix = -1; doSubPix = -1;
} }

View File

@ -191,7 +191,7 @@ void monocularCalibration(
flags |= cv::fisheye::CALIB_FIX_SKEW; flags |= cv::fisheye::CALIB_FIX_SKEW;
cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs);// , flags, cv::TermCriteria(3, 20, 1e-6)); cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs);// , flags, cv::TermCriteria(3, 20, 1e-6));
#else #else
cv::calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, cv::CALIB_FIX_ASPECT_RATIO); cv::calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs);
#endif #endif
// 重投影三维点到二维图像点 // 重投影三维点到二维图像点
// 计算重投影误差 // 计算重投影误差