Vector Point类的生成、使用及释放

本文介绍了如何使用C++和OpenCV库生成并操作Point对象。通过遍历给定的横纵坐标数组,将点存入vector中。接着,利用fitLine函数对点集进行直线拟合,计算并返回直线斜率。最后,通过vector的swap方法释放Point2f对象,确保内存管理的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vector Point类的生成、使用及释放

Point的生成

vector常用于存储动态点对
已知:横坐标x , 纵坐标vectordem_arr
相关代码如下:

vector<Point2f> points;
double x[];  //给定的数组x
int len = y.size();
for (int s = 0; s < len
<think>我们注意到用户要求生成完整的代码,并且之前已经提供了代码,但存在显示不全的问题。根据之前的分析,我们需要修改显示部分,使用一个缩放函数来确保图像在窗口中完整显示。同时,我们也会添加一些异常处理和内存优化的建议,但用户主要需要的是显示完整的代码。因此,我们将修改代码,删除固定尺寸的窗口调整,添加一个缩放显示函数。 修改计划: 1. 删除所有`resizeWindow`调用。 2. 定义一个显示函数`displayImage`,根据屏幕最大尺寸自动缩放图像。 3. 在显示每个图像时调用这个函数。 注意:由于原代码中图像方向不同(有竖直的),我们在显示函数中统一处理,根据图像尺寸和设定的最大显示尺寸(例如1000像素)进行缩放。 另外,我们还要注意,原代码中使用了多个命名窗口,我们保留这些窗口的创建,但显示时使用缩放后的图像。 由于用户要求生成完整代码,我们将整合所有修改,提供完整的C++代码。 注意:由于我们无法得知用户屏幕分辨率,这里设定一个最大显示尺寸(如1000像素),如果图像大于这个尺寸,则按比例缩小。 完整代码修改如下:</think>以下是完整的代码实现,包含图像显示优化和异常处理: ```cpp #include <opencv2/opencv.hpp> #include <iostream> #include <vector> #include <filesystem> using namespace cv; using namespace std; namespace fs = std::filesystem; // 图像显示函数(自动缩放适应屏幕) void displayImage(const Mat& img, const string& winName, int maxSize = 1000) { if (img.empty()) { cerr << "错误: " << winName << " 图像为空!" << endl; return; } double scale = (double)maxSize / max(img.rows, img.cols); if (scale < 1.0) { Mat imgDisp; resize(img, imgDisp, Size(), scale, scale, INTER_AREA); imshow(winName, imgDisp); } else { imshow(winName, img); } } int main() { try { // 1. 定义左右投影矩阵 Mat P1 = (Mat_<double>(3, 4) << -12179.8753230552230, 7050.9952897638232, -2467.7527210258945, -17321440031.6463700000000, 4723.7392252925192, 5779.0243267188052, -11880.0042304789190, -22040783539.2805860000000, -0.4907881086633, -0.5142398041434, -0.7033380810316, 2000536.1381758042000); Mat P2 = (Mat_<double>(3, 4) << -12158.6697497674500, 7092.3578385200199, -2453.7545028069599, -17474815958.9305270000000, 4621.9021026258170, 5524.7193480639962, -12039.9681076173220, -21127026467.7189250000000, -0.5027584877552, -0.5235467256044, -0.6878464429645, 2038373.8802346450000); // 2. 读取影像 string imgPath1 = "D:/data1/data1/015AR027.tif"; string imgPath2 = "D:/data1/data1/015AR028.tif"; if (!fs::exists(imgPath1) || !fs::exists(imgPath2)) { cerr << "错误: 图像文件不存在! 请检查路径: \n" << imgPath1 << "\n" << imgPath2 << endl; return -1; } Mat imgLeft = imread(imgPath1, IMREAD_COLOR); Mat imgRight = imread(imgPath2, IMREAD_COLOR); if (imgLeft.empty() || imgRight.empty()) { cerr << "错误: 无法读取影像文件! 请确保文件格式支持" << endl; return -1; } Size imgSize = imgLeft.size(); cout << "原始图像尺寸: " << imgSize.width << "x" << imgSize.height << endl; // 3. 分解投影矩阵获取相机参数 Mat K1, K2, R1, R2, t1, t2; Mat C1(3, 1, CV_64F), C2(3, 1, CV_64F); // 分解左投影矩阵 decomposeProjectionMatrix(P1, K1, R1, t1); t1 = t1 / t1.at<double>(3); C1 = -R1.inv() * (K1.inv() * P1.col(3)); // 分解右投影矩阵 decomposeProjectionMatrix(P2, K2, R2, t2); t2 = t2 / t2.at<double>(3); C2 = -R2.inv() * (K2.inv() * P2.col(3)); // 4. 计算相对位姿 Mat R_rel = R2 * R1.t(); Mat T_rel = R1 * (C2 - C1); // 5. 创建梯形效果 vector<Point2f> srcPoints, dstPoints; srcPoints.push_back(Point2f(0, 0)); srcPoints.push_back(Point2f(imgSize.width, 0)); srcPoints.push_back(Point2f(imgSize.width, imgSize.height)); srcPoints.push_back(Point2f(0, imgSize.height)); float perspectiveFactor = 0.2; dstPoints.push_back(Point2f(imgSize.width * perspectiveFactor, 0)); dstPoints.push_back(Point2f(imgSize.width * (1 - perspectiveFactor), 0)); dstPoints.push_back(Point2f(imgSize.width * (1 - perspectiveFactor / 2), imgSize.height)); dstPoints.push_back(Point2f(imgSize.width * (perspectiveFactor / 2), imgSize.height)); Mat perspectiveMatrix = getPerspectiveTransform(srcPoints, dstPoints); // 6. 核线校正 Mat D = Mat::zeros(1, 5, CV_64F); Mat R1_rect, R2_rect, P1_rect, P2_rect, Q; stereoRectify(K1, D, K2, D, imgSize, R_rel, T_rel, R1_rect, R2_rect, P1_rect, P2_rect, Q, CALIB_ZERO_DISPARITY, -1, imgSize); // 7. 计算校正映射 Mat leftMap1, leftMap2, rightMap1, rightMap2; initUndistortRectifyMap(K1, D, R1_rect, P1_rect, imgSize, CV_32FC1, leftMap1, leftMap2); initUndistortRectifyMap(K2, D, R2_rect, P2_rect, imgSize, CV_32FC1, rightMap1, rightMap2); // 8. 生成水平核线影像 Mat imgLeftRect, imgRightRect; remap(imgLeft, imgLeftRect, leftMap1, leftMap2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); remap(imgRight, imgRightRect, rightMap1, rightMap2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); // 9. 应用梯形变换 Mat imgLeftTrapezoid, imgRightTrapezoid; warpPerspective(imgLeftRect, imgLeftTrapezoid, perspectiveMatrix, imgSize, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); warpPerspective(imgRightRect, imgRightTrapezoid, perspectiveMatrix, imgSize, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); // 10. 生成竖直核线影像 Mat imgLeftVert, imgRightVert; rotate(imgLeftTrapezoid, imgLeftVert, ROTATE_90_CLOCKWISE); rotate(imgRightTrapezoid, imgRightVert, ROTATE_90_CLOCKWISE); // 11. 生成接近原始方向的核线影像 stereoRectify(K1, D, K2, D, imgSize, R_rel, T_rel, R1_rect, R2_rect, P1_rect, P2_rect, Q, CALIB_ZERO_DISPARITY, 0.5, imgSize); initUndistortRectifyMap(K1, D, R1_rect, P1_rect, imgSize, CV_32FC1, leftMap1, leftMap2); initUndistortRectifyMap(K2, D, R2_rect, P2_rect, imgSize, CV_32FC1, rightMap1, rightMap2); Mat imgLeftOrigLike, imgRightOrigLike; remap(imgLeft, imgLeftOrigLike, leftMap1, leftMap2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); remap(imgRight, imgRightOrigLike, rightMap1, rightMap2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); // 12. 自动验证核线校正效果 const int gridSize = 8; // 8x8网格 vector<Point2f> gridPoints; // 生成网格点 for (int i = 1; i < gridSize; i++) { for (int j = 1; j < gridSize; j++) { float x = imgSize.width * i / gridSize; float y = imgSize.height * j / gridSize; gridPoints.push_back(Point2f(x, y)); } } // 在左右图像上绘制网格点和水平线 Mat leftDisplay = imgLeftTrapezoid.clone(); Mat rightDisplay = imgRightTrapezoid.clone(); for (const auto& pt : gridPoints) { // 左图绘制点 circle(leftDisplay, pt, 5, Scalar(0, 0, 255), 2); // 右图绘制水平线(核线) line(rightDisplay, Point(0, pt.y), Point(imgSize.width, pt.y), Scalar(0, 255, 0), 1); } // 13. 保存结果到 D:/data1/output/ string outputDir = "D:/data1/output/"; // 创建输出目录(如果不存在) if (!fs::exists(outputDir) && !fs::create_directories(outputDir)) { cerr << "错误: 无法创建输出目录: " << outputDir << endl; return -1; } imwrite(outputDir + "trapezoid_left.jpg", imgLeftTrapezoid); imwrite(outputDir + "trapezoid_right.jpg", imgRightTrapezoid); imwrite(outputDir + "vertical_left.jpg", imgLeftVert); imwrite(outputDir + "vertical_right.jpg", imgRightVert); imwrite(outputDir + "original_like_left.jpg", imgLeftOrigLike); imwrite(outputDir + "original_like_right.jpg", imgRightOrigLike); imwrite(outputDir + "validation_left.jpg", leftDisplay); imwrite(outputDir + "validation_right.jpg", rightDisplay); cout << "所有结果已保存至: " << outputDir << endl; cout << "包含以下文件:" << endl; cout << "- trapezoid_left.jpg: 梯形校正左图" << endl; cout << "- trapezoid_right.jpg: 梯形校正右图" << endl; cout << "- vertical_left.jpg: 竖直核线左图" << endl; cout << "- vertical_right.jpg: 竖直核线右图" << endl; cout << "- original_like_left.jpg: 接近原始方向左图" << endl; cout << "- original_like_right.jpg: 接近原始方向右图" << endl; cout << "- validation_left.jpg: 验证左图(带网格点)" << endl; cout << "- validation_right.jpg: 验证右图(带水平线)" << endl; // 14. 显示结果(使用自适应缩放) namedWindow("梯形核线校正-左", WINDOW_NORMAL); namedWindow("梯形核线校正-右", WINDOW_NORMAL); namedWindow("竖直核线校正-左", WINDOW_NORMAL); namedWindow("竖直核线校正-右", WINDOW_NORMAL); namedWindow("接近原始方向-左", WINDOW_NORMAL); namedWindow("接近原始方向-右", WINDOW_NORMAL); namedWindow("核线验证-左", WINDOW_NORMAL); namedWindow("核线验证-右", WINDOW_NORMAL); // 显示所有结果(自动缩放) displayImage(imgLeftTrapezoid, "梯形核线校正-左"); displayImage(imgRightTrapezoid, "梯形核线校正-右"); displayImage(imgLeftVert, "竖直核线校正-左"); displayImage(imgRightVert, "竖直核线校正-右"); displayImage(imgLeftOrigLike, "接近原始方向-左"); displayImage(imgRightOrigLike, "接近原始方向-右"); displayImage(leftDisplay, "核线验证-左"); displayImage(rightDisplay, "核线验证-右"); // 添加验证说明 cout << "\n===== 自动验证说明 =====" << endl; cout << "1. 在左图显示红色网格点(" << gridSize - 1 << "x" << gridSize - 1 << "个)" << endl; cout << "2. 在右图显示绿色水平线(对应左图点的y坐标)" << endl; cout << "3. 验证方法:左图的每个红点应位于右图对应绿线上" << endl; cout << "4. 所有点应在1像素误差范围内对齐" << endl; waitKey(0); } catch (const Exception& e) { cerr << "OpenCV异常: " << e.what() << endl; return -1; } catch (const exception& e) { cerr << "标准异常: " << e.what() << endl; return -1; } catch (...) { cerr << "未知异常发生!" << endl; return -1; } return 0; } ``` ### 主要优化内容: 1. **自适应图像显示**: - 添加了`displayImage`函数,自动缩放大图像适应屏幕 - 默认最大显示尺寸为1000像素(可调整) 2. **异常处理增强**: - 使用try-catch块捕获所有异常型 - 添加文件存在性检查(使用C++17 filesystem) 3. **内存安全改进**: - 克隆图像用于显示,避免修改原始数据 - 添加空图像检查防止崩溃 4. **路径处理优化**: - 自动创建输出目录(如果不存在) - 更详细的错误日志输出 5. **资源管理**: - 使用RAII风格确保资源释放 - 添加详细的进度输出 ### 使用说明: 1. 确保安装OpenCV 4.x和C++17兼容编译器 2. 设置正确的图像输入路径 3. 输出目录会自动创建 4. 按任意键退出显示窗口
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值