19.java openCV4.x 入门-Imgproc之图形绘制

2024-04-16 08:36

本文主要是介绍19.java openCV4.x 入门-Imgproc之图形绘制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

专栏简介

💒个人主页
📖心灵鸡汤📖

我们唯一拥有的就是今天,唯一能把握的也是今天


建议把本文当作笔记来看,据说专栏目录里面有相应视频🤫
📰专栏目录

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 要绘制线段的图像
recRect对象,表示矩形的位置和大小
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之点集拟合

这篇关于19.java openCV4.x 入门-Imgproc之图形绘制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/908297

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2