美文网首页
利用opencv 实现ROI区域的绘制

利用opencv 实现ROI区域的绘制

作者: 此间不留白 | 来源:发表于2020-10-29 11:52 被阅读0次

    随机生成一幅指定大小的三通道图像,设定其所有元素均为0,有如下要求:

    • 生成一幅大小为200×200大小的三通道图像,所有像素值设置为0
    • 给定原点坐标和半径,在生成的图像上绘制一个圆
    • 给定一个起始坐标和一个终点坐标,在生成的图像上绘制一个矩形
    生成一幅大小为指定大小,所有像素为0的三通道图像
    Mat createImage() {
        Mat m;
        m.create(WIDTH, HEIGHT, CV_8UC3);
        m.setTo(Scalar(0, 0, 0));
        return m;
    }
    
    在生成的图像上画一个圆

    在图像上画圆,主要用到了opencv的cv::circle函数,其主要参数有如下解释:

    CV_EXPORTS_W void circle(InputOutputArray img, Point center, int radius,
                           const Scalar& color, int thickness = 1,
                           int lineType = LINE_8, int shift = 0);
    @param img 指定绘制的图像
    @param center 圆的圆心坐标
    @param radius 圆的半径长度
    @param color 所绘制圆的轮廓颜色
    @param thickness 圆的轮廓的厚度,当为正时,值越大,轮廓线越粗,当为负时,圆形区域变为实心圆
    @param lineType 所绘制圆形的边缘线的类型,一般4连接,8连接,抗锯齿连接,如下所示:
    enum LineTypes {
        FILLED  = -1,
        LINE_4  = 4, //!< 4-connected line
        LINE_8  = 8, //!< 8-connected line
        LINE_AA = 16 //!< antialiased line
    };
    @param 偏移圆心坐标和半径的最小位数,一般默认为0
     */
    
    

    综上,在图像上画圆的代码如下所示:

    void DrawCircle(Mat m, int x_0, int y_0, int r)
    {
        if (m.empty())
        {
            throw("Fialed read image!");
        }
        if (x_0<0 || x_0>m.rows|| y_0<0||y_0>m.cols)
        {
            throw("position error!");
        }
        circle(m, Point(x_0,y_0), r, Scalar(0, 255, 0), 3, 16, 0);
    }
    

    为了对比,设置设置thickness>0thickness<0 两种情况,并为了使得整个轮廓线更加圆滑,显示效果更好,设置linetyoe=16,抗锯齿连接方式。

    其效果如下图所示:


    thinckness=2,linetype=16 thickness=-1,linetype=16
    在图像上绘制矩形

    在图像上绘制矩形和在图像上绘制圆形,非常相似,主要用到了rectangle()函数,唯一的区别是,圆心坐标和半径参数被替换为了矩形左上角坐标和右下角的坐标,整体代码如下所示:

    void DrawRect(Mat m, int x_0, int y_0, int x_1, int y_1)
    {
    
        if (m.empty())
        {
            throw("Fialed read image!");
    
        }
        if (x_0<0 || x_1>m.rows || y_0 < 0 || y_1>m.cols)
        {
            throw("position error!");
        }
        Point p0 = Point(x_0, y_0);
        Point p1 = Point(x_1, y_1);
        rectangle(m, p0, p1, Scalar(0, 255, 0), 1, 8, 0);
    }
    

    实现效果如下所示:


    最后,所有的实现代码如下:

    #include<opencv2/opencv.hpp>
    #include<iostream>
    using namespace cv;
    const int HEIGHT = 200;
    const int WIDTH = 200;
    // 创建一个200*200 的3通道图像,所有元素都初始化为0
    Mat createImage() {
        Mat m;
        m.create(WIDTH, HEIGHT, CV_8UC3);
        m.setTo(Scalar(0, 0, 0));
        return m;
    }
    void DrawCircle(Mat m, int x_0, int y_0, int r)
    {
        if (m.empty())
        {
            throw("Fialed read image!");
        }
        if (x_0<0 || x_0>m.rows|| y_0<0||y_0>m.cols)
        {
            throw("position error!");
        }
        circle(m, Point(x_0,y_0), 100, Scalar(0, 255, 0), -1, 16, 0);
    }
    // 在原始图像上画圆
    void DrawRect(Mat m, int x_0, int y_0, int x_1, int y_1)
    {
    
        if (m.empty())
        {
            throw("Fialed read image!");
    
        }
        if (x_0<0 || x_1>m.rows || y_0 < 0 || y_1>m.cols)
        {
            throw("position error!");
        }
        Point p0 = Point(x_0, y_0);
        Point p1 = Point(x_1, y_1);
        rectangle(m, p0, p1, Scalar(0, 255, 0), 2, 8, 0);
    }
    
    int main(int argc, char* argv[])
    {
        
        Mat m = createImage();
        //DrawCircle(m, WIDTH / 2, HEIGHT / 2, 100);
        DrawRect(m, 30, 30, 100, 100);
        //std::cout << m << std::endl;
        imshow("Image_0", m);
        imwrite("rect.png",m);
        waitKey(0);
        
        return 0;
    }
    

    图像上实现金字塔边框绘制

    有如下要求:

    • 创建一幅单通道图像,大小为210×210,类型为unsigned int,所有元素初始化为0;
    • 设置最外层的边框,值为0,此外层,值为20……,从最外层到最内层,按照0,20,40……的值递增,边框的宽度为10个像素,实现金字塔结构的递增。

    分析以上题目,其实就是对ROI区域用指定值进行设定,重点在于掌握Rect函数绘制ROI区域时,确定每次ROI区域的起点坐标x,y,长,宽 四个参数,根据题目要求,实现代码如下:

    
    #include<opencv2/opencv.hpp>
    #include<iostream>
    using namespace cv;
    
    
    int m1ain()
    {
        Mat m = Mat(210, 210, CV_8U, Scalar(0));
        for (int i = 0; i < 210 / 2; i = i + 10)
        {
            Mat roi = m(cv::Rect(i, i, 210 - i * 2, 210 - i * 2));
            roi.setTo(i * 2);// roi = i*2;
    
        }
    
            imshow("image", m);
        waitKey(0);
        return 0;
    }
    

    实现效果如下所示:


    相关文章

      网友评论

          本文标题:利用opencv 实现ROI区域的绘制

          本文链接:https://www.haomeiwen.com/subject/vudkvktx.html