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倍,细心的读者可以量一量。
总结
上面几个画图函数是最常用的,用起来也非常简单,读者可以多试试,各个参数都调整一下看看效果。
原创不易,请勿抄袭。共同进步,相互学习。