void approxPolyDPTest(const cv::Mat img, const cv::Mat ROI_img, std::vector<cv::Point> maxContour)
{
std::vector<cv::Point> approx;
double epsilon = 0.02 * arcLength(maxContour, true);
approxPolyDP(maxContour, approx, epsilon, true);
cv::Point topLeft;
int minSum = INT_MAX;
for (const auto& p : approx) {
int currentSum = p.x + p.y;
if (currentSum < minSum) {
minSum = currentSum;
topLeft = p;
}
}
cv::circle(img, topLeft, 5, cv::Scalar(0, 0, 255), -1); // 标记左上角点
cv::Rect roiRect(topLeft.x - 100, topLeft.y+10 , 200, 300);
if (roiRect.x < 0 || roiRect.y < 0 ||
roiRect.br().x > ROI_img.cols ||
roiRect.br().y > ROI_img.rows) {
std::cerr << "错误:ROI超出图像范围" << std::endl;
}
cv::Mat roi = ROI_img(roiRect);
//std::vector<cv::Vec4i> lines;
////cv::HoughLinesP(binaryImage, lines, 1, CV_PI / 180, 50, 50, 10);
//cv::HoughLinesP(roi, lines, 1, CV_PI / 180, 10, 50, 10);
std::vector<std::vector<cv::Point>> basic_contours;
cv::findContours(roi, basic_contours, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
// --- 关键改进区域 start ---
// 1. 寻找有效轮廓(尺寸排序)
std::vector<cv::Point> lineContour;
std::vector<double> contourSizes;
for (const auto& contour : basic_contours) {
if (contour.size() > 5) { // 忽略小噪点
contourSizes.push_back(cv::contourArea(contour));
}
}
// 2. 选择最大轮廓(使用面积更可靠)
if (!contourSizes.empty()) {
auto maxIt = std::max_element(contourSizes.begin(), contourSizes.end());
size_t idx = std::distance(contourSizes.begin(), maxIt);
lineContour = basic_contours[idx];
}
// 3. 确保点数据可用
if (lineContour.empty() || lineContour.size() < 2) {
std::cerr << "错误:有效轮廓点不足" << std::endl;
return;
}
// 4. 格式转换:Point → Point2f(OpenCV必需)
std::vector<cv::Point2f> points2f;
points2f.reserve(lineContour.size());
for (const auto& pt : lineContour) {
points2f.emplace_back(pt);
std::cout << "point.x " << pt.x << " , " << "point.y " << pt.y << std::endl;
}
// 5. 调用fitLine(优化参数)
cv::Vec4f lineParams; // 使用float精度(更合理的类型)
cv::fitLine(
points2f, // 输入:点向量
lineParams, // 输出:[vx, vy, x0, y0]单位向量+直线上点
cv::DIST_L2, // 距离算法
0, // L2不需要参数
0.01, // 半径精度(推荐值)
0.01 // 角度精度(推荐值)
);
// --- 关键改进区域 end ---
// 使用拟合结果:绘制直线
float vx = lineParams[0], vy = lineParams[1];
float x0 = lineParams[2], y0 = lineParams[3];
float k = vy / vx; // 斜率
float b = y0 - k * x0;
// 计算线段起点终点(在ROI内)
cv::Point pt1(0, static_cast<int>(b));
cv::Point pt2(roi.cols, static_cast<int>(k * roi.cols + b));
cv::line(roi, pt1, pt2, cv::Scalar(0, 255, 0), 2);
// ... [原始绘制逻辑] ...
// 调试标记(左上角点)
cv::circle(img, topLeft, 5, cv::Scalar(0, 0, 255), -1);
std::vector<std::vector<cv::Point>> drawingContour;
drawingContour.push_back(approx);
cv::drawContours(img, drawingContour, -1, cv::Scalar(0, 255, 0), 1);
}
优化一下 目前问题是 cv::fitLine(
points2f, // 输入:点向量
lineParams, // 输出:[vx, vy, x0, y0]单位向量+直线上点
cv::DIST_L2, // 距离算法
0, // L2不需要参数
0.01, // 半径精度(推荐值)
0.01 // 角度精度(推荐值)
);拟合的线不准 具体数据详见前一个问题
最新发布