cv::RotatedRect minRect = cv::minAreaRect(vMaxDftArea);如何判断最长边方向直线方程

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cmath>

void GetLongestEdgeLineEquation(cv::RotatedRect& minRect) {
    // 获取矩形的中心坐标、尺寸和角度
    cv::Point2f center = minRect.center;
    cv::Size2f size = minRect.size;
    float angle = minRect.angle;

    // 判断哪个边是最长边
    float angleOfLongestEdge = 0;
    if (size.width > size.height) {
        angleOfLongestEdge = angle; // 如果宽度是最长边
    } else {
        angleOfLongestEdge = angle + 90; // 如果高度是最长边
    }

    // 计算最长边的方向的斜率 (方向角转为斜率)
    // 角度转弧度
    float radian = angleOfLongestEdge * CV_PI / 180.0;
    float slope = tan(radian);

    // 直线方程:y = mx + b,其中 m 是斜率,b 是截距
    // 计算 b (截距),使用矩形的中心点代入方程
    float b = center.y - slope * center.x;

    // 输出计算的直线方程
    std::cout << "Line equation: y = " << slope << "x + " << b << std::endl;
}

int main() {
    // 创建一个旋转矩形
    cv::RotatedRect minRect(cv::Point2f(100, 100), cv::Size2f(80, 50), 30);  // 中心 (100, 100),宽 80,高 50,角度 30°

    // 调用函数获取最长边的直线方程
    GetLongestEdgeLineEquation(minRect);

    return 0;
}
 

#include "rclcpp/rclcpp.hpp" #include "sensor_msgs/msg/image.hpp" #include "cv_bridge/cv_bridge.h" #include <opencv2/opencv.hpp> #include <opencv2/core.hpp> #include <opencv2/imgproc.hpp> #include <stdexcept> // 关键头文件 class ImageSubscriber : public rclcpp::Node { public: ImageSubscriber() : Node("image_subscriber") { // 使用lambda避免绑定错误 subscription_ = create_subscription<sensor_msgs::msg::Image>( "/detector/initial_img", 10, [this](sensor_msgs::msg::Image::ConstSharedPtr msg) { this->image_callback(msg); }); } private: void image_callback(sensor_msgs::msg::Image::ConstSharedPtr msg) { try { cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(msg, "bgr8"); cv::Mat image=cv_ptr->image; cv::imshow("Preview", image); cv::waitKey(1); std::vector<cv::Mat> channels; cv::Mat binary,Gaussian,gray,kernal; kernal = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); cv::cvtColor(image,gray,cv::COLOR_BGR2GRAY); cv::threshold(gray,binary,120,255,0); cv::waitKey(1); cv::dilate(binary,binary,kernal); cv::erode(binary, binary, kernal); cv::imshow("dilated", binary); cv::waitKey(1); std::vector<std::vector<cv::Point>> contours; // 存储所有轮廓(二维点集) std::vector<cv::Vec4i> hierarchy; cv::findContours(binary,contours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE); cv::Mat result = image.clone(); cv::Mat result2 = image.clone(); std::vector<cv::RotatedRect> lightBarRects; for (const auto &contour : contours) { // 忽略太小的轮廓 if (contour.size() < 5) // 拟合椭圆至少需要5个点 continue; // 计算轮廓面积 double area = cv::contourArea(contour); if (area < 50) // 面积阈值,根据实际情况调整 continue; // 计算轮廓的最小外接矩形(旋转矩形) cv::RotatedRect minRect = cv::minAreaRect(contour); float aspectRatio = std::max(minRect.size.width, minRect.size.height) / std::min(minRect.size.width, minRect.size.height); // 根据长宽比筛选(灯条通常长宽比较大) if (aspectRatio > 3.0 && aspectRatio <8.5) { // 拟合椭圆 cv::RotatedRect ellipse = cv::fitEllipse(contour); // 在图像上绘制椭圆 cv::ellipse(result, ellipse, cv::Scalar(0, 255, 0), 2); } } cv::imshow("Armor Detection", result); cv::waitKey(1); std::vector<cv::RotatedRect> armorRects; const double maxAngleDiff = 15.0; cv::Point2f vertices2[4]; for (size_t i = 0; i < lightBarRects.size(); i++) { for (size_t j = i + 1; j < lightBarRects.size(); j++) { cv::RotatedRect bar1 = lightBarRects[i]; cv::RotatedRect bar2 = lightBarRects[j]; // 简化角度计算:直接取旋转矩形的角度(OpenCV原生角度) float angle1 = fabs(bar1.angle); float angle2 = fabs(bar2.angle); // 计算角度差(简化角度转换,直接用原生角度差) double angleDiff = fabs(angle1 - angle2); // 仅通过角度判断是否匹配 if (angleDiff < maxAngleDiff) { // 简化装甲板计算:直接用两灯条中心尺寸构建 cv::Point2f armorCenter = (bar1.center + bar2.center) / 2; float distance = norm(bar1.center - bar2.center); // 两灯条间距 cv::Size2f armorSize(distance * 1.1, (bar1.size.height + bar2.size.height) / 2 * 1.2); float armorAngle = (bar1.angle + bar2.angle) / 2; // 平均角度 armorRects.push_back(cv::RotatedRect(armorCenter, armorSize, armorAngle)); } } } for (auto& armor : armorRects) { armor.points(vertices2); for (int j = 0; j < 4; j++) { cv::line(result2, vertices2[j], vertices2[(j+1)%4], cv::Scalar(0, 0, 255), 2); } imshow("hihi",result2); cv::waitKey(1); }
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值