<学习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_​SIM⁠PLEX
    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>

posted @ 2019-11-12 09:13  Xu_Lin  阅读(397)  评论(0编辑  收藏  举报