【Emgu CV教程】2.3、基本方法之基本绘图函数

1、PutText()绘制文字

利用编程语言输出"Hello World"已经成为初学者必备技能,没有之一。图像处理也可以输出"Hello World",可是它输出到哪里了呢,当然是在图片上。以大名鼎鼎的lena.jpg举例,可以输出这样四种文字效果。

图片中出现了四段文字,代码非常简单,如下:

Mat m = srcMat.Clone();
CvInvoke.PutText(m, "Hello, world", new System.Drawing.Point(10, 50), FontFace.HersheyComplex, 2, new Bgr(255, 0, 0).MCvScalar, 3, LineType.EightConnected, false);
CvInvoke.PutText(m, "Hello, world", new System.Drawing.Point(150, 100), FontFace.HersheyComplex, 1.5, new Bgr(0, 255, 0).MCvScalar, 2, LineType.EightConnected, true);
CvInvoke.PutText(m, "Hello, world", new System.Drawing.Point(300, 200), FontFace.HersheyComplex, 1, new Bgr(0, 0, 255).MCvScalar, 1, LineType.EightConnected, false);
CvInvoke.PutText(m, "Hello, world", new System.Drawing.Point(300, 400), FontFace.HersheyComplex, 0.75, new Bgr(128, 30, 200).MCvScalar, 2, LineType.EightConnected, false);
CvInvoke.Imshow("Result Mat", m);

srcMat就是加载的lena.jpg,下文中还会用到。写文字的时候,就会用到CvInvoke.PutText()函数,官方定义如下:

public static void PutText(
    IInputOutputArray img, // 输入的图像
    string text, // 绘制的文字
    Point org,  // 文本框左下角的坐标,也就是起始坐标
    FontFace fontFace,  // 字体
    double fontScale,  // 尺寸因子,值越大文字越大
    MCvScalar color,  // 文字的颜色,BGR颜色格式
    int thickness = 1, // 文字线条宽度,值越大文字越粗
    LineType lineType = LineType.EightConnected,  // 线型(4邻域或8邻域,默认8邻域)
    bool bottomLeftOrigin = false // 默认false,如果是true,文字会翻转,起始位置也编程左上角的坐标
)

这样再看图中的四段文字怎么得到的,是不是就很清晰了,四个PutText()函数从上到下分别是: 

  •  P(10,50)坐标起始、文字大小是2、蓝色的、文字线条宽是3、8邻域线型、正常绘制。
  •  P(150,100)坐标起始、文字大小是1.5、绿色的、文字线条宽是2、8邻域线型、文字翻转绘制,这时候P(150,100)是文字的左上角了。
  •  P(300,200)坐标起始、文字大小是1、红色的、文字线条宽是1、8邻域线型、正常绘制。
  •  P(300,400)坐标起始、文字大小是0.75、紫色的、文字线条宽是2、8邻域线型、正常绘制。

注意:PutText()函数不支持非ASCII码的字符,包括中文、特殊符号都不能正常显示。据说OpenCV到5.0版本就可以支持了。

2、Line()画直线 

以lena.jpg举例,先看画线的效果。

一共画了四条直线,代码很简单:

Mat m = srcMat.Clone();
CvInvoke.Line(m, new System.Drawing.Point(50, 50), new System.Drawing.Point(200, 50), new MCvScalar(255, 0, 0), 1, LineType.AntiAlias, 0); // 蓝色,线条粗是1
CvInvoke.Line(m, new System.Drawing.Point(100, 100), new System.Drawing.Point(300, 100), new MCvScalar(0, 255, 0), 2, LineType.EightConnected, 0); // 绿色,线条粗是2
CvInvoke.Line(m, new System.Drawing.Point(10, 100), new System.Drawing.Point(400, 400), new MCvScalar(0, 0, 255), 3, LineType.Filled, 0); // 红色,线条粗是3
CvInvoke.Line(m, new System.Drawing.Point(400, 300), new System.Drawing.Point(200, 400), new MCvScalar(255, 255, 0), 8, LineType.FourConnected, 0); // 青色,线条粗是8

Line()函数的官方解释也很简单:

public static void Line(
    IInputOutputArray img, // 输入的图像
    Point pt1, // 起始点坐标
    Point pt2,  // 结束点坐标
    MCvScalar color, // 直线的颜色,BGR颜色格式
    int thickness = 1, // 线条宽度,值越大直线越粗
    LineType lineType = LineType.EightConnected, // 线型(4邻域或8邻域,默认8邻域)
    int shift = 0 // 精度, 点座标中的小数点等级,不知道干什么用的
)

上面四个Line()函数的具体含义,应该能看清了吧。其实就是让Emgu CV连接两个坐标,用什么颜色、多粗的线条展示都可以定义。

3、Circle()画圆

以lena.jpg举例,先看画圆的效果。

在原始图片上画四个圆形,也是执行了四次Circle()函数,如下:

Mat m = srcMat.Clone();
CvInvoke.Circle(m, new System.Drawing.Point(100, 50), 30, new MCvScalar(255, 0, 0), 1, LineType.EightConnected, 0);
CvInvoke.Circle(m, new System.Drawing.Point(100, 200), 80, new MCvScalar(0, 255, 0), -1, LineType.EightConnected, 0); // thickness = -1,代表实心圆
CvInvoke.Circle(m, new System.Drawing.Point(350, 300), 100, new MCvScalar(0, 0, 255), 10, LineType.EightConnected, 0);
CvInvoke.Circle(m, new System.Drawing.Point(150, 400), 100, new MCvScalar(100, 100, 100), -1, LineType.EightConnected, 0); // thickness = -1,代表实心圆

官方对于Circle()函数的定义是:

public static void Circle(
    IInputOutputArray img,  // 输入的图像
    Point center,  // 圆心坐标
    int radius,  // 半径
    MCvScalar color,  // 圆的颜色,BGR颜色格式
    int thickness = 1,  // 圆形线条宽度,默认是1,如果是-1,则代表是实心圆
    LineType lineType = LineType.EightConnected,  // 线型(4邻域或8邻域,默认8邻域)
    int shift = 0 // 精度, 点座标中的小数点等级,不知道干什么用的
)

所以上述的四行画圆代码含义分别是:

  • 在P(100,50)这个点上,画一个半径是30的圆、蓝色、线条宽度是1
  • 在P(100,200)这个点上,画一个半径是80的圆、绿色、实心圆
  • 在P(350,300)这个点上,画一个半径是100的圆、红色、线条宽度是10
  • 在P(150,400)这个点上,画一个半径是100的圆、灰黑色、实心圆

 4、Rectangle()画矩形

先看效果:

也是执行了四次函数,画了四个矩形,代码如下:

Mat m = srcMat.Clone();
CvInvoke.Rectangle(m, new Rectangle(50, 10, 100, 50), new MCvScalar(255, 0, 0), 1, LineType.EightConnected, 0);
CvInvoke.Rectangle(m, new Rectangle(400, 100, 50, 300), new MCvScalar(0, 255, 0), 10, LineType.EightConnected, 0);
CvInvoke.Rectangle(m, new Rectangle(200, 150, 100, 100), new MCvScalar(0, 0, 255), -1, LineType.EightConnected, 0); // thickness = -1,代表实心
CvInvoke.Rectangle(m, new Rectangle(10, 400, 300, 50), new MCvScalar(255, 0, 0), 10, LineType.EightConnected, 0);

官方对于Rectangle()函数的定义是:

public static void Rectangle(
    IInputOutputArray img, // 输入的图像
    Rectangle rect, // 矩形形状,包括左上角起始点坐标,长度、宽度
    MCvScalar color, // 矩形的颜色
    int thickness = 1, // 矩形线条宽度,默认是1,如果是-1,则代表是实心矩形
    LineType lineType = LineType.EightConnected,  // 线型(4邻域或8邻域,默认8邻域)
    int shift = 0 // 精度, 点座标中的小数点等级,不知道干什么用的
)

这个函数的使用也很简单,基本不用再解释了。 

 5、Ellipse()画椭圆

先看效果:

画了五个椭圆,包括完整的、不完整的、空心的、实心的,代码如下:

Mat m = srcMat.Clone();
CvInvoke.Ellipse(m, new System.Drawing.Point(100, 50), new System.Drawing.Size(100, 40), 0, 0, 270, new MCvScalar(255, 0, 0), 1, LineType.EightConnected, 0);
CvInvoke.Ellipse(m, new System.Drawing.Point(200, 200), new System.Drawing.Size(100, 50), 30, 0, 360, new MCvScalar(0, 255, 0), 5, LineType.EightConnected, 0);
CvInvoke.Ellipse(m, new System.Drawing.Point(400, 300), new System.Drawing.Size(100, 200), 0, 0, 180, new MCvScalar(0, 0, 255), -1, LineType.EightConnected, 0);
CvInvoke.Ellipse(m, new System.Drawing.Point(400, 250), new System.Drawing.Size(100, 200), 0, 180, 360, new MCvScalar(0, 128, 128), -1, LineType.EightConnected, 0);
CvInvoke.Ellipse(m, new System.Drawing.Point(200, 400), new System.Drawing.Size(120, 60), 0, 0, 360, new MCvScalar(200, 50, 200), 20, LineType.EightConnected, 0);

此函数官方定义如下:

public static void Ellipse(
    IInputOutputArray img, // 输入的图像
    Point center, // 椭圆中心点坐标
    Size axes, // Size变量,分别代表椭圆的长轴和短轴(长轴半径长度,短轴半径长度)
    double angle, // 椭圆旋转角度,以度为单位,0就是不旋转
    double startAngle, // 画椭圆的起始角度,以度为单位
    double endAngle,  // 画椭圆的结束角度,以度为单位
    MCvScalar color,  // 椭圆的颜色
    int thickness = 1, // 椭圆形线条宽度,默认是1,如果是-1,则代表是实心椭圆
    LineType lineType = LineType.EightConnected, // 线型(4邻域或8邻域,默认8邻域)
    int shift = 0 // 精度, 点座标中的小数点等级,不知道干什么用的
)

这个xue微复杂一点,上面的5个Ellipse()函数其实就是这个意思:

  •  在P(100,50)这个点上,画一个长轴半径是100、短轴半径是40、0度的旋转、从椭圆的0度画到270度、蓝色、线条宽度是1的椭圆。
  •  在P(200,200)这个点上,画一个长轴半径是100、短轴半径是50、30度的旋转、从椭圆的0度画到360度、绿色、线条宽度是5的椭圆。
  •  在P(400,300)这个点上,画一个长轴半径是100、短轴半径是200、0度的旋转、从椭圆的0度画到180度、红色、实心的椭圆。
  •  在P(400,250)这个点上,画一个长轴半径是100、短轴半径是200、0度的旋转、从椭圆的180度画到360度、偏棕色、实心的椭圆。
  •  在P(200,400)这个点上,画一个长轴半径是120、短轴半径是60、0度的旋转、从椭圆的0度画到360度、紫罗兰色、线条宽度是20的椭圆。

如果对于椭圆参数的含义还不清楚,再看看这张图,是不是就容易理解了。

6、ArrowedLine()画带箭头的线

ArrowedLine()函数和Line()差不多,只不过在直线的结尾,多了一个箭头,先看四个箭头的实际效果:

代码如下:

Mat m = srcMat.Clone();
CvInvoke.ArrowedLine(m, new System.Drawing.Point(50, 50), new System.Drawing.Point(200, 50), new MCvScalar(255, 0, 0), 1, LineType.AntiAlias, 0, 0.1); // 蓝色,线条粗是1
CvInvoke.ArrowedLine(m, new System.Drawing.Point(100, 100), new System.Drawing.Point(300, 100), new MCvScalar(0, 255, 0), 2, LineType.EightConnected, 0, 0.1); // 绿色,线条粗是2
CvInvoke.ArrowedLine(m, new System.Drawing.Point(10, 100), new System.Drawing.Point(400, 400), new MCvScalar(0, 0, 255), 3, LineType.Filled, 0, 0.5); // 红色,线条粗是3
CvInvoke.ArrowedLine(m, new System.Drawing.Point(400, 300), new System.Drawing.Point(200, 400), new MCvScalar(255, 255, 0), 8, LineType.FourConnected, 0, 0.2); // 青色,线条粗是8

官方对于ArrowedLine()函数的定义如下:

public static void ArrowedLine(
    IInputOutputArray img, // 输入的图像
    Point pt1, // 起始点坐标
    Point pt2, // 结束点坐标
    MCvScalar color, // 线条的颜色,BGR颜色格式
    int thickness = 1, // 线条宽度,值越大越粗
    LineType lineType = LineType.EightConnected, // 线型(4邻域或8邻域,默认8邻域)
    int shift = 0, // 精度, 点座标中的小数点等级,不知道干什么用的
    double tipLength = 0.1 // 箭头笔尖的长度(相对于线段长度的比例),默认0.1,比例越大箭头越长
)

这个相比Line()画直线函数,其实就多了一个tipLength参数,比如上面代码的第三个ArrowedLine()函数的tipLength就是0.5,意思就是箭头那部分线段的长度是直线长度的0.5倍,细心的读者可以量一量。

总结

上面几个画图函数是最常用的,用起来也非常简单,读者可以多试试,各个参数都调整一下看看效果。

原创不易,请勿抄袭。共同进步,相互学习。

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值