标签 opencv 下的文章

1. createTrackbar是Opencv中的API,其可在显示图像的窗口中快速创建一个滑动控件,用于手动调节阈值,具有非常直观的效果。具体定义如下:

    CV_EXPORTS int createTrackbar(const string& trackbarname, const string& winname,
                                  int* value, int count,
                                  TrackbarCallback onChange = 0,
                                  void* userdata = 0);

形式参数一、trackbarname:滑动空间的名称;

形式参数二、winname:滑动空间用于依附的图像窗口的名称;

形式参数三、value:初始化阈值;

形式参数四、count:滑动控件的刻度范围;

形式参数五、TrackbarCallback是回调函数,其定义如下:

typedef void (CV_CDECL *TrackbarCallback)(int pos, void* userdata);

参考: https://blog.csdn.net/mysee1989/article/details/41379817 https://docs.opencv.org/3.4.1/dc/dfa/Morphology_1_8cpp-example.html#a20

2. Rect 是矩形类,成员变量x、y、width、height,分别为左上角点的坐标和矩形的宽和高。常用的成员函数有Size()返回值为一个Size,area()返回矩形的面积,contains(Point)用来判断点是否在矩形内,inside(Rect)函数判断矩形是否在该矩形内,tl()返回左上角点坐标,br()返回右下角点坐标。

Rect类的使用

    rect = rect ± point (shifting a rectangle by a certain offset)
    rect = rect ± size (expanding or shrinking a rectangle by a certain amount)
    rect += point, rect -= point, rect += size, rect -= size (augmenting operations)
    rect = rect1 & rect2 (rectangle intersection)
    rect = rect1 | rect2 (minimum area rectangle containing rect1 and rect2 )
    rect &= rect1, rect |= rect1 (and the corresponding augmenting operations)
    rect == rect1, rect != rect1 (rectangle comparison)

参考: https://www.cnblogs.com/happyamyhope/p/9844629.html

3. copyTo 是深拷贝,但是要根据大小信息,决定是否重新申请空间,clone 不管大小信息,全部重新申请空间进行深拷贝。

参考: https://blog.csdn.net/u013806541/article/details/70154719

4. opencv 提供的字符串格式化如下:

string formated_str = format("I have made %d dollars on this product.", 500);

参考: https://blog.csdn.net/yiyeshuanglinzui/article/details/108388683

5. 获取矩阵的行,列,位数。

Mat(int rows, int cols, int type), 直接使用属性就行。

m.rows
m.cols

参考: https://blog.csdn.net/renweiyi1487/article/details/101616758

6. 添加文字, putText

void cv::putText    (   InputOutputArray    img,
        const String &      text,
        Point   org,
        int     fontFace,
        double      fontScale,
        Scalar      color,
        int     thickness = 1,
        int     lineType = LINE_8,
        bool    bottomLeftOrigin = false 
    )   
    cv::putText(image, text, origin, font_face, font_scale, cv::Scalar(0, 255, 255), thickness, 8, 0);

参考:https://docs.opencv.org/3.4/d6/d6e/group__imgproc__draw.html#ga5126f47f883d730f633d74f07456c576 https://blog.csdn.net/guduruyu/article/details/68491211

7. imutils 有 c++ 的部分实现,https://github.com/minooei/imutils

8. 获得轮廓最小矩形,使用 boundingRect

Rect boundRect = boundingRect( contours_poly[i] );

参考: https://docs.opencv.org/3.4/da/d0c/tutorial_bounding_rects_circles.html

9. 矩形 rectangle()

void cv::rectangle  (   InputOutputArray    img,
        Point   pt1,
        Point   pt2,
        const Scalar &      color,
        int     thickness = 1,
        int     lineType = LINE_8,
        int     shift = 0 
    )   
void cv::rectangle  (   Mat &   img,
        Rect    rec,
        const Scalar &      color,
        int     thickness = 1,
        int     lineType = LINE_8,
        int     shift = 0 
    )   
rectangle(src, boundRect[i], Scalar(0, 255, 0));
rectangle(flipFrame, Point(roi_ws, roi_hs), Point(roi_we, roi_he), Scalar(0, 255, 0), 0)

参考: https://docs.opencv.org/3.4/d6/d6e/group__imgproc__draw.html#ga07d2f74cadcf8e305e810ce8eed13bc9 https://kknews.cc/code/66yekj3.html

10. 获得轮廓最小面积

◆ contourArea()
double cv::contourArea  (   InputArray      contour,
        bool    oriented = false 
    )   
fabs(contourArea(Mat(c)));

参考: https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#ga2c759ed9f497d4a618048a2f56dc97f1 https://docs.opencv.org/3.4.1/dd/d9d/segment_objects_8cpp-example.html#a1

11. 膨胀

◆ dilate()
void cv::dilate     (   InputArray      src,
        OutputArray     dst,
        InputArray      kernel,
        Point   anchor = Point(-1,-1),
        int     iterations = 1,
        int     borderType = BORDER_CONSTANT,
        const Scalar &      borderValue = morphologyDefaultBorderValue() 
    )   
dilate(mid_filer,gray_dilate1,element);

参考: https://docs.opencv.org/3.4/d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c https://www.itread01.com/articles/1478557515.html https://docs.opencv.org/3.4.1/d8/dc0/morphology2_8cpp-example.html#a10 https://zhuanlan.zhihu.com/p/40326127 https://www.jianshu.com/p/ee72f5215e07 https://www.cnblogs.com/ssyfj/p/9276999.html

12. 查找轮廓

    findContours(image,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point());

查找轮廓的参数导致的结果,参考: https://blog.csdn.net/dcrmg/article/details/51987348

13. mat 的创建,复制和释放,构造函数等等

参考: https://blog.csdn.net/wanggao_1990/article/details/53150926 https://blog.csdn.net/guyuealian/article/details/70159660

14. createTrackbar 用于创建滑动控件,方便调试效果。

参考: https://blog.csdn.net/u013270326/article/details/72821149

15. 求差 absdiff

absdiff(frameNow,framePre,frameDet);

参考: https://blog.csdn.net/dcrmg/article/details/52234929

16. 翻转图像

flip()
void cv::flip   (   InputArray      src,
        OutputArray     dst,
        int     flipCode 
    )   

参考: https://docs.opencv.org/3.4/d2/de8/group__core__array.html#gaca7be533e3dac7feb70fc60635adf441

17. 截取部分矩阵

◆ Mat() [15/29]
cv::Mat::Mat    (   const Mat &     m,
        const Range &   rowRange,
        const Range &   colRange = Range::all() 
    )   
roiFrame = Mat(flipFrame, Range(roi_hs, roi_he), Range(roi_ws, roi_we));

参考: https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#a92a3e9e5911a2eb0cf0950a0a9670c76

18. 转换颜色

◆ cvtColor()
void cv::cvtColor   (   InputArray      src,
        OutputArray     dst,
        int     code,
        int     dstCn = 0 
    )   
cvtColor(roiFrame, hsvFrame, COLOR_BGR2HSV)

参考: https://docs.opencv.org/3.4/d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab

19. 通过上下限阈值从图像中提取作为前景,其他作为后景,完成图像的二值化。

inRange()
void cv::inRange    (   InputArray      src,
        InputArray      lowerb,
        InputArray      upperb,
        OutputArray     dst 
    )   
inRange(hsvFrame, Scalar(0, 20, 70), Scalar(20, 255, 255), maskFrame);

参考: https://docs.opencv.org/master/d2/de8/group__core__array.html#ga48af0ab51e36436c5d04340e036ce981 https://docs.opencv.org/master/d6/d7f/samples_2cpp_2camshiftdemo_8cpp-example.html#a33

20. 寻找轮廓 findContours 获得的轮廓类型是: std::vector<std::vector >, 获取轮廓面积的时候输入的轮廓参数是 std::vector

参考: https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#gadf1ad6a0b82947fa1fe3c3d497f260e0 https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#ga2c759ed9f497d4a618048a2f56dc97f1

21. 画轮廓线

◆ drawContours()
void cv::drawContours   (   InputOutputArray    image,
        InputArrayOfArrays      contours,
        int     contourIdx,
        const Scalar &      color,
        int     thickness = 1,
        int     lineType = LINE_8,
        InputArray      hierarchy = noArray(),
        int     maxLevel = INT_MAX,
        Point   offset = Point() 
    )   

参考: https://docs.opencv.org/master/d6/d6e/group__imgproc__draw.html#ga746c0625f1781f1ffc9056259103edbc

22. 计算曲线长度或者轮廓周长。

◆ arcLength()
double cv::arcLength    (   InputArray      curve,
        bool    closed 
    )   

参考: https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#ga8d26483c636be6b35c3ec6335798a47c

23. 计算轮廓近似多边形

◆ approxPolyDP()
void cv::approxPolyDP   (   InputArray      curve,
        OutputArray     approxCurve,
        double      epsilon,
        bool    closed 
    )   

参考: https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#ga0012a5fdaea70b8a9970165d98722b4c

24. 计算凸包

◆ convexHull()
void cv::convexHull     (   InputArray      points,
        OutputArray     hull,
        bool    clockwise = false,
        bool    returnPoints = true 
    )   

参考: https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#ga014b28e56cb8854c0de4a211cb2be656

25. 计算凸性缺陷

◆ convexityDefects()
void cv::convexityDefects   (   InputArray      contour,
        InputArray      convexhull,
        OutputArray     convexityDefects 
    )   

注意: contour 是 vector, convexhull 是 vector,convexityDefects 是 vector

如果有报错: OpenCV Error: Assertion failed (hpoints > 0) in convexityDefects, file /home/neha/opencv-3.4.0/modules/imgproc/src/convhull.cpp, line 284 terminate called after throwing an instance of 'cv::Exception' what(): /home/neha/opencv-3.4.0/modules/imgproc/src/convhull.cpp:284: error: (-215) hpoints > 0 in function convexityDefects 那么需要检查 convexhull 是不是 vector

参考: https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#gada4437098113fd8683c932e0567f47ba https://github.com/wonderseen/Sparse-Points-Gen-Convex/issues/1

26. Vec4i 是 4个 int 组成的 vector 向量,即 vector

参考: https://www.coder.work/article/826469

27. 画圆圈。

◆ circle()
void cv::circle     (   InputOutputArray    img,
        Point   center,
        int     radius,
        const Scalar &      color,
        int     thickness = 1,
        int     lineType = LINE_8,
        int     shift = 0 
    )   

参考: https://docs.opencv.org/master/d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670
https://blog.csdn.net/caomin1hao/article/details/81876836

28. 画线

◆ line()
void cv::line   (   InputOutputArray    img,
        Point   pt1,
        Point   pt2,
        const Scalar &      color,
        int     thickness = 1,
        int     lineType = LINE_8,
        int     shift = 0 
    )   

参考: https://docs.opencv.org/master/d6/d6e/group__imgproc__draw.html#ga7078a9fae8c7e7d13d24dac2520ae4a2

29. 高斯模糊

◆ GaussianBlur()
void cv::GaussianBlur   (   InputArray      src,
        OutputArray     dst,
        Size    ksize,
        double      sigmaX,
        double      sigmaY = 0,
        int     borderType = BORDER_DEFAULT 
    )

模糊参数的影响效果可以参考: https://www.cnblogs.com/sdu20112013/p/11600436.html

参考: https://docs.opencv.org/master/d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1

30. 手势识别,用到凸包和缺陷。

具体可参考: http://www.zfhblog.com/index.php/archives/22/ https://www.cnblogs.com/Anita9002/p/5332122.html https://docs.opencv.org/master/d7/d1d/tutorial_hull.html https://blog.csdn.net/lichengyu/article/details/38392473

31. resize

    cv::Mat dst(300, 300, image.type());
    cv::resize(image, dst, dst.size(), 0, 0, cv::INTER_LINEAR);

参考: https://blog.csdn.net/i_chaoren/article/details/54564663 https://blog.csdn.net/u012005313/article/details/51943442 https://www.jianshu.com/p/11879a49d1a0

32. 复制所有的图像数据

    cv::Mat image;
    image = cv::imread(imgPath);
    memcpy(data, image.data, image.dataend - image.datastart);

参考: https://www.jianshu.com/p/cfc0c1f87bf8

33. 清除图像数据

Mat mat3 = Mat::zeros(1, 4, CV_32F);
mat3.release();

参考: https://blog.csdn.net/wanggao_1990/article/details/53150926

1. cv2.GaussianBlur()

def GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None):
"""
使用高斯滤波器模糊图像
Argument:
    src: 原图像
    dst: 目标图像
    ksize: 高斯核的大小;(width, height);两者都是正奇数;如果设为0,则可以根据sigma得到;
    sigmaX: X方向的高斯核标准差;
    sigmaY: Y方向的高斯核标准差;
        如果sigmaY设为0,则与sigmaX相等;
        如果两者都为0,则可以根据ksize来计算得到;
    (推荐指定ksize,sigmaX,sigmaY)
    borderType: pixel extrapolation method
"""

参考: https://www.cnblogs.com/chenzhen0530/p/10742536.html https://blog.csdn.net/wuqindeyunque/article/details/103694900

2. cv2.imshow() 用来在窗口上显示图像。代码如下:

img = cv2.imread('3.jpg',1)
cv2.imshow('imshow',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
    cv2.namedWindow('image', cv2.WINDOW_NORMAL)
    cv2.imshow('image',img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

cv2.namedWindow()函数可以指定窗口是否可以调整大小。在默认情况下,标志为cv2.WINDOW_AUTOSIZE。但是,如果指定标志为cv2.WINDOW_Normal,则可以调整窗口的大小。当图像尺寸太大,并在窗口中添加跟踪条时,这些操作可以让我们的工作更方便一点。

cv2.waitKey(0): 是一个和键盘绑定的函数,它的作用是等待一个键盘的输入(因为我们创建的图片窗口如果没有这个函数的话会闪一下就消失了,所以如果需要让它持久输出,我们可以使用该函数)。它的参数是毫秒级。该函数等待任何键盘事件的指定毫秒。如果您在此期间按下任何键,程序将继续进行。我们也可以将其设置为一个特定的键。

cv2.destroyALLWindows(): 销毁我们创建的所有窗口。如果要销毁任何特定窗口,请使用函数cv2.destroyWindow(),其中传递确切的窗口名称作为参数。(应该是使用创建窗口时所使用的窗口名称,字符串类型。)

参考: https://blog.csdn.net/weixin_38383877/article/details/82659779

3. waitKey() 用于等待一段时间,接受用户按键。如果参数是 0, 那么循环就只执行一次,然后一直等待用户按键。如果参数不是 0,那么每次等待参数给定的 ms,如果没有按键,那么继续循环。

ord() 函数用来获得按键对应的 ASCII 码,用来和 waitKey() 返回值进行对比。

if cv2.waitKey(1) & 0xFF == ord("q"):

参考: https://blog.csdn.net/qq_39377418/article/details/101393007 https://www.runoob.com/python/python-func-ord.html

4. release() 用来释放视频,然后再调用 cv2.destroyAllWindows() 来关闭所有窗口。

参考: https://www.jianshu.com/p/949683764115

5. imutils.resize() 用来改变图像大小,但是不改变长宽比例。

参考: https://www.jianshu.com/p/bb34ddf2a947

6. cv2.cvtColor() 用来转换图像色彩。

def cvtColor(src, code, dst=None, dstCn=None):
"""
转换图像的颜色空间
Argument:
    src: 原图像;
    code: 指定颜色空间转换类型;
    dst: 目标图像;与原图像大小深度一致;
    dstCn: 指定目标图像通道数;默认None,则会根据src、code自动计算;
"""

参考: https://www.cnblogs.com/chenzhen0530/p/10741264.html

7. cv2.absdiff() 用来对图像求差,主要是对于灰度图。用来比较两幅图像的差别。

参考: https://blog.csdn.net/u014737138/article/details/80388482 https://zhuanlan.zhihu.com/p/42940310

8. cv2.threshold() 阈值函数。

def threshold(src, thresh, maxval, type, dst=None):
"""
设置固定级别的阈值应用于多通道矩阵
    例如,将灰度图像变换二值图像,或去除指定级别的噪声,或过滤掉过小或者过大的像素点;
Argument:
    src: 原图像
    dst: 目标图像
    thresh: 阈值
    type: 指定阈值类型;下面会列出具体类型;
    maxval: 当type指定为THRESH_BINARY或THRESH_BINARY_INV时,需要设置该值;
"""

参考: https://www.cnblogs.com/chenzhen0530/p/10742540.html https://www.cnblogs.com/yinliang-liang/p/9293310.html

9. cv2.dilate() 形态学膨胀。用于白色增大。

dst = cv2.dilate(src,kernel,anchor,iterations,borderType,borderValue)
        src: 输入图像对象矩阵,为二值化图像
        kernel:进行腐蚀操作的核,可以通过函数getStructuringElement()获得
        anchor:锚点,默认为(-1,-1)
        iterations:腐蚀操作的次数,默认为1
        borderType: 边界种类
        borderValue:边界值

参考: https://www.cnblogs.com/silence-cho/p/11069903.html https://zhuanlan.zhihu.com/p/110330329 https://www.aiuai.cn/aifarm350.html https://www.cnblogs.com/my-love-is-python/p/10394908.html

10. cv2.findContours() 查找轮廓,最好使用原图像的拷贝。

参考: https://www.cnblogs.com/wmy-ncut/p/9889294.html https://blog.csdn.net/gaoranfighting/article/details/34877549

11. imutils.grab_contours 返回轮廓,是配合 cv2.findContours() 使用的。cv2.findContours()在就版本返回两个值,在新版本返回3个值,通过imutils.grab_contours 把返回中的轮廓拿到。

参考: https://blog.csdn.net/nima1994/article/details/90542992

13. cv2.contourArea() 对轮廓线求面积。

参考: https://blog.csdn.net/greatwall_sdut/article/details/108862018

14. cv2.boundingRect() 对找到的形状用最小的矩形框起来。

参考: https://www.cnblogs.com/Anita9002/p/8033101.html

15. cv2.rectangle() 用于在图像上画出一个矩形。

参考: https://blog.csdn.net/Gaowang_1/article/details/103087922

16. cv2.putText() 用于在图像上增加文字

参考: https://blog.csdn.net/GAN_player/article/details/78155283

17. cv2.FONT_HERSHEY_SIMPLEX 字体效果可以参考:

https://blog.csdn.net/hgkdzbf6/article/details/102093323

18. 形态学详细使用,包括不同的核的效果。

参考: https://blog.csdn.net/sunny2038/article/details/9137759

19. cv2.flip 图像翻转。

flip(src, flipCode[, dst]) flipCode Anno 1 水平翻转 0 垂直翻转 -1 水平垂直翻转

参考: https://blog.csdn.net/JNingWei/article/details/78753607

20. 从矩阵中取出一部分。

 Mat() [15/29]
cv::Mat::Mat    (   const Mat &     m,
        const Range &   rowRange,
        const Range &   colRange = Range::all() 
    )   
roi = frame[0 : 300, 0: 300]

注意第一组参数是 height / row,第二组参数是 width / col. 注意这个范围是 左闭右开的。 参考:https://docs.opencv.org/master/d3/d63/classcv_1_1Mat.html#a92a3e9e5911a2eb0cf0950a0a9670c76

21. 保持长宽比转换图像后,获得转换后的尺寸。

            ret, frame = capture.read()
            width = 500
            frame = imutils.resize(frame, width)
            height = frame.shape[1]
            print("width %d, height %d\n" % (frame.shape[0], frame.shape[1]))

参考: https://vimsky.com/zh-tw/examples/detail/python-method-imutils.resize.html

22. 彩色图像转为 HSV 格式,主要用于图像前处理,然后会对某个颜色区间去做检测,主要用于去背景处理后的,物体检测。

色相(H):色彩的顏色名稱,如紅色、黃色等。 飽和度(S):色彩的純度,越高色彩越純,低則逐漸變灰,數值為0-100%。 明度(V):亮度,數值為0-100%。

hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

参考: https://shengyu7697.github.io/blog/2020/03/22/Python-OpenCV-rgb-to-hsv/ https://blog.csdn.net/u012193416/article/details/79312798 https://docs.opencv.org/3.4/da/d97/tutorial_threshold_inRange.html

23. 转换数组为 uint8 类型

skin = np.array([0, 20, 70], dtype = np.uint8)

参考: https://numpy.org/doc/stable/reference/generated/numpy.array.html

24. 检查数据是否在范围内,在范围内就设置为 255,不在范围内就设置为 0。也是一种对图像二值化的方法。

◆ inRange()
void cv::inRange    (   InputArray      src,
        InputArray      lowerb,
        InputArray      upperb,
        OutputArray     dst 
    )       
Python:
    dst =   cv.inRange( src, lowerb, upperb[, dst]  )

#include <opencv2/core.hpp>

Checks if array elements lie between the elements of two other arrays.

The function checks the range as follows:

    For every element of a single-channel input array:

    dst(I)=lowerb(I)0≤src(I)0≤upperb(I)0
    For two-channel arrays:

    dst(I)=lowerb(I)0≤src(I)0≤upperb(I)0∧lowerb(I)1≤src(I)1≤upperb(I)1
    and so forth.

That is, dst (I) is set to 255 (all 1 -bits) if src (I) is within the specified 1D, 2D, 3D, ... box and 0 otherwise.

When the lower and/or upper boundary parameters are scalars, the indexes (I) at lowerb and upperb in the above formulas should be omitted. 
mask = cv2.inRange(hsv, skin_low, skin_up)

25. 画轮廓线

            contours = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
            contours = imutils.grab_contours(contours)
            cv2.drawContours(frame, contours, -1, (0, 255, 0), 3)

参考: https://stackoverflow.com/questions/48948769/how-to-draw-contours-using-opencv-in-python

26. 计算轮廓周长或曲线长度

◆ arcLength()
double cv::arcLength    (   InputArray      curve,
        bool    closed 
    )       
Python:
    retval  =   cv.arcLength(   curve, closed   )

#include <opencv2/imgproc.hpp>

Calculates a contour perimeter or a curve length.

The function computes a curve length or a closed contour perimeter.

Parameters
    curve   Input vector of 2D points, stored in std::vector or Mat.
    closed  Flag indicating whether the curve is closed or not. 
cv2.arcLength(cnt,True)

参考: https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#ga8d26483c636be6b35c3ec6335798a47c https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html

27. 用更少顶点的曲线或多边形来逼近给定的曲线或多边形

◆ approxPolyDP()
void cv::approxPolyDP   (   InputArray      curve,
        OutputArray     approxCurve,
        double      epsilon,
        bool    closed 
    )       
Python:
    approxCurve =   cv.approxPolyDP(    curve, epsilon, closed[, approxCurve]   )

#include <opencv2/imgproc.hpp>

Approximates a polygonal curve(s) with the specified precision.

The function cv::approxPolyDP approximates a curve or a polygon with another curve/polygon with less vertices so that the distance between them is less or equal to the specified precision. It uses the Douglas-Peucker algorithm http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm

Parameters
    curve   Input vector of a 2D point stored in std::vector or Mat
    approxCurve Result of the approximation. The type should match the type of the input curve.
    epsilon Parameter specifying the approximation accuracy. This is the maximum distance between the original curve and its approximation.
    closed  If true, the approximated curve is closed (its first and last vertices are connected). Otherwise, it is not closed. 
            epsilon = 0.0005 * cv2.arcLength(cnt, True)
            approx = cv2.approxPolyDP(cnt, epsilon, True)

28. 寻找轮廓的凸包,可以用来手势识别

hull = cv2.convexHull(cnt)

参考: https://www.cnblogs.com/jclian91/p/9728488.html https://kk665403.pixnet.net/blog/post/403518029-%5Bpython%5D-%E5%88%A9%E7%94%A8opencv%E7%B9%AA%E8%A3%BD%E5%87%B8%E5%8C%85(convexhull)-%E8%BC%AA%E5%BB%93(contour

29. 显示凸包,因为凸包是一维的,需要增加一维,才能通过 drawContours 显示出来。

            hull = cv2.convexHull(cnt)
            hull_list = []
            hull_list.append(hull)
            cv2.drawContours(frame, hull_list, -1, (0, 0, 255), 3)

参考: https://stackoverflow.com/questions/36683556/drawing-convex-hull-of-the-biggest-contour-using-opencv-c https://docs.opencv.org/3.4/d7/d1d/tutorial_hull.html https://docs.opencv.org/master/d7/d1d/tutorial_hull.html

30. 生成一个二维数组。

kernel = np.ones((3, 3), np.uint8)

返回的是一个二维数组

[[1 1 1]
 [1 1 1]
 [1 1 1]]

参考: https://numpy.org/doc/stable/reference/generated/numpy.ones.html

31. shape 不仅仅指的是一个图像的高度,宽度,像素通道数,其实也是指的图像本身矩阵的行数,列数,表示每个像素的数组长度。

通道数,灰度时候为 1, RGB 为 3, RGBA 为 4,RGB555 和 RGB565 是 2。 其实这样看就是字节数,用几个字节来表示像素。 RGB一个像素点的打印如下:

[22 22 15]

RGB 一行打印如下:

[[22 22 15]
 [18 21 13]
 ...
 [127 126 127]]

RGB 图像打印如下:

[[[22 22 15]
  [18 21 13]
  ...
  [127 126 127]]
 ...
 [[10 15 16]
  [15 13 12]
  ...
  [5 5 5]]]

参考:https://blog.csdn.net/qq_28618765/article/details/78618724 https://blog.csdn.net/mvtechnology/article/details/9008499

32. 打印异常

import traceback
try:
    2/0
except Exception as e:
    traceback.print_exc()

参考: https://blog.csdn.net/feiyang5260/article/details/86661103

33. 用 lambda 来获取轮廓当中面积最大的那个:

cnt = max(contours, key = lambda x: cv2.contourArea(x))

参考: https://www.cnblogs.com/bjwu/articles/9028399.html

34. 凸性缺陷 函数是 convexityDefects

convexityDefects()
void cv::convexityDefects   (   InputArray      contour,
        InputArray      convexhull,
        OutputArray     convexityDefects 
    )       
Python:
    convexityDefects    =   cv.convexityDefects(    contour, convexhull[, convexityDefects] )
    epsilon = 0.0005 * cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, epsilon, True)
    hull = cv2.convexHull(approx, returnPoints = False)
    defects = cv2.convexityDefects(approx, hull)

如上: 首先对图像简化成简易多边形,然后是生成凸包,最后生成凸性缺陷。 打印 hull如下:

[[165]
 [163]
 [128]
 [124]
 ...
 [209]
 [208]
 [168]
 [166]]

打印 defects 如下:

[[[166 168 167 114]]
 [[168 208 189 10549]]
 [[209 243 229 11994]]
 ...
 [[122 124 123 114]]
 [[124 128 125 181]]
 [[128 163 152 1784]]
 [[163 165 164 186]]]

defects 四个数是起始点,结束点,最远点,最远点到 hull 的距离。这些数值都是索引,用来索引的。 approx 打印如下:

[[[193 92]]
 [[192 92]]
 ...
 [[192 109]]
 [[193 109]]]
    for i in range(defects.shape[0]):
        s, e, f, d = defects[i, 0]
        start = tuple(approx[s][0])
        end = tuple(approx[e][0])
        far = tuple(approx[f][0])
        pt = (100, 180)

如上,当 i = 0 的时候, sefd 从 defects 里面取出 第一行,第一列的数组,[166 168 167 114], 即 s = 166, e = 168, f = 167, d = 114。然后 start = tuple(approx[s][0]),即 从 approx 里面取出 166行 0 列的数组,然后转为元组。 这个数组只有两个数值,估计就是像素点的 x, y 值。

参考: https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#gada4437098113fd8683c932e0567f47ba https://docs.opencv.org/master/d7/d1d/tutorial_hull.html https://zhuanlan.zhihu.com/p/56360621 https://vimsky.com/zh-tw/examples/detail/python-method-cv2.convexityDefects.html https://zhuanlan.zhihu.com/p/140384182

35. 手势识别,需要用到凸包和缺陷。

可以参考: https://blog.csdn.net/qq_41562704/article/details/88975569 https://zhuanlan.zhihu.com/p/140384182 https://www.pythonf.cn/read/29390 https://blog.csdn.net/weixin_44885615/article/details/97811684

36. putText 中文,使用 pil

import cv2
import numpy
from PIL import Image, ImageDraw, ImageFont

class EspVisionUtil:
    @staticmethod
    def cv2ImgAddText(img, txt, left, top, color = (0, 255, 0), size = 20):
        # 判断是 opencv 的图片,就转换RGB因为 PIL 和 CV 的颜色格式不同
        if (isinstance(img, numpy.ndarray)):
            img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        # 创建绘图对象
        draw = ImageDraw.Draw(img)
        # 字体格式
        fontStyle = ImageFont.truetype("SourceHanSansCN-Light.otf", size,
                                       encoding = "utf-8")
        # 绘制文本
        draw.text((left, top), txt, color, font = fontStyle)
        # 转换 opencv 格式
        return cv2.cvtColor(numpy.asarray(img), cv2.COLOR_RGB2BGR)

参考: https://blog.csdn.net/ctwy291314/article/details/91492048 https://www.cnblogs.com/vipstone/p/8998249.html https://blog.csdn.net/javastart/article/details/88796482 https://blog.csdn.net/zizi7/article/details/70145150 https://www.cnblogs.com/arkenstone/p/6961453.html https://www.cnblogs.com/YouXiangLiThon/p/7815124.html https://blog.csdn.net/qq_41895190/article/details/90513453 https://zhuanlan.zhihu.com/p/161385206