From 1a955962a948952f9cae551e55ce153320f6ba04 Mon Sep 17 00:00:00 2001 From: maxbang <946568130@qq.com> Date: Thu, 26 Dec 2024 02:53:25 -0500 Subject: [PATCH 1/4] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20src/PBBiology/src/PBIm?= =?UTF-8?q?ageProcess.cpp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加镜头畸变矫正函数接口 Signed-off-by: maxbang <946568130@qq.com> --- src/PBBiology/src/PBImageProcess.cpp | 48 ++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/PBBiology/src/PBImageProcess.cpp b/src/PBBiology/src/PBImageProcess.cpp index 8293479..8cb0a13 100644 --- a/src/PBBiology/src/PBImageProcess.cpp +++ b/src/PBBiology/src/PBImageProcess.cpp @@ -1276,4 +1276,52 @@ Mat get_magic_wand_image(Mat src,int x,int y,float max,float min) } } return matDst; +} + +bool camera_calibration(Mat gray,cv::Size patternSize,cv::Mat& cameraMatrix,cv::Mat& distCoeffs) +{ + if(gray.type() != CV_8UC1) + { + std::cerr << "Error: gray not CV_8UC1!" << std::endl; + return 0; + } + std::vector corners; + bool found = cv::findChessboardCorners(gray, patternSize, corners, + cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE); + + if (found) { + cv::cornerSubPix(gray, corners, cv::Size(3, 3), cv::Size(-1, -1), + cv::TermCriteria(cv::TermCriteria::EPS | cv::TermCriteria::MAX_ITER, 30, 0.1)); + } else { + std::cerr << "Error: Chessboard corners not found!" << std::endl; + return 0; + } + std::vector> objectPoints; + std::vector> imagePoints; + + std::vector objPts; + for (int i = 0; i < patternSize.height; ++i) { + for (int j = 0; j < patternSize.width; ++j) { + objPts.push_back(cv::Point3f(j, i, 0.0f)); + } + } + objectPoints.push_back(objPts); + imagePoints.push_back(corners); + cameraMatrix = cv::Mat::eye(3, 3, CV_64F); // 相机矩阵初始化 + distCoeffs = cv::Mat::zeros(8, 1, CV_64F); // 畸变系数初始化 + std::vector rvecs, tvecs; + int calibrationFlags = cv::CALIB_ZERO_TANGENT_DIST + // 假设无切向畸变 + cv::CALIB_FIX_K4 + // 固定第四个畸变参数(通常为0) + cv::CALIB_FIX_K5; // 固定第五个畸变参数(通常为0) + calibrationFlags = 0; + TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 30, DBL_EPSILON); + cv::calibrateCamera(objectPoints, imagePoints, gray.size(), cameraMatrix, distCoeffs, rvecs, tvecs,calibrationFlags,criteria); + return 1; +} + +Mat distortion_correction(Mat image,cv::Mat cameraMatrix,cv::Mat distCoeffs) +{ + cv::Mat undistortedImage; + cv::undistort(image, undistortedImage, cameraMatrix, distCoeffs); + return undistortedImage; } \ No newline at end of file -- 2.39.5 From b2295e2385e40989205497c75f433a6f45825798 Mon Sep 17 00:00:00 2001 From: maxbang <946568130@qq.com> Date: Thu, 26 Dec 2024 02:55:34 -0500 Subject: [PATCH 2/4] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20src/PBBiology/include/?= =?UTF-8?q?PBImageProcess.h?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加镜头畸变矫正函数接口 Signed-off-by: maxbang <946568130@qq.com> --- src/PBBiology/include/PBImageProcess.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/PBBiology/include/PBImageProcess.h b/src/PBBiology/include/PBImageProcess.h index 5e95fb8..01ca301 100644 --- a/src/PBBiology/include/PBImageProcess.h +++ b/src/PBBiology/include/PBImageProcess.h @@ -77,4 +77,13 @@ Mat bgr_scale_image(Mat src, float maxVal, float minVal, int scientific_flag); Mat get_photon_image(Mat src, float sec, float Wcm, float Hcm, float sr); //魔术棒功能,src是处理成8bit的图,x,y是点击位置的坐标,max和min是设定的大小,max和min需要注意除以256,使用0-255数据 //点击位置的像素差在[min,max]范围内的连在一起的像素,都会被框选 -Mat get_magic_wand_image(Mat src,int x,int y,float max,float min); \ No newline at end of file +Mat get_magic_wand_image(Mat src,int x,int y,float max,float min); +//相机标定功能,gray是包含完整棋盘格灰度图像,patternSize是棋盘格内角点的数量(假如棋盘格的尺寸是9*7,那内角点就是8*6) +//cameraMatrix和distCoeffs是后续图像畸变矫正需要的参数,标定一次后,镜头无变动情况下,后续图像直接用此参数矫正就可以 +//返回值是0表示标定错误,返回值是1表示标定正确 +//注:相机标定功能得到的结果参数只能用于矫正和计算得到结果的输入图像分辨率一致的图 +bool camera_calibration(Mat gray,cv::Size patternSize,cv::Mat& cameraMatrix,cv::Mat& distCoeffs); +//图像畸变矫正功能,image是输入图像(无要求),cameraMatrix和distCoeffs是图像畸变矫正的参数 +//返回值是矫正后的图像,输入图像是什么格式,输出图像就是什么格式 +//注:相机标定功能得到的结果参数只能用于矫正和计算得到结果的输入图像分辨率一致的图 +Mat distortion_correction(Mat image,cv::Mat cameraMatrix,cv::Mat distCoeffs); \ No newline at end of file -- 2.39.5 From 3fad215f7ad955a2024015dc46d112e9e4a651f7 Mon Sep 17 00:00:00 2001 From: maxbang <946568130@qq.com> Date: Sun, 29 Dec 2024 07:51:24 -0500 Subject: [PATCH 3/4] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20src/PBBiology/src/PBIm?= =?UTF-8?q?ageProcess.cpp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加图像畸变矫正和pixel对应物理大小计算 Signed-off-by: maxbang <946568130@qq.com> --- src/PBBiology/src/PBImageProcess.cpp | 44 ++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/src/PBBiology/src/PBImageProcess.cpp b/src/PBBiology/src/PBImageProcess.cpp index 8cb0a13..46eb2b8 100644 --- a/src/PBBiology/src/PBImageProcess.cpp +++ b/src/PBBiology/src/PBImageProcess.cpp @@ -1278,7 +1278,7 @@ Mat get_magic_wand_image(Mat src,int x,int y,float max,float min) return matDst; } -bool camera_calibration(Mat gray,cv::Size patternSize,cv::Mat& cameraMatrix,cv::Mat& distCoeffs) +bool camera_calibration(Mat gray,cv::Size patternSize,float grid_size,cv::Mat& cameraMatrix,cv::Mat& distCoeffs,float& pixel_size) { if(gray.type() != CV_8UC1) { @@ -1310,12 +1310,46 @@ bool camera_calibration(Mat gray,cv::Size patternSize,cv::Mat& cameraMatrix,cv:: cameraMatrix = cv::Mat::eye(3, 3, CV_64F); // 相机矩阵初始化 distCoeffs = cv::Mat::zeros(8, 1, CV_64F); // 畸变系数初始化 std::vector rvecs, tvecs; - int calibrationFlags = cv::CALIB_ZERO_TANGENT_DIST + // 假设无切向畸变 - cv::CALIB_FIX_K4 + // 固定第四个畸变参数(通常为0) - cv::CALIB_FIX_K5; // 固定第五个畸变参数(通常为0) - calibrationFlags = 0; + int calibrationFlags = 0; TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 30, DBL_EPSILON); cv::calibrateCamera(objectPoints, imagePoints, gray.size(), cameraMatrix, distCoeffs, rvecs, tvecs,calibrationFlags,criteria); + + vector undistortedCorners; + undistortPoints(corners, undistortedCorners, cameraMatrix, distCoeffs); + + std::vector homogeneousPoints; + for (const auto& p : undistortedCorners) { + homogeneousPoints.push_back(cv::Point3f(p.x, p.y, 1.0f)); // 将 (x, y) 转换为 (x, y, 1) + } + std::vector pixelPoints; + for (const auto& p : homogeneousPoints) { + cv::Mat pointMat = (cv::Mat_(3, 1) << p.x, p.y, p.z); + cv::Mat transformedPoint = cameraMatrix * pointMat; + float x = transformedPoint.at(0, 0) / transformedPoint.at(2, 0); + float y = transformedPoint.at(1, 0) / transformedPoint.at(2, 0); + pixelPoints.push_back(cv::Point2f(x, y)); + } + int numCols = patternSize.width; + int numRows = patternSize.height; + float meanSideLength = 0; + int num = 0; + for (int i = 0; i < (patternSize.height - 1); ++i) { + for (int j = 0; j < (patternSize.width - 1); ++j) { + int index = i * patternSize.width + j; + if (j + 1 < numCols) { + float width = static_cast(norm(pixelPoints[index] - pixelPoints[index + 1])); + meanSideLength+=(width); + num++; + } + if (i + 1 < patternSize.height) { + float height = static_cast(norm(pixelPoints[index] - pixelPoints[index + numCols])); + meanSideLength+=(height); + num++; + } + } + } + meanSideLength /= num; + pixel_size = grid_size/meanSideLength; return 1; } -- 2.39.5 From 15f02988a9790f5769c0657204757bc8f92fc068 Mon Sep 17 00:00:00 2001 From: maxbang <946568130@qq.com> Date: Sun, 29 Dec 2024 07:52:04 -0500 Subject: [PATCH 4/4] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20src/PBBiology/include/?= =?UTF-8?q?PBImageProcess.h?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加图像畸变矫正和pixel对应物理大小计算 Signed-off-by: maxbang <946568130@qq.com> --- src/PBBiology/include/PBImageProcess.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PBBiology/include/PBImageProcess.h b/src/PBBiology/include/PBImageProcess.h index 01ca301..a15d80c 100644 --- a/src/PBBiology/include/PBImageProcess.h +++ b/src/PBBiology/include/PBImageProcess.h @@ -78,11 +78,11 @@ Mat get_photon_image(Mat src, float sec, float Wcm, float Hcm, float sr); //魔术棒功能,src是处理成8bit的图,x,y是点击位置的坐标,max和min是设定的大小,max和min需要注意除以256,使用0-255数据 //点击位置的像素差在[min,max]范围内的连在一起的像素,都会被框选 Mat get_magic_wand_image(Mat src,int x,int y,float max,float min); -//相机标定功能,gray是包含完整棋盘格灰度图像,patternSize是棋盘格内角点的数量(假如棋盘格的尺寸是9*7,那内角点就是8*6) -//cameraMatrix和distCoeffs是后续图像畸变矫正需要的参数,标定一次后,镜头无变动情况下,后续图像直接用此参数矫正就可以 +//相机标定功能,gray是包含完整棋盘格灰度图像,patternSize是棋盘格内角点的数量(假如棋盘格的尺寸是9*7,那内角点就是8*6),grid_size是每个格子的物理大小 +//cameraMatrix和distCoeffs是后续图像畸变矫正需要的参数,标定一次后,镜头无变动情况下,后续图像直接用此参数矫正就可以,pixel_size是矫正后每个pixel的物理大小 //返回值是0表示标定错误,返回值是1表示标定正确 //注:相机标定功能得到的结果参数只能用于矫正和计算得到结果的输入图像分辨率一致的图 -bool camera_calibration(Mat gray,cv::Size patternSize,cv::Mat& cameraMatrix,cv::Mat& distCoeffs); +bool camera_calibration(Mat gray,cv::Size patternSize,float grid_size,cv::Mat& cameraMatrix,cv::Mat& distCoeffs,float& pixel_size); //图像畸变矫正功能,image是输入图像(无要求),cameraMatrix和distCoeffs是图像畸变矫正的参数 //返回值是矫正后的图像,输入图像是什么格式,输出图像就是什么格式 //注:相机标定功能得到的结果参数只能用于矫正和计算得到结果的输入图像分辨率一致的图 -- 2.39.5