C ++ Opencv重新缩放边界矩形

Posted

技术标签:

【中文标题】C ++ Opencv重新缩放边界矩形【英文标题】:C++ Opencv Rescale Bounding Rect 【发布时间】:2017-05-31 17:43:26 【问题描述】:

所以,我有一个问题:

我在android中做opencv,因为我用手机拍摄的图像分辨率非常高,我想将图像调整为更小的图像,获取轮廓并处理图像,然后在原始图像上创建边界矩形.为此,我需要缩放该边界框,使其完全适合我的原始图像。我拥有的代码在处理和绘制原始图像上的边界框时效果很好,但是,如何进行缩放?这是代码sn-p:

 Mat &image = *(Mat *) matAddrRgba;
//over here I should resize image and do the processing with the resized one, and in the end, scale everything back so I can draw the bounding box to the original
    Rect bounding_rect;

    Mat thr(image.rows, image.cols, CV_8UC1);
    cvtColor(image, thr, CV_BGR2GRAY); //Convert to gray
    threshold(thr, thr, 150, 255, THRESH_BINARY + THRESH_OTSU); //Threshold the gray

    vector<vector<Point> > contours; // Vector for storing contour
    vector<Vec4i> hierarchy;
    RotatedRect rect;
    findContours(thr, contours, hierarchy, CV_RETR_CCOMP,
                 CV_CHAIN_APPROX_SIMPLE); // Find the contours in the image
    sort(contours.begin(), contours.end(),
         compareContourAreas);            //Store the index of largest contour
    bounding_rect = boundingRect(contours[0]);
    rect = minAreaRect(contours[0]);
    // matrices we'll use
    Mat rot_mat, rotated;
    // get angle and size from the bounding box
    float angle = rect.angle;
    Size rect_size = rect.size;

    if (rect.angle < -45.) 
        angle += 90.0;
        swap(rect_size.width, rect_size.height);
    

    rot_mat = getRotationMatrix2D(rect.center, angle, 1);

    warpAffine(image, rotated, rot_mat, image.size(), INTER_CUBIC);

    image = rotated;

    cvtColor(image, thr, CV_BGR2GRAY); //Convert to gray
    threshold(thr, thr, 150, 255, THRESH_BINARY + THRESH_OTSU); //Threshold the gray

    findContours(thr, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
    sort(contours.begin(), contours.end(), compareContourAreas);
    bounding_rect = boundingRect(contours[0]);

    image = Mat(image, bounding_rect);

【问题讨论】:

"如何进行缩放" -- 除非是指攀爬或从对象上移除鳞片,否则 乘法 往往可以解决问题。您可以将scale-1 的偏移量添加到新的宽度和高度,使其更适合一点。只需拿一张方形纸并画出来——这不应该花太多精力来弄清楚。 @DanMašek 我得到了旋转的矩形,这是我计算的产物。然后我旋转图像以使其与我的设备完美对齐。之后,我使用旋转的矩形进行裁剪(从中创建边界矩形)。如何扩展/乘/放大边界矩形? 例如,如果您将图像的宽度和高度加倍,则相同的缩放因子适用于坐标。所以边界框的 x 和 y 坐标会加倍,它的宽度和高度会加倍。 @DanMašek 有没有办法从中心放大边界框,所以可以说,将宽度和高度加倍,但将中心留在原处? 假设您在 (0,0) 处有一个尺寸为 (2,4) 的边界框。因此,中心位于 (1,2)。 |现在我们将边界框的大小加倍,所以它的新维度是 (4,8)。这将新中心置于 (2,4)。新中心与旧中心的偏移量为 (1, 2)。因此,为了使中心匹配,我们必须将边界框的位置偏移到 (-1, -2)。 |我真的建议您尝试使用一张正方形或方格纸来解决这些问题,以帮助您将其可视化。 【参考方案1】:

好的,那么,我将从这个开始:

    Mat &img = (Mat ) matAddrRgba;
    Mat image;
    double thrA = 5;
    resize(img, image, Size((int) (img.size().width / thrA), (int) (img.size().height / thrA)));

    Rect bounding_rect;

    Mat thr(image.rows, image.cols, CV_8UC1);
    cvtColor(image, thr, CV_BGR2GRAY); //Convert to gray
    threshold(thr, thr, 150, 255, THRESH_BINARY + THRESH_OTSU); //Threshold the gray

    vector<vector<Point> > contours; // Vector for storing contour
    vector<Vec4i> hierarchy;
    RotatedRect rect;
    findContours(thr, contours, hierarchy, CV_RETR_CCOMP,
                 CV_CHAIN_APPROX_SIMPLE); // Find the contours in the image
    sort(contours.begin(), contours.end(),
         compareContourAreas);            //Store the index of largest contour
    bounding_rect = boundingRect(contours[0]);

    bounding_rect.width = (int) (bounding_rect.width * thrA);
    bounding_rect.height = (int) (bounding_rect.height * thrA);
    bounding_rect.x = (int) (bounding_rect.x * thrA);
    bounding_rect.y = (int) (bounding_rect.y * thrA);

    rectangle(img, bounding_rect, Scalar(0, 172, 236, 255), 3);

如您所见,您应该有一个比例尺,该比例尺应该乘以边界矩形的宽度、高度、x 和 y。你可以从中找出其余的。

【讨论】:

以上是关于C ++ Opencv重新缩放边界矩形的主要内容,如果未能解决你的问题,请参考以下文章

包围轮廓的矩形边界 opencv

youcans 的 OpenCV 例程200篇199.轮廓的外接边界框

OpenCV 例程200篇212. 绘制倾斜的矩形

OpenCV 例程200篇212. 绘制倾斜的矩形

在 OpenCV 中检测不完整的矩形(缺少角/短边)

OpenCV中的图像处理 —— 轮廓入门+轮廓特征