Opencv 330 如何裁剪图片中大的目标?

main.cpp

cv::Mat CropImage(cv::Mat& src, cv::RotatedRect& rotatedRect);
cv::Mat MaxBoxSelectionRotatedRect(cv::Mat& src, cv::RotatedRect& ret);

int main()
{
#if 1
    cv::VideoCapture capture;
    cv::Mat rawData;
    cv::Mat ROI;
    cv::namedWindow("Show", cv::WINDOW_NORMAL);
    cv::namedWindow("ROI", cv::WINDOW_AUTOSIZE);
    capture.open(0);
    capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
#if 0
    capture.set(cv::CAP_PROP_FRAME_WIDTH, 3264);
    capture.set(cv::CAP_PROP_FRAME_HEIGHT, 2448);
#endif
    cv::RotatedRect rotatedRect;
    while (capture.isOpened())
    {
        capture >> rawData;
        if (rawData.empty()){break;}
        /******************************算法处理*******************************************/
#if 1
        if (cv::waitKey(1) == Esc)
        {
            cv::imwrite("640x480.jpg", rawData);
        }
        cv::Mat src = rawData.clone();
        src = MaxBoxSelectionRotatedRect(src, rotatedRect);
        ROI = CropImage(rawData, rotatedRect);
#else
        ROI = ImageColorMode(rawData, 3);
#endif
        
        
        /*********************************************************************************/
        cv::imshow("ROI", ROI);
        cv::imshow("Show", src);
        //退出循环
        if (cv::waitKey(1) == Esc)
        {
            cv::imwrite("640x480.jpg", rawData);
            break;
        }
    }
#else

#endif
    pause();
    return 0;
}
cv::Mat CropImage(cv::Mat& src,cv::RotatedRect& rotatedRect)
{
    //std::cout << rotatedRect.size.width << "x" << rotatedRect.size.height << std::endl;
    //定义框架边框边距像素大小以及参照物像素大小
    const int pixel = 10;
    const int defaultPixel = 5000000;

    //获取4个最小矩形四个顶点
    cv::Point2f pts[4];
    rotatedRect.points(pts);

    //获取最小矩形中心点
    cv::Point2f center = cv::Point2f((pts[0].x + pts[2].x) / 2, (pts[0].y + pts[2].y) / 2);
    //获取旋转角度
    double angle = rotatedRect.angle;

    std::cout << "angle:" << angle << std::endl;
#if 0
    //获取最小矩形长和宽 获取该参数可实现长方形矩形始终水平放置
    int lineWidth = sqrt((pts[1].y - pts[0].y)*(pts[1].y - pts[0].y) + (pts[1].x - pts[0].x)*(pts[1].x - pts[0].x));
    int lineHeight = sqrt((pts[3].y - pts[0].y)*(pts[3].y - pts[0].y) + (pts[3].x - pts[0].x)*(pts[3].x - pts[0].x));
#endif
    
    //
    cv::Rect roi;
    //边距
    int margin = pixel * src.cols * src.rows / defaultPixel;
    //宽
    roi.width = rotatedRect.size.width - margin * 2;
    //高
    roi.height = rotatedRect.size.height - margin * 2;
    //矩形起始坐标
    roi.x = center.x - roi.width / 2;
    roi.y = center.y - roi.height / 2;

    //目标框选超出范围部分像素直接砍掉
    if (roi.x < 0) roi.x = 0;
    if (roi.y < 0) roi.y = 0;
    if (roi.x + roi.width > src.cols)
    {
        roi.width = src.cols - roi.x;
    }
    if (roi.y + roi.height > src.rows)
    {
        roi.height = src.rows - roi.y;
    }

    cv::Mat dst(src.rows, src.cols, CV_8UC3, cv::Scalar(0, 0, 0));
    //获取仿射矩阵 M
    cv::Mat matrix2D = cv::getRotationMatrix2D(center, angle, 1);
    //变换图像
    cv::warpAffine(src, dst, matrix2D, cv::Size(src.cols, src.rows));

    //ROI 最终结果
    cv::Mat ret(dst,roi);
#if 0
    cv::namedWindow("Return");
    cv::imshow("Return",ret);
#endif
    return ret;
}
cv::Mat MaxBoxSelectionRotatedRect(cv::Mat& src, cv::RotatedRect& ret)
{
    cv::Mat dst = src.clone();
    //颜色模型转换
    cv::cvtColor(src, src, cv::COLOR_BGR2HSV_FULL);
    //cv::Mat 向量容器
    std::vector<cv::Mat> threeChannels;
    //分割HSV模型,提取 V(亮度) 通道
    cv::split(src, threeChannels);
    cv::threshold(threeChannels.back(), src, 0, 255, cv::THRESH_OTSU);
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(src, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    //假设最大轮廓值向量容器索引
    size_t maxContoursIndex = contours.size() - 1;
    //遍历向量容器
    for (size_t i = maxContoursIndex; i > 0; i--)
    {
        //寻找最大点集
        //if (contours.at(i).size() > contours.at(maxContoursIndex).size())
        //寻找最大的轮廓
        if (cv::contourArea(contours.at(i)) > cv::contourArea(contours.at(maxContoursIndex)))
        {
            //最大轮廓在向量容器中的位置
            maxContoursIndex = i;
        }
    }

    //std::cout << "contourAreaMax:" << cv::contourArea(contours.at(maxContoursIndex)) << std::endl;
    if (cv::contourArea(contours.at(maxContoursIndex)) < 488.0)//double minAreaRectSize = 488;
    {
        return dst;
    }

    ret = cv::minAreaRect(contours.at(maxContoursIndex));

    const int pixel = 10;
    const int defaultPixel = 5000000;
    int lineWidth = 2 * (dst.cols * dst.rows / 5000000);
    cv::Point2f pts[4];
    ret.points(pts);
#if 1
    //绘制最小外接矩形
    for (int i = 0; i < 4; ++i) {
        line(dst, pts[i], pts[(i + 1) % 4], cv::Scalar(0, 255, 0), lineWidth);
    }
#else
    roi = dst(cv::boundingRect(contours.at(maxContoursIndex)));
    //绘制最大外接矩形
    cv::rectangle(dst, cv::boundingRect(contours.at(maxContoursIndex)), cv::Scalar(0, 255, 0), 2, 8);
#endif
    return dst;
}

转载于:https://www.cnblogs.com/cheungxiongwei/p/8303325.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值