随机生成一幅指定大小的三通道图像,设定其所有元素均为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>0
和thickness<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;
}
实现效果如下所示:
网友评论