#include <opencv2/opencv.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\calib3d\calib3d.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\legacy\legacy.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <list>
#include <algorithm>
#include <iterator>
#include <cstdio>
#include <string>
using namespace cv;
using namespace std;
typedef unsigned int uint;
Size imgSize(1280, 720);
Size patSize(14, 12); //每张棋盘寻找的角点个数是14*12个
const double patLen = 5.0f; // unit: mm 标定板每个格的宽度(金属标定板)
double imgScale = 1.0; //图像缩放的比例因子
//将要读取的图片路径存储在fileList中
vector<string> fileList;
void initFileList(string dir, int first, int last){
fileList.clear();
for(int cur = first; cur <= last; cur++){
string str_file = dir + "/" + to_string(cur) + ".jpg";
fileList.push_back(str_file);
}
}
// 生成点云坐标后保存
static void saveXYZ(string filename, const Mat& mat)
{
const double max_z = 1.0e4;
ofstream fp(filename);
if (!fp.is_open())
{
std::cout<<"打开点云文件失败"<<endl;
fp.close();
return ;
}
//遍历写入
for(int y = 0; y < mat.rows; y++)
{
for(int x = 0; x < mat.cols; x++)
{
Vec3f point = mat.at<Vec3f>(y, x); //三通道浮点型
if(fabs(point[2] - max_z) < FLT_EPSILON || fabs(point[2]) > max_z)
continue;
fp<<point[0]<<" "<<point[1]<<" "<<point[2]<<endl;
}
}
fp.close();
}
// 存储视差数据
void saveDisp(const string filename, const Mat& mat)
{
ofstream fp(filename, ios::out);
fp<<mat.rows<<endl;
fp<<mat.cols<<endl;
for(int y = 0; y < mat.rows; y++)
{
for(int x = 0; x < mat.cols; x++)
{
double disp = mat.at<short>(y, x); // 这里视差矩阵是CV_16S 格式的,故用 short 类型读取
fp<<disp<<endl; // 若视差矩阵是 CV_32F 格式,则用 float 类型读取
}
}
fp.close();
}
void F_Gray2Color(Mat gray_mat, Mat& color_mat)
{
color_mat = Mat::zeros(gray_mat.size(), CV_8UC3);
int rows = color_mat.rows, cols = color_mat.cols;
Mat red = Mat(gray_mat.rows, gray_mat.cols, CV_8U);
Mat green = Mat(gray_mat.rows, gray_mat.cols, CV_8U);
Mat blue = Mat(gray_mat.rows, gray_mat.cols, CV_8U);
Mat mask = Mat(gray_mat.rows, gray_mat.cols, CV_8U);
subtract(gray_mat, Scalar(255), blue); // blue(I) = 255 - gray(I)
red = gray_mat.clone(); // red(I) = gray(I)
green = gray_mat.clone(); // green(I) = gray(I),if gray(I) < 128
compare(green, 128, mask, CMP_GE); // green(I) = 255 - gray(I), if gray(I) >= 128
subtract(green, Scalar(255), green, mask);
convertScaleAbs(green, green, 2.0, 2.0);
vector<Mat> vec;
vec.push_back(red);
vec.push_back(green);
vec.push_back(blue);
cv::merge(vec, color_mat);
}
Mat F_mergeImg(Mat img1, Mat disp8){
Mat color_mat = Mat::zeros(img1.size(), CV_8UC3);
Mat red = img1.clone();
Mat green = disp8.clone();
Mat blue = Mat::zeros(img1.size(), CV_8UC1);
vector<Mat> vec;
vec.push_back(red);
vec.push_back(blue);
vec.push_back(green);
cv::merge(vec, color_mat);
return color_mat;
}
// 双目立体标定
int stereoCalibrate(string intrinsic_filename="intrinsics.yml", string extrinsic_filename="extrinsics.yml")
{
vector<int> idx;
//左侧相机的角点坐标和右侧相机的角点坐标
vector<vector<Point2f>> imagePoints[2];
//vector<vector<Point2f>> leftPtsList(fileList.size());
//vector<vector<Point2f>> rightPtsList(fileList.size());
for(uint i = 0; i < fileList.size();++i)
{
vector<Point2f> leftPts, rightPts; // 存储左右相机的角点位置
Mat rawImg = imread(fileList[i]); //原始图像
if(rawImg.empty()){
std::cout<<"the Image is empty..."<<fileList[i]<<endl;
continue;
}
//截取左右图片
Rect leftRect(0, 0, imgSize.width, imgSize.height);
Rect rightRect(imgSize.width, 0, imgSize.width, imgSize.height);
Mat leftRawImg = rawImg(leftRect); //切分得到的左原始图像
Mat rightRawImg = rawImg(rightRect); //切分得到的右原始图像
//imwrite("left.jpg", leftRawImg);
//imwrite("right.jpg", rightRawImg);
//std::cout<<"左侧图像: 宽度"<<leftRawImg.size().width<<" 高度"<<rightRawImg.size().height<<endl;
//std::cout<<"右侧图像: 宽度"<<rightRawImg.size().width<<" 高度"<<rightRawImg.size().height<<endl; //
Mat leftImg, rightImg, leftSimg, rightSimg, leftCimg, rightCimg, leftMask, rightMask;
// BGT -> GRAY
if(leftRawImg.type() == CV_8UC3)
cvtColor(leftRawImg, leftImg, CV_BGR2GRAY); //转为灰度图
else
leftImg = leftRawImg.clone();
if(rightRawImg.type() == CV_8UC3)
cvtColor(rightRawImg, rightImg, CV_BGR2GRAY);
else
rightImg = rightRawImg.clone();
imgSize = leftImg.size();
//图像滤波预处理
resize(leftImg, leftMask, Size(200, 200)); //resize对原图像img重新调整大小生成mask图像大小为200*200
resize(rightImg, rightMask, Size(200, 200));
GaussianBlur(leftMask, leftMask, Size(13, 13), 7);
GaussianBlur(rightMask, rightMask, Size(13, 13), 7);
resize(leftMask, leftMask, imgSize);
resize(rightMask, rightMask, imgSize);
medianBlur(leftMask, leftMask, 9); //中值滤波
medianBlur(rightMask, rightMask, 9);
for (int v = 0; v < imgSize.height; v++) {
for (int u = 0; u < imgSize.width; u++) {
int leftX = ((int)leftImg.at<uchar>(v, u) - (int)leftMask.at<uchar>(v, u)) * 2 + 128;
int rightX = ((int)rightImg.at<uchar>(v, u) - (int)rightMask.at<uchar>(v, u)) * 2 + 128;
leftImg.at<uchar>(v, u) = max(min(leftX, 255), 0);
rightImg.at<uchar>(v, u) = max(min(rightX, 255), 0);
}
}
//寻找角点, 图像缩放
resize(leftImg, leftSimg, Size(), imgScale, imgScale); //图像以0.5的比例缩放
resize(rightImg, rightSimg, Size(), imgScale, imgScale);
cvtColor(leftSimg, leftCimg, CV_GRAY2BGR); //转为BGR图像,cimg和simg是800*600的图像
cvtColor(rightSimg, rightCimg, CV_GRAY2BGR);
//寻找棋盘角点
bool leftFound = findChessboardCorners(leftCimg, patSize, leftPts, CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS);
bool rightFound = findChessboardCorners(rightCimg, patSize, rightPts, CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS);
if(leftFound)
cornerSubPix(leftSimg, leftPts, Size(11, 11), Size(-1,-1 ),
TermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 300, 0.01));
if(rightFound)
cornerSubPix(rightSimg, rightPts, Size(11, 11), Size(-1, -1),
TermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 300, 0.01)); //亚像素
//放大为原来的尺度
for(uint j = 0;j < leftPts.size();j++) //该幅图像共132个角点,坐标乘以2,还原角点位置
leftPts[j] *= 1./imgScale;
for(uint j = 0;j < rightPts.size();j++)
rightPts[j] *= 1./imgScale;
//显示
string leftWindowName = "Left Corner Pic", rightWindowName = "Right Corner Pic";
Mat leftPtsTmp = Mat(leftPts) * imgScale; //再次乘以 imgScale
Mat rightPtsTmp = Mat(rightPts) * imgScale;
drawChessboardCorners(leftCimg, patSize, leftPtsTmp, leftFound); //绘制角点坐标并显示
imshow(leftWindowName, leftCimg);
imwrite("输出/DrawChessBoard/"+to_string(i)+"_left.jpg", leftCimg);
waitKey(200);
drawChessboardCorners(rightCimg, patSize, rightPtsTmp, rightFound); //绘制角点坐标并显示
imshow(rightWindowName, rightCimg);
imwrite("输出/DrawChessBoard/"+to_string(i)+"_right.jpg", rightCimg);
waitKey(200);
cv::destroyAllWindows();
//保存角点坐标
if(leftFound && rightFound)
{
imagePoints[0].push_back(leftPts);
imagePoints[1].push_back(rightPts); //保存角点坐标
std::cout<<"图片 "<<i<<" 处理成功!"<<endl;
idx.push_back(i);
}
}
cv::dest
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
【资源说明】 基于C++实现的双目摄像头三维重建源码(相机标定+矫正+获取点云坐标+体积估计)+超详细注释.zip 基于C++实现的双目摄像头三维重建源码(相机标定+矫正+获取点云坐标+体积估计)+超详细注释.zip 基于C++实现的双目摄像头三维重建源码(相机标定+矫正+获取点云坐标+体积估计)+超详细注释.zip 基于C++实现的双目摄像头三维重建源码(相机标定+矫正+获取点云坐标+体积估计)+超详细注释.zip 基于C++实现的双目摄像头三维重建源码(相机标定+矫正+获取点云坐标+体积估计)+超详细注释.zip 基于C++实现的双目摄像头三维重建源码(相机标定+矫正+获取点云坐标+体积估计)+超详细注释.zip 基于C++实现的双目摄像头三维重建源码(相机标定+矫正+获取点云坐标+体积估计)+超详细注释.zip 基于C++实现的双目摄像头三维重建源码(相机标定+矫正+获取点云坐标+体积估计)+超详细注释.zip 基于C++实现的双目摄像头三维重建源码(相机标定+矫正+获取点云坐标+体积估计)+超详细注释.zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
资源推荐
资源详情
资源评论

























收起资源包目录






共 5 条
- 1
资源评论

- 宋洪振2023-09-26非常有用的资源,有一定的参考价值,受益匪浅,值得下载。onnx2023-10-17感谢认可和支持,互相学习进步!

onnx
- 粉丝: 1w+
上传资源 快速赚钱
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


最新资源
- excel绘制蛋白质浓度标准曲线.ppt
- 基于互联网+的气象服务行政审批系统设计与实现.docx
- 安徽省移动通信公司内部控制系统构建研究的开题报告.docx
- 软件测试在电子信息工程建设中的应用分析.docx
- 我国电力行业电子商务应用研究.docx
- 第二届全国高校云计算应用创新大赛宣讲PPT.pptx
- 嵌入式HMI组态软件研究与设计的开题报告.docx
- 西门子S7300PLC05教程文件.ppt
- 4-1-第4章-S7-300PLC-第1节-硬件-配置方式及地址分配.ppt
- 基于本体的计算机取证的研究的开题报告.docx
- 操作系统(第四版)教材配套资源ppt课件(完整版).zip
- 计算机应用基础及实训教案资料.ppt
- 营销型网站建设必备的七点(1).doc
- 浅谈计算机网络安全漏洞及防范措施(1).docx
- Excel表格通用模板:生产成本核算.xlsx
- Java语言基础.ppt
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈



安全验证
文档复制为VIP权益,开通VIP直接复制
