利用opencv 实现ROI区域的绘制

随机生成一幅指定大小的三通道图像,设定其所有元素均为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
#include
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
#include
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区域的绘制)