<学习opencv>绘画和注释
/*=========================================================================*/ // 绘画 和 注释 /*=========================================================================*/ 我们经常想画一些图片,或者在从其他地方获得的图像上画一些东西。 为了达到这个目的,OpenCV提供了一个可以让我们制作线条、正方形、圆形等的功能。 OpenCv的绘图功能可以处理任何深度的图像, 但大多数只影响前三个通道-对于单通道图像,默认为仅第一个通道。 大多数绘图功能都支持对象的颜色、粗细、线条类型(实际上是指是否反混叠线条)和子像素对齐。 指定颜色时,约定是使用cv::scalar对象,即使大多数情况下只使用前三个值。 (有时使用cv::scalar中的第四个值来表示alpha通道比较方便,但绘图函数目前不支持alpha混合) 此外,按照惯例,opencv使用bgrordering将多通道图像转换为颜色渲染 (这是u由绘制函数imshow()生成,它实际上在屏幕上绘制图像以供查看)。 当然,您不必使用这个约定,而且如果您使用的是其他库中的数据, 并且这些库的顶部有opencv头,那么它可能不理想。 在任何情况下,库的核心功能总是与您可能分配给某个通道的任何“含义”无关。 线条艺术和填充多边形 —————————————————————————————————————————————————————————————————————————————— 绘制一种或另一种线条(段、圆、矩形等)的函数通常接受厚度和线型参数。 两者都是整数,但后者唯一可接受的值是4、8或cv::LINE_AA。 厚度是以像素为单位测量的线条的厚度。 对于圆、矩形和所有其他闭合形状,厚度参数也可以设置为cv::filled(它是−1的别名)。 画一条线,种类或其他(片段,圆形,矩形等)的函数通常会接受a thickness 和lineType 参数。 两者都是整数,但对于后者的唯一可接受的值为4 ,8 ,或cv::LINE_AA 。 thickness 是以像素为单位测量的线条粗细。 对于圆形,矩形和所有其他闭合形状,thickness 参数也可以设置为cv::FILLED (这是别名−1 )。 在这种情况下,结果是绘制的图形将填充与边缘相同的颜色。 该lineType 参数表示线路是“4连接”, “8连接”还是抗锯齿。 对于下面两个示例 ,使用了Bresenham算法,而对于抗锯齿线, 使用高斯滤波。宽线总是绘制圆形末端。 列出的绘制算法 ,端点(线),中心点(圆),角(矩形)等通常指定为整数。 但是,这些算法通过shift 参数支持子像素对齐。在shift 可用的地方, 它被解释为整数参数中作为小数位处理的位数。 例如,如果您想要一个以(5,5)为中心的圆,但设置shift 为1,则圆将在(2.5,2.5)处绘制。 这种效果通常非常微妙,取决于所使用的线型。对于抗锯齿线,效果最明显。 【绘图功能】 【【线条艺术和填充多边形】】 —————————————————————————————————————————————————————————————————————————————— 功能 | 描述 —————————————————————————————————————————————————————————————————————————————— cv::circle() | 画出一个简单的圆圈 |——用法: circle( cv::Mat &img , //要绘制的图像 cv::Point center , //圆心的位置 int radius , //圆的半径 const cv::Scalar& color, //颜色,RGB形式 int thickness = 1 , //线的粗细 int lineType = 8 , // Connectedness,4或8 int shift = 0 //作为分数处理的半径位 ) cv::circle()的第一个参数就是图像img。接下来是圆心、二维点和半径。 其余参数是标准颜色、厚度、线型和SHIFT。移动同时应用于半径和中心位置。 —————————————————————————————————————————————————————————————————————————————— cv::clipLine() | 确定一条线是否在给定的椭圆之中 |——用法: bool clipLine(//如果'imgRect'中的任何一行,则为True cv :: Rect imgRect,//要剪切的矩形 cv :: Point&pt1,//行的第一个端点,被覆盖 cv :: Point&pt2 //行的第二个端点,被覆盖 ); bool clipLine(//如果图像大小为行的任何部分,则为True cv :: Size imgSize,//图像大小,表示矩形为0,0 cv :: Point&pt1,//行的第一个端点,被覆盖 cv :: Point&pt2 //行的第二个端点,被覆盖 ); 此函数用于确定两点pt1和pt2指定的线是否位于矩形边界内。 在第一个版本中,提供了一个cv::rect,并将该行与该矩形进行比较。 cv::clipline()仅当行完全在指定矩形区域之外时才会返回false。 第二个版本是相同的,只是它采用了cv::size参数。 调用第二个版本相当于使用一个矩形(x,y)位置为(0,0)调用第一个版本。 —————————————————————————————————————————————————————————————————————————————— cv::ellipse() | 画一个椭圆,可以是倾斜的或椭圆弧的 |——用法: bool ellipse( cv :: Mat&img,//要绘制的图像 cv ::Point center,//椭圆中心的位置 cv ::Size axes,//长轴和短轴的长度 double angle,//长轴倾斜角度 double startAngle,//弧形绘制的起始角度 double endAngle,//弧形绘制的结束角度 const cv ::Scalar& color,//颜色,BGR形式 int thickness = 1,//线的粗细 int lineType = 8,// Connectedness,4或8 int shift = 0 //作为分数处理的半径位 ); bool ellipse( cv :: Mat&img,//要绘制的图像 const cv :: RotatedRect&rect,//旋转矩形边界椭圆 const cv ::Scalar& color,//颜色,BGR形式 int thickness = 1,//线的粗细 int lineType = 8,// Connectedness,4或8 int shift = 0 //作为分数处理的半径位 ); cv::Ellipse()函数与cv::Circle()函数非常相似, 主要区别在于轴参数,其类型为cv::Size。 在这种情况下,height和width参数表示椭圆长轴和短轴的长度。 角度是长轴的角度(以度为单位),从水平(即从x轴)逆时针测量。 同样,start angle和endangle指示(也以度为单位)圆弧的开始和结束角度。 因此,对于完整的椭圆,必须分别将这些值设置为0和360。 指定椭圆图形的另一种方法是使用边界框。 在这种情况下,cv::rotatedrect类型的参数框完全指定椭圆的大小和方向。 —————————————————————————————————————————————————————————————————————————————— cv::ellipse2Poly() | 计算椭圆弧的多边形近似 |——用法: void ellipse2Poly( cv ::Point center,//椭圆中心的位置 cv ::Size axes,//长轴和短轴的长度 double angle,//长轴倾斜角度 double startAngle,//弧形绘制的起始角度 double endAngle,//弧形绘制的结束角度 int delta,//连续顶点之间的角度 vector <cv :: Point>&pts //结果,STL-点向量 ); cv::ellipse2poly()函数在cv::ellipse()内部用于计算椭圆弧,但您也可以自己调用它。 给定有关椭圆弧(中心、轴、角度、开始角度和结束角度-均如cv::Ellipse()中定义) 和参数delta(指定要采样的后续点之间的角度)的信息, cv::Ellipse2Poly()计算形成多边形a的点序列与指定的椭圆弧近似。 计算的点返回到向量<>pts中。 —————————————————————————————————————————————————————————————————————————————— cv::fillConvexPoly() | 绘制简单多边形的填充版本 |——用法: void fillConvexPoly( cv::Mat& img , //要绘制的图像 const cv::Point* pts , /// C风格的点数组 int npts , //'pts'中的点数 const cv::Scalar& color , //颜色,BGR形式 int lineType = 8 , // Connectedness,4或8 int shift = 0 //作为分数处理的半径位 ) 此函数绘制一个填充多边形。它比cv::fillpy()快得多,因为它使用的算法要简单得多。 但是,如果传递给它的多边形具有自交集,则cv::FillConverxpoly()使用的算法将无法正常工作。 PTS中的点被视为连续的,并且PTS中的最后一点和第一点之间的一段是隐含的(即假定多边形是闭合的)。 —————————————————————————————————————————————————————————————————————————————— cv::fillPoly() | 绘制任意多边形的填充版本 |——用法: void fillPoly( cv :: Mat&img, //要绘制的图像 const cv :: Point * pts, // C样式的点数组数组 int npts, //'pts [i]'中的点数 int ncontours, //'pts'中的数组数 const cv ::Scalar& color, //颜色,BGR形式 int lineType = 8, // Connectedness,4或8 int shift = 0, //作为分数处理的半径位 cv :: Point offset = Point() //应用于所有点的均匀偏移量 ); 此函数绘制任意数量的填充多边形。cv::fillConvexPoly() 与之不同,它可以处理具有自交叉的多边形。 所述ncontours 参数指定不同多边形轮廓有多少会,并且npts 参数是一个C数组, 指示多少个点有在每个轮廓(即,npts[i] 表示有多少点有在多边形i )。 pts 是包含这些多边形中所有点的C样式数组的C样式数组 (即,pts[i][j]包含第多个多边形j中的i第th个点)。 cv::fillPoly() 还有一个附加参数,offset 它是一个像素偏移量,在绘制多边形时将应用于所有顶点位置。 假设多边形是闭合的(即,从最后一个元素开始的一个分段)pts[i][] 将假设第一个元素)。 —————————————————————————————————————————————————————————————————————————————— cv::line() | 画一条简单的线 |——用法: line( cv :: Mat&img, //要绘制的图像 cv :: Point pt1, //行的第一个端点 cv :: Point pt2 //行的第二个端点 const cv ::Scalar& color, //颜色,BGR形式 int lineType = 8, // Connectedness,4或8 int shift = 0 //作为分数处理的半径位 ); 函数cv::line()在图像img中绘制一条从pt1到pt2的直线。线条被图像边界自动裁剪。 —————————————————————————————————————————————————————————————————————————————— cv::rectangle() | 画一个简单的线 |——用法: void rectangle( cv :: Mat&img, //要绘制的图像 cv :: Point pt1, //矩形的第一个角 cv :: Point pt2 //矩形的对角 const cv ::Scalar& color, //颜色,BGR形式 int lineType = 8, // Connectedness,4或8 int shift = 0 //作为分数处理的半径位 ); void rectangle( cv :: Mat&img, //要绘制的图像 cv :: Rect r, //要绘制的矩形 const cv ::Scalar& color, //颜色,BGR形式 int lineType = 8, // Connectedness,4或8 int shift = 0 //作为分数处理的半径位 ); 函数的作用是:在图像img中绘制一个角为pt1到pt2的矩形。 此函数的另一种形式允许由单个cv::rect参数r指定矩形的位置和大小。 —————————————————————————————————————————————————————————————————————————————— cv::polyLines() | 绘制多条多边形曲线 |——用法: void polyLines( cv :: Mat&img, //要绘制的图像 const cv :: Point * pts, // C样式的点数组数组 int npts, //'pts [i]'中的点数 int ncontours, //'pts'中的数组数 bool isClosed, //如果为true,则连接last和first pts const cv ::Scalar& color, //颜色,BGR形式 int lineType = 8, // Connectedness,4或8 int shift = 0 //作为分数处理的半径位 ); 此函数绘制任意数量的未填充多边形。它可以处理一般多边形,包括具有自交叉的多边形。 所述ncontours 参数指定不同多边形轮廓有多少会,并且npts 参数是一个C数组, 指示多少个点有在每个轮廓(即,npts[i] 表示有多少点有在多边形i )。 pts 是包含这些多边形中所有点的C样式数组的C样式数组 (即,pts[i][j]包含第多个多边形j中的i第th个点)。不假设多边形是封闭的。 如果参数isClosed 是true ,那么pts[i][] 将假定从最后一个元素到第一个元素的一个段。 否则,轮廓被视为一个开放的轮廓,仅包含npts[i]-1 在轮廓之间的区段npts[i]列出的点数。 —————————————————————————————————————————————————————————————————————————————— cv::LineIterator() | |——用法: LineIterator()::LineIterator( cv::Mat& img , //要绘制的图像 cv::Point pt1 , //行的第一个端点 cv::Point pt2 , //行的第二个端点 int lineType = 8 , //Connectedness,4或8 bool leftToRight = false //如果为true,则始终在左侧开始 ) cv::lineIterator对象是一个迭代器,用于按顺序获取光栅线的每个像素。 行迭代器是opencv中函数的第一个示例。我们将在下一章中看到更多这些“做事情的对象”。 行迭代器的构造函数接受行的两个端点,以及一个行类型说明符和一个附加的布尔值,该值指示行应该遍历的方向。 初始化后,行中的像素数存储在成员整数cv::lineIterator::count中。 重载的取消引用运算符cv::lineIterator::operator*()返回类型为uchar*的指针, 该指针指向“当前”像素。当前像素从行的一端开始, 并通过重载的递增运算符cv::lineIterator::operator++()递增。 实际的遍历是根据前面提到的Bresenham算法完成的。 [注意] 重载解除引用运算符的样式cv::LineIterator::operator*()与STL等库可能习惯的样式略有不同。 不同之处在于迭代器的返回值本身就是一个指针,因此迭代器的行为不像指针,而是指向指针的指针。 —————————————————————————————————————————————————————————————————————————————— 【【字体和文字】】 另一种绘图形式是绘制文本。 —————————————————————————————————————————————————————————————————————————————— 功能 | 描述 cv::putText() | 在图像中绘制指定的文本 |——用法: void cv::putText( cv::Mat& img, //要绘制的图像 const string& text , //要写这个(通常来自cv::format) int fontFace , //Font(例如,cv::FONT_HERSHEY_PLAIN) double fontScale , //size(乘数,不是"points"") cv::Scalar& color , //颜色,RGB int thickness = 1 , //线的粗细 int lineType = 8 , //Connectedness,4或8 bool bottomLeftOrigin = false //true = "左下角的原点" ) 这个函数是OpenCV的一个主要文本绘图程序; 它只是将一些文本抛到图像上。 指示的文本text 打印时,文本框的左上角位于origin 和指示的颜色color, 除非bottomLeftOrigin 标志是true,在这种情况下,文本框的左下角位于origin 。 使用的字体由fontFace 参数选择,其中可以是任何一个列于下表的字体。 可用的字体(都是Hershey的变体) 识别码 描述 —————————————————————————————————————————————————————————————————————————— cv::FONT_HERSHEY_SIMPLEX 正常尺寸sans-serif cv::FONT_HERSHEY_PLAIN 小尺寸无衬线 cv::FONT_HERSHEY_DUPLEX 正常尺寸sans-serif; 比...更复杂cv::FONT_HERSHEY_SIMPLEX cv::FONT_HERSHEY_COMPLEX 正常大小的衬线; 比...更复杂cv::FONT_HERSHEY_DUPLEX cv::FONT_HERSHEY_TRIPLEX 正常大小的衬线; 比...更复杂cv::FONT_HERSHEY_COMPLEX cv::FONT_HERSHEY_COMPLEX_SMALL 较小的版本 cv::FONT_HERSHEY_COMPLEX cv::FONT_HERSHEY_SCRIPT_SIMPLEX 手写风格 cv::FONT_HERSHEY_SCRIPT_COMPLEX 更复杂的变种 cv::FONT_HERSHEY_SCRIPT_SIMPLEX —————————————————————————————————————————————————————————————————————————— 列出的任何字体名称 也可以组合(通过OR运算符)以cv::FONT_HERSHEY_ITALIC 斜体显示指示的字体。 每种字体都有“自然”大小。如果fontScale 不是1.0,则在绘制文本之前,通过此数字缩放字体大小。 —————————————————————————————————————————————————————————————————————————————— cv::getTextSize() | 确定文本字符串的宽度和高度 |——用法: cv::Size::getTextSize( const string& text , cv::Point origin , int fontFace , double fontScale , int thickness , int* baseLine ) ; cv::gettextsize()函数回答了这样一个问题: 如果不在图像上绘制文本(使用一些参数集),那么某些文本会有多大。 cv::gettextsize()唯一新颖的参数是baseline,它实际上是一个输出参数。 基线是文本基线相对于文本最低点的Y坐标 ——————————————————————————————————————————————————————————————————————————————
参考书籍:<学习opencv>
Talk is cheap. Show me the code