专栏简介 | ||
💒个人主页 | 📖心灵鸡汤📖 我们唯一拥有的就是今天,唯一能把握的也是今天 建议把本文当作笔记来看,据说专栏目录里面有相应视频🤫 | 📰专栏目录 |
Imgproc之图像绘制
- 一、直线绘制
- 字段
- 1.带箭直线绘制
- 2.普通直线绘制
- 1.line
- 2.polylines
- 二、矩形绘制
- 三、圆绘制
- 四、椭圆(椭圆弧)绘制
- 五、多边形填充
- 1.单个填充
- 2.多个填充
- 六、标记绘制
- 1.字段
- 2.方法介绍
- 七、文本绘制
- 1.字段
- 2.方法介绍
- 八、相关扩展方法
- 1.线段裁定
- 2.椭圆弧转换为多段线
- 3.计算字体尺寸比例
本节内容比较简单,但是很重要
一、直线绘制
线段被图像边界裁剪。对于非抗锯齿的整数坐标线,使用8-连接或4-连接的Bresenham算法。粗线以圆角结束绘制。抗锯齿线使用高斯滤波器绘制。
字段
LINE_4 | 使用4点线段。这通常用于表示直线,使用起点和终点坐标 |
LINE_8 | 使用8点线段。这提供了更多的控制点,可以用于更精确地表示曲线或直线 |
LINE_AA | 使用抗锯齿线段。抗锯齿技术用于平滑线条的边缘,使其看起来更平滑和自然 |
1.带箭直线绘制
1.在给定的图像上,从第一个点到第二个点绘制一个箭头线段
arrowedLine(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int line_type, int shift, double tipLength) | |
参数: | |
img | 要绘制线段的图像 |
pt1 | 线段的起始点坐标 |
pt2 | 线段的终点坐标 |
color | 线段的颜色 |
thickness | 线段的粗细 |
line_type | 线段的类型。 参见 #LINE_* |
shift | 坐标点的小数位数 |
tipLength | 箭头尖端的长度与箭头长度之间的关系 |
//创建一个图像Mat mat = new Mat(400,400, CvType.CV_8UC3);//设置颜色mat.setTo(new Scalar(0,0,0));// 定义线段的起始点和终点坐标Point pt1 = new Point(50, 50);Point pt2 = new Point(350, 350);// 定义线段的颜色Scalar color = new Scalar(0, 0, 255);int lineType=Imgproc.LINE_AA;Imgproc.arrowedLine(mat,pt1,pt2,color,10, lineType, 0, 0.1);HighGui.imshow("mat",mat);HighGui.waitKey();
结果:
2.普通直线绘制
1.line
1.图像上绘制直线(线段被图像边界裁剪)
line(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int lineType, int shift) | |
参数: | |
img | 要绘制线段的图像 |
pt1 | 线段的起始点坐标 |
pt2 | 线段的终点坐标 |
color | 线段的颜色 |
thickness | 线段的粗细 |
line_type | 线段的类型。 参见 #LINE_* |
shift | 坐标点的小数位数 |
//创建矩阵Mat img = new Mat(200,300, CvType.CV_8UC3,new Scalar(0,0,0) );//定义线段开始结束坐标pt1Point pt1 = new Point(20,20);Point pt2 = new Point(100,100);Point pt3 = new Point(150,100);//定义绘制的颜色Scalar scalar= new Scalar(0,255,0);//定义线条粗细int thickness = 2;//定义线条类型int lineType=Imgproc.LINE_AA;//定义点坐标小数位数int shift=0;Imgproc.line(img,pt1,pt2,scalar,thickness,lineType,shift);Imgproc.line(img,pt2,pt3,scalar,thickness,lineType,shift);//显示HighGui.imshow("img",img);HighGui.waitKey();
结果:
2.polylines
1.绘制多段线
polylines(Mat img, java.util.List pts, boolean isClosed, Scalar color, int thickness, int lineType, int shift) | |
参数: | |
img | 要绘制线段的图像 |
pts | 包含多段线顶点的 java.util.List 对象。每个 MatOfPoint 对象表示多段线的一个单独部分 |
isClosed | 一个布尔值,指示多段线是否闭合。如果为 true,则多段线闭合;如果为 false,则不闭合 |
color | 线段的颜色 |
thickness | 线段的粗细 |
line_type | 线段的类型。 参见 #LINE_* |
shift | 坐标点的小数位数 |
Mat mat = new Mat(500,500, CvType.CV_8UC3);mat.setTo(new Scalar(255,255,255));List<MatOfPoint> pts = new ArrayList<>();MatOfPoint point = new MatOfPoint();point.fromArray(new Point(50,50),new Point(150,90),new Point(80,180),new Point(250,250));pts.add(point);Imgproc.polylines(mat,pts,false,new Scalar(0,255,0),2,Imgproc.LINE_AA,0);HighGui.imshow("mat",mat);HighGui.waitKey();
二、矩形绘制
1.矩形绘制(填充)
rectangle(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int lineType, int shift) | |
参数: | |
img | 要绘制线段的图像 |
pt1 | 矩形的一个角的坐标 |
pt2 | 与 pt1 相对的矩形角的坐标 |
color | 矩形的颜色 |
thickness | 构成矩形的线条的厚度,-1则表示填充矩形 |
line_type | 线段的类型。 参见 #LINE_* |
shift | 坐标点的小数位数 |
Mat mat = new Mat(300,300, CvType.CV_8UC3);
mat.setTo(new Scalar(255,255,255));Imgproc.rectangle(mat,new Point(50,50),new Point(250,250),new Scalar(0,250,0),4,Imgproc.LINE_AA,0);HighGui.imshow("mat",mat);
HighGui.waitKey();
结果:
2.矩形绘制(填充)
rectangle(Mat img, Rect rec, Scalar color, int thickness, int lineType, int shift) | |
参数: | |
img | 要绘制线段的图像 |
rec | Rect对象,表示矩形的位置和大小 |
color | 矩形的颜色 |
thickness | 构成矩形的线条的厚度,-1则表示填充矩形 |
line_type | 线段的类型。 参见 #LINE_* |
shift | 坐标点的小数位数 |
三、圆绘制
1.绘制一个圆
circle(Mat img, Point center, int radius, Scalar color, int thickness, int lineType, int shift) | |
参数: | |
img | 要绘制圆的图像 |
center | 圆心的坐标(x, y) |
radius | 圆的半径 |
color | 圆的颜色 |
thickness | 圆的线条厚度。如果为正数,表示绘制圆的外轮廓;如果为负数,表示绘制填充圆 |
line_type | 圆的边界类型。 参见 #LINE_* |
shift | 圆心和半径值的坐标的小数位数 |
//创建矩阵Mat img = new Mat(300,420, CvType.CV_8UC3,new Scalar(255,255,255));//定义坐标Point point = new Point(100,100);//定义半径int radius=50;//定义颜色Scalar scalar = new Scalar(255, 0, 0);//绘制圆Imgproc.circle(img,point,radius,scalar,4,Imgproc.LINE_AA,0);//蓝色圆//====在上方的基础上绘制一个五环===//定义坐标Point point1 = new Point(210,100);Point point2 = new Point(320,100);Point point3 = new Point(150,160);Point point4 = new Point(260,160);//定义颜色Scalar scalar1 = new Scalar(0, 0, 0);Scalar scalar2 = new Scalar(0,0,255);Scalar scalar3 = new Scalar(0,215,255);Scalar scalar4 = new Scalar(0,215,0);//绘制圆Imgproc.circle(img,point1,radius,scalar1,4,Imgproc.LINE_AA,0);//黑色圆Imgproc.circle(img,point2,radius,scalar2,4,Imgproc.LINE_AA,0);//红色圆Imgproc.circle(img,point3,radius,scalar3,4,Imgproc.LINE_AA,0);//黄色圆Imgproc.circle(img,point4,radius,scalar4,4,Imgproc.LINE_AA,0);//绿色圆//显示HighGui.imshow("img",img);HighGui.waitKey();
结果:
四、椭圆(椭圆弧)绘制
使用分段线性曲线近似椭圆弧边界。如果您需要更多控制椭圆渲染,您可以使用 #ellipse2Poly 获取曲线,然后使用 #polylines 渲染或使用 #fillPoly 填充。如果您使用该函数的第一个变体并希望绘制整个椭圆而不是弧 ,请传递 startAngle=0 和 endAngle=360。如果 startAngle 大于 endAngle,它们将被交换。下面的图说明了绘制蓝色弧的参数的含义
ellipse(Mat img, Point center, Size axes, double angle, double startAngle, double endAngle, Scalar color, int thickness, int lineType, int shift) | |
参数: | |
img | 要绘制椭圆的图像 |
center | 椭圆的中心点 |
axes | 椭圆的两个轴的长度(Size类型,包含宽度和高度) |
angle | 椭圆的旋转角度(以度为单位) |
startAngle | 椭圆弧的起始角度(以度为单位) |
endAngle | 椭圆弧的结束角度(以度为单位) |
color | 椭圆的颜色 |
thickness | 这是线条的厚度。如果设置为负数,则会填充椭圆 |
line_type | 边界类型。 参见 #LINE_* |
shift | 点坐标中的小数位数 |
//创建空白图像Mat mat = new Mat(500,500, CvType.CV_8UC3,new Scalar(255,255,255));//椭圆中心点Point point = new Point(250,250);//轴长Size axes = new Size(200,150);//旋转角度double angle = 0;//起始角度double startAngle= 0;//结束角度double endAngle = 360;Imgproc.ellipse(mat,point,axes,angle,startAngle,endAngle,new Scalar(0,200,0),2,Imgproc.LINE_8,0);//绘制椭圆double vals[]={200,200,100,100,0};RotatedRect box = new RotatedRect(vals);Imgproc.ellipse(mat,box,new Scalar(0,0,255),2,Imgproc.LINE_8);Imgcodecs.imwrite(FileUtil.resPath + "imgproc/ellipse.jpg",mat);
结果:
2.椭圆绘制
ellipse(Mat img, RotatedRect box, Scalar color, int thickness, int lineType) | |
参数: | |
img | 要绘制椭圆的图像 |
box | 这是一个 RotatedRect 对象,表示椭圆的边界框 |
axes | 椭圆的两个轴的长度(Size类型,包含宽度和高度) |
angle | 椭圆的旋转角度(以度为单位) |
startAngle | 椭圆弧的起始角度(以度为单位) |
endAngle | 椭圆弧的结束角度(以度为单位) |
color | 椭圆的颜色 |
thickness | 这是线条的厚度。如果设置为负数,则会填充椭圆 |
line_type | 边界类型。 参见 #LINE_* |
shift | 点坐标中的小数位数 |
五、多边形填充
1.单个填充
fillConvexPoly 用于绘制填充的凸多边形它不仅可以填充凸多边形,还可以填充任何单调的非自相交多边形,即轮廓最多与每条水平线(扫描线)相交两次的多边形(尽管其顶部和/或底部边缘可能是水平的)
fillConvexPoly(Mat img, MatOfPoint points, Scalar color, int lineType, int shift) | |
参数: | |
img | 输入/输出图像 |
points | 含多边形顶点坐标的 MatOfPoint 对象 |
color | 填充多边形时使用的颜色 |
line_type | 边界类型。 参见 #LINE_* |
shift | 点坐标中的小数位数 |
Mat mat = new Mat(500,500, CvType.CV_8UC3,new Scalar(255,255,255));MatOfPoint matOfPoint = new MatOfPoint();matOfPoint.fromArray(new Point(100 ,100 ),new Point(400 ,100 ),new Point(400 ,400 ),new Point(100 ,400 ));//填充多边形Imgproc.fillConvexPoly(mat,matOfPoint,new Scalar(0,255,0),Imgproc.LINE_8,0);HighGui.imshow("fill",mat);HighGui.waitKey();mat.release();HighGui.destroyAllWindows();
2.多个填充
fillPoly 用于填充由多个多边形轮廓所包围的区域。该函数可以填充复杂的区域,例如包含空洞的区域、具有自交点(即某些部分相互交叉)的轮廓等等.
fillPoly(Mat img, java.util.List pts, Scalar color, int lineType, int shift, Point offset) | |
参数: | |
img | 输入/输出图像 |
pts | 包含多边形顶点坐标的 java.util.List 对象 |
color | 填充多边形时使用的颜色 |
line_type | 边界类型。 参见 #LINE_* |
offset | 填充多边形时的偏移量,是一个 Point 对象 |
Mat mat = new Mat(500,500, CvType.CV_8UC3,new Scalar(255,255,255));MatOfPoint matOfPoint = new MatOfPoint();MatOfPoint matOfPoint1 = new MatOfPoint();matOfPoint.fromArray(new Point(100 ,100 ),new Point(400 ,100 ),new Point(400 ,400 ),new Point(100 ,400 ));matOfPoint1.fromArray(new Point(50 ,50 ),new Point(200 ,50 ),new Point(200 ,200 ),new Point(50 ,200 ));List pts = new ArrayList<>();pts.add(matOfPoint); pts.add(matOfPoint1);//填充多边形Imgproc.fillPoly(mat,pts,new Scalar(0,255,0),Imgproc.LINE_8,0);HighGui.imshow("fill",mat);HighGui.waitKey();mat.release();HighGui.destroyAllWindows();
结果:
六、标记绘制
1.字段
列举部分
MARKER_CROSS | 十字形标记 |
MARKER_DIAMOND | 菱形标记 |
MARKER_SQUARE | 正方形标记 |
MARKER_STAR | 五角星标记 |
2.方法介绍
在图像中预定义的位置绘制标记
drawMarker(Mat img, Point position, Scalar color, int markerType, int markerSize, int thickness, int line_type) | |
参数: | |
img | 输入/输出图像 |
position | 标记的位置 |
color | 标记的颜色 |
markerType | 标记的类型,表示标记的形状。可以使用Imgproc类中定义的常量,如Imgproc.MARKER_CROSS等 |
markerSize | 标记轴的长度(标记的大小) [默认 = 20 像素] |
thickness | 标记的线条粗细 |
line_type | 线条类型。 |
// 创建一个空白图像Mat img = Mat.zeros(500, 500, 16); // 16表示CV_8UC3,即3通道的8位无符号整数图像// 定义标记的位置、颜色和其他参数Point position = new Point(250, 250); // 在图像中心Scalar color = new Scalar(0, 255, 0); // 绿色int markerType = Imgproc.MARKER_CROSS;int markerSize = 20;int thickness = 2;int lineType = Imgproc.LINE_8;// 在图像上绘制标记Imgproc.drawMarker(img, position, color, markerType, markerSize, thickness, lineType);// 显示图像HighGui.imshow("DrawMarkerExample", img);HighGui.waitKey(0);HighGui.destroyAllWindows();
结果:
七、文本绘制
如果使用指定的字体无法渲染某些符号,它们将被替换为问号。
1.字段
列举部分。
FONT_HERSHEY_COMPLEX | 使用复杂的 Hershey 字体风格。这是默认的字体样式,提供多种字符集和可读性 |
FONT_HERSHEY_PLAIN | 使用简单的 Hershey 字体风格。字体比 FONT_HERSHEY_COMPLEX 更简单,但仍然具有多种字符集 |
FONT_HERSHEY_SCRIPT_COMPLEX | 使用复杂的 Hershey 手写字体风格。这种字体模仿手写文字的外观 |
FONT_HERSHEY_SIMPLEX | 使用Hershey简单字体风格。这种字体提供了一种清晰、简洁的外观,适合于在图像上绘制文本时要求较高的可读性和易读性的场景 |
FONT_HERSHEY_TRIPLEX | 使用三重的 Hershey 字体风格,提供更多的字符集和可读性 |
2.方法介绍
1.绘制一个文本字符串
putText(Mat img, java.lang.String text, Point org, int fontFace, double fontScale, Scalar color, int thickness, int lineType, boolean bottomLeftOrigin) | |
参数: | |
img | 输入/输出图像 |
text | 要绘制的文本字符串 |
org | 指定文本字符串的起始位置(左下角或右下角,取决于bottomLeftOrigin参数) |
fontFace | 指定字体类型。OpenCV提供了一些预定义的字体,如FONT_HERSHEY_SIMPLEX、FONT_HERSHEY_PLAIN等 |
fontScale | 指定字体大小。它表示字体相对于原始大小的缩放因子 |
color | 指定文本的颜色 |
thickness | 文本线条线条粗细 |
line_type | 线条类型。 |
bottomLeftOrigin | boolean类型,指定文本字符串的起始位置是否从图像的左下角开始。如果为true,则文本从左下角开始绘制;如果为false,则从图像的右下角开始绘制 |
// 创建一个空白图像Mat img = Mat.zeros(200, 400, CvType.CV_8UC3);//绘制文本Imgproc.putText(img,"hello OpenCV",new Point(100,100),Imgproc.FONT_HERSHEY_SIMPLEX,1,new Scalar(0,255,0),1,Imgproc.LINE_AA,false);// 显示图像HighGui.imshow("img", img);HighGui.waitKey(0);HighGui.destroyAllWindows();
结果:
八、相关扩展方法
1.线段裁定
clipLine用于检查线段是否完全位于给定的图像边界内,并进行裁剪。如果线段与图像边界相交或超出边界,它将被裁剪到边界内。函数返回一个布尔值,指示线段是否被裁剪。
clipLine(Rect imgRect, Point pt1, Point pt2) | |
参数: | |
img | 输入/输出图像 |
pts | 包含多边形顶点坐标的 java.util.List 对象 |
color | 填充多边形时使用的颜色 |
line_type | 边界类型。 参见 #LINE_* |
offset | 填充多边形时的偏移量,是一个 Point 对象 |
// 创建一个图像矩形范围Rect imgRect = new Rect(0, 0, 100, 100);// 创建线段的起点和终点Point pt1 = new Point(50, 50);Point pt2 = new Point(60, 150);// 剪裁线段,使其位于图像矩形范围内boolean clipped = Imgproc.clipLine(imgRect, pt1, pt2);if (clipped) {System.out.println("线段被剪裁后的起点:" + pt1);System.out.println("线段被剪裁后的终点:" + pt2);} else {System.out.println("线段完全位于图像矩形范围之外");}
结果
线段被剪裁后的起点:{50.0, 50.0}
线段被剪裁后的终点:{55.0, 99.0}
2.椭圆弧转换为多段线
ellipse2Poly用于将椭圆弧转换为多段线 如果arcStart的值大于arcEnd,那么这两个值会被交换。
ellipse2Poly(Point center, Size axes, int angle, int arcStart, int arcEnd, int delta, MatOfPoint pts) | |
参数: | |
center | 椭圆的中心点坐标 (Point 类型) |
axes | 椭圆的半长轴和半短轴的长度 (Size 类型). |
angle | 椭圆的旋转角度 |
arcStart | 椭圆弧的起始角度 |
arcEnd | 椭圆弧的结束角度 |
delta | 角度增量,用于计算椭圆弧上的点。增加这个值会增加多段线的精度 |
pts | 输出参数,包含生成的椭圆边界点的 MatOfPoint 对象. |
//创建空白图像Mat mat = new Mat(500,500, CvType.CV_8UC3,new Scalar(255,255,255));//椭圆中心点Point point = new Point(250,250);//轴长Size axes = new Size(200,150);//旋转角度int angle = 0;//起始角度int arcStart= 0;//结束角度int arcEnd = 360;//转换成线段MatOfPoint matOfPoint = new MatOfPoint();Imgproc.ellipse2Poly(point,axes,angle,arcStart,arcEnd,10,matOfPoint);System.out.println("matOfPoint.dump() = " + matOfPoint.dump());//绘制线段List pts = new ArrayList<>();pts.add(matOfPoint);Imgproc.polylines(mat,pts,true,new Scalar(255,0,0),2);Imgcodecs.imwrite(FileUtil.resPath + "imgproc/ellipse_2_poly.jpg",mat);
请自行验证结果
。
3.计算字体尺寸比例
getFontScaleFromHeight用于根据给定的像素高度计算字体尺寸比例。这对于绘制文本到图像上时非常有用,特别是当您需要确保文本的高度与给定的像素高度相匹配时。
请注意,此方法返回的是字体尺寸的比例因子,而不是具体的像素值或绝对大小。这意味着,如果您使用返回的比例因子与某个基础字体大小(例如 12)相乘,您将获得合适的字体大小以匹配给定的像素高度。
getFontScaleFromHeight(int fontFace, int pixelHeight, int thickness) | |
参数: | |
fontFace | 字体类型 |
pixelHeight | 目标像素高度. |
thickness | 文本的线条粗细 |
请自行验证结果
。
万水千山总是情,本栏完全公开免费。点赞+收藏过30,瞬更下一篇 | |
上一篇:Imgproc之色彩映射及颜色空间转换 | 下一篇: Imgproc之点集拟合 |