OpenCV2.4.13 中 选取roi区域,任意形状(矩形,不规则多边形,圆形,椭圆,手动指定形状)

在利用OpenCV对图像进行处理时,通常会遇到一个情况,就是只需要对部分感兴趣区域进行处理。
因此,如何选取感兴趣区域(其实就是“抠图”)。
下面给出一个例子:

    Mat img = imread(IMG_PATH);
    Mat cat = imread(CAT_PATH);
    if (img.empty()|| cat.empty())
        cerr << "can not read image."<<endl;

    // 指定感兴趣区域,两种方法
    Mat ROI =  img(Rect(40,40,cat.cols,cat.rows));
    Mat ROI2(img,Rect(40,40,cat.cols,cat.rows));

    // 展示 roi 区域
    imshow("roi",ROI);

    cout<<endl
        <<"将猫放到感兴趣区域,两种方法"<<endl;
    //cat.copyTo(ROI);
    cat.copyTo(ROI,cat);
    imshow("lotus with cat",img);


    // 在图像中画出 矩形
    rectangle(img,Rect(240,240,cat.cols,cat.rows),Scalar(0,0,255));
    imshow("with rectangle box",img);

    //  另一种方法
    cout <<endl
        << "利用 Rect 保存方框,然后使用"<<endl;
    Rect r1 = Rect(100,0,200,200);
    rectangle(img,r1,Scalar(255,0,0));
    imshow("with rectangle box 2",img);

下面是程序最终的结果:
这里写图片描述

  • 问题:如果感兴趣区域不是方形的怎么办?
    答:参考这里的代码,也就是说,使用 contour (轮廓)来指定roi。
    其代码如下:
    Mat img = imread(IMG_PATH);
    Mat dst;
    Mat roi = Mat::zeros(img.size(),CV_8U);

    vector<vector<Point>> contour;
    vector<Point> pts;
    pts.push_back(Point(30,45));
    pts.push_back(Point(100,15));
    pts.push_back(Point(300,145));
    pts.push_back(Point(330,240));
    pts.push_back(Point(50,250));
    contour.push_back(pts);

    drawContours(roi,contour,0,Scalar::all(255),-1);
    img.copyTo(dst,roi);

    imshow("roi",roi);
    imshow("img",img);
    imshow("dst",dst);

效果图:这里写图片描述

  • 问题:我不想要这么复杂的区域,只是想要一个圆形区域呢?
    答:经过参考这里的回答,给出其中回答中的代码,可以画出圆形区域的roi。
    Mat image = imread(IMG_PATH);
    Mat dst = Mat::zeros(image.size(), image.type());
    Mat mask = Mat::zeros(image.size(),CV_8U);

    Point circleCenter(mask.cols / 2, mask.rows / 2);
    int radius = min(mask.cols, mask.rows)/2;
    // 画圆
    circle(mask, circleCenter, radius, Scalar(255),-1);

    image.copyTo(dst, mask);

    imshow("mask",mask);
    imshow("image",image);
    imshow("dst",dst);

效果如下:这里写图片描述
- 问题:我想要个椭圆区域呢?
答:将上面代码中画圆的那一句替换为:

ellipse(mask,circleCenter,Size(240,146),10,-180,180,Scalar(255),-1);

效果如下:
这里写图片描述
- 问题:说了这么多,有什么规律么?
答:有啊。
其实主要用到了一个函数:copyTo,先看手册中 它的定义:
这里写图片描述
给出一个例子:

src.copyTo(dst, mask);

这里解释一下:将 src 的位于 mask 中的部分,拷贝到 dst 中。
这里,mask是一个“掩膜”, 其中非零的位置既是指定了 src 中的那些需要拷贝的部分。

上面才是整个方法的核心部分。

  • 问题:我想手动,用鼠标选取感兴趣区域,怎么办么?
    答:额,这个我还没用到,不过帮你搜到了一个相关的博客,在这里。具体效果如何,我没有实验,实在需要的话,可以自己折腾一下。
    不过,这里貌似只能手动选择方形区域。

放大招:整体代码如下:

// csdn_code.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;



//#define IMG_PATH  "..//figures//12.jpg"

#define IMG_PATH  "..//figures//lotus.jpg"

#define CAT_PATH  "..//figures//cat.jpg"

void testroi(void){
    Mat img = imread(IMG_PATH);
    Mat cat = imread(CAT_PATH);
    if (img.empty()|| cat.empty())
        cerr << "can not read image."<<endl;

    // 指定感兴趣区域,两种方法
    Mat ROI =  img(Rect(40,40,cat.cols,cat.rows));
    Mat ROI2(img,Rect(40,40,cat.cols,cat.rows));

    // 展示 roi 区域
    imshow("roi",ROI);

    cout<<endl
        <<"将猫放到感兴趣区域,两种方法"<<endl;
    //cat.copyTo(ROI);
    cat.copyTo(ROI,cat);
    imshow("lotus with cat",img);


    // 在图像中画出 矩形
    rectangle(img,Rect(240,240,cat.cols,cat.rows),Scalar(0,0,255));
    imshow("with rectangle box",img);

    //  另一种方法
    cout <<endl
        << "利用 Rect 保存方框,然后使用"<<endl;
    Rect r1 = Rect(100,0,200,200);
    rectangle(img,r1,Scalar(255,0,0));
    imshow("with rectangle box 2",img);

}


void contour_roi(void){
    Mat img = imread(IMG_PATH);
    Mat dst;
    Mat roi = Mat::zeros(img.size(),CV_8U);

    // 利用 边界设置roi区域
    vector<vector<Point>> contour;
    vector<Point> pts;
    pts.push_back(Point(30,45));
    pts.push_back(Point(100,15));
    pts.push_back(Point(300,145));
    pts.push_back(Point(330,240));
    pts.push_back(Point(50,250));
    contour.push_back(pts);

    // 画出
    drawContours(roi,contour,0,Scalar::all(255),-1);
    img.copyTo(dst,roi);

    imshow("roi",roi);
    imshow("img",img);
    imshow("dst",dst);

}

void circle_roi(void){
    Mat image = imread(IMG_PATH);
    Mat dst = Mat::zeros(image.size(), image.type());
    Mat mask = Mat::zeros(image.size(),CV_8U);

    Point circleCenter(mask.cols / 2, mask.rows / 2);
    int radius = min(mask.cols, mask.rows)/2;

    // 画圆
    //circle(mask, circleCenter, radius, Scalar(255),-1);
    // 画椭圆
    ellipse(mask,circleCenter,Size(240,146),10,-180,180,Scalar(255),-1);

    image.copyTo(dst, mask);

    imshow("mask",mask);
    imshow("image",image);
    imshow("dst",dst);
}

int main()
{
    testroi();

    contour_roi();

    circle_roi();


    waitKey();
    system("pause");
    return 0;
}
  • 25
    点赞
  • 162
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
在Python使用OpenCV进行不规则多边形ROI区域提取需要以下步骤: 1. 导入所需的库 我们需要导入OpenCV库,并将其命名为cv2。 2. 读取图像 使用cv2.imread()函数读取图像。这里假设图像文件名为"image.jpg"。 3. 创建ROI多边形 定义一个包含不规则多边形顶点的列表作为ROI区域。 4. 创建掩膜 使用cv2.fillPoly()函数创建一个与图像大小相同的空白图像,作为掩膜。然后使用cv2.fillPoly()函数在掩膜上填充多边形。 5. 应用掩膜 使用cv2.bitwise_and()函数将原始图像与掩膜进行按位与操作,即只保留ROI区域。 6. 显示结果 使用cv2.imshow()函数显示提取的ROI区域。 7. 释放窗口 使用cv2.waitKey(0)等待按下任意键后,使用cv2.destroyAllWindows()函数关闭窗口。 以下是一个简单的示例代码: ```python import cv2 import numpy as np # 读取图像 image = cv2.imread('image.jpg') # 创建ROI多边形 roi_vertices = np.array([[(100, 100), (300, 100), (200, 300), (50, 200)]], dtype=np.int32) # 创建掩膜 mask = np.zeros_like(image) cv2.fillPoly(mask, roi_vertices, 255) # 应用掩膜 roi_image = cv2.bitwise_and(image, mask) # 显示结果 cv2.imshow('ROI Image', roi_image) # 释放窗口 cv2.waitKey(0) cv2.destroyAllWindows() ``` 将以上代码保存为Python脚本,运行后会显示提取的ROI区域图像。其roi_vertices是一个包含多边形顶点的列表,可以根据需要调整顶点的坐标和个数来定义不规则多边形形状

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值