以下opencv的版本为4.0.6,尤其以前的老版本有很大差异。

1、cv::RotatedRect返回的w,h,angle

在box逆时针旋转过程,与x正轴相交的第一条边就是w,另外是h,w和h的大小没有必然联系。

angle返回值是[0,90],为图示所讲的角度。

2、cv::getRotationMatrix2D

cv::Mat rotationMatrix = cv::getRotationMatrix2D(center, angle, 1.0);

// angle>0时,绕逆时针旋转

3、按照最小角度旋转,下面是伪代码,注意就是angle的问题

// 计算最小外接矩形
// opencv的版本是4.0.6
// 原点在图像(0,0)位置,水平向左为x正,竖直向下为y正
cv::RotatedRect rotatedRect = cv::minAreaRect(contours[maxAreaIdx]);

// 将检测到的矩形坐标映射回原图尺寸
    float scaleX = static_cast<float>(originalImage.cols) / oW;
    float scaleY = static_cast<float>(originalImage.rows) / oH;
    // 缩放矩形坐标到原图尺寸
    cv::Point2f center = rotatedRect.center;
    center.x *= scaleX;
    center.y *= scaleY;
    cv::Size2f size = rotatedRect.size;
    size.width *= scaleX;
    size.height *= scaleY;
    float angle = rotatedRect.angle;    //输出在[0,90]

    //按照最小角度进行旋转
    if(angle>45) {
        angle=angle-90;
        std::swap(size.width, size.height);
    }

    // 创建变换矩阵以校正旋转矩形到水平方向
    // angle>0时,绕逆时针旋转
    cv::Mat rotationMatrix = cv::getRotationMatrix2D(center, angle, 1.0);

    // 执行旋转校正
    cv::Mat rotatedImage;
    cv::warpAffine(originalImage, rotatedImage, rotationMatrix, 
                cv::Size(originalImage.cols, originalImage.rows), 
                cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));
      
    // 根据角度确定宽高
    cv::Size rectSize=cv::Size(static_cast<int>(size.width), static_cast<int>(size.height));

    // 计算旋转后的边界框
    cv::Rect bbox = cv::RotatedRect(center, size, angle).boundingRect();

    // 确保边界框在原图范围内
    bbox &= cv::Rect(0, 0, originalImage.cols, originalImage.rows);

    // 截取校正后的矩形区域
    cv::Rect roiRect(center.x - size.width/2, center.y - size.height/2, 
                    static_cast<int>(size.width), static_cast<int>(size.height));
    
    // 正确调整ROI区域,确保不超出图像边界
    if (roiRect.x < 0) {
        roiRect.width += roiRect.x;  // 减少宽度
        roiRect.x = 0;
    }
    if (roiRect.y < 0) {
        roiRect.height += roiRect.y; // 减少高度
        roiRect.y = 0;
    }
    if (roiRect.x + roiRect.width > rotatedImage.cols) {
        roiRect.width = rotatedImage.cols - roiRect.x;
    }
    if (roiRect.y + roiRect.height > rotatedImage.rows) {
        roiRect.height = rotatedImage.rows - roiRect.y;
    }
    auto postprocess_time = 1000.0 * (clock() - begin_time) / CLOCKS_PER_SEC;    
    printf("postprocess: %.1fms\n",postprocess_time);

    if (roiRect.width > 0 && roiRect.height > 0) {
        output = rotatedImage(roiRect).clone();
        return true;
    } else {
        // 如果截取失败,返回分割图
        output = pred;
        return false;
    }

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐