栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

备份笔记

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

备份笔记

之前的OpenCV笔记
图像的获取
  • .VideoCapture() 获取视频流 cap

    • .isOpened() 返回是否打开

    • .read() 读取一张照片,一帧一帧读,而不是抽帧读

    • .get(propId) 获取视频特征, .set(propId, value) 修改值

      import numpy as np
      import cv2 as cv
      cap = cv.VideoCapture(0)
      while(True):
          # 一帧一帧捕捉
          ret, frame = cap.read()
          # 我们对帧的操作在这里
          gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
          # 显示返回的每帧
          cv.imshow('frame',gray)
          if cv.waitKey(1) & 0xFF == ord('q'):
              break
      # 当所有事完成,释放 VideoCapture 对象
      cap.release()
      cv.destroyAllWindows()
      
  • .imread() 读取图片

画画
  • .line()
  • .circle()
  • .rectangle()
  • .ellipse() 画椭圆
  • .putText() 写中文的话要改调用 PIL包
  • 上面的这些函数,你能看到一些相同的参数:
    • img:你想画的图片
    • color:形状的颜色,如 BGR,它是一个元组,例如:蓝色(255,0,0)。对于灰度图,只需传一个标量值。
    • thickness: 线或圆等的厚度。如果传 -1 就是像圆的闭合图形,它将填充形状。_ 默认 thickness = 1_
    • lineType:线条类型,如 8 连接,抗锯齿线等。默认情况下,它是 8 连接。cv.LINE_AA 画出抗锯齿线,非常好看的曲线。
鼠标事件
  • import numpy as np
    import cv2 as cv
    # 鼠标回调函数
    def draw_circle(event,x,y,flags,param):
        if event == cv.EVENT_LBUTTONDBLCLK:
            cv.circle(img,(x,y),100,(255,0,0),-1)
    # 创建一个黑色图像,一个窗口,然后和回调绑定
    img = np.zeros((512,512,3), np.uint8)
    cv.namedWindow('image')
    cv.setMouseCallback('image',draw_circle)
    while(1):
        cv.imshow('image',img)
        if cv.waitKey(20) & 0xFF == 27:
            break
    cv.destroyAllWindows()
    
  • 其中 cv2.EVENT_LBUTTONDOWN 等属性可以判断一直按下等操作

图像操作
  • Numpy 是一个用于快速阵列计算的优化库。因此,简单地访问每个像素值并对其进行修改将非常缓慢,并不鼓励这样做。

  • img.dtype 获取图像数据类型

  • 合并与拆分

    • >>>b,g,r = cv.spilt(img) #拆分,速度慢
      >>>img = cv.merge((b,g,r))#合并,一般BGR
      
  • 制作边界

    • .copyMakeBorder()

      • src-输入的图像

      • top,bottom,left,right-上下左右四个方向上的边界拓宽的值

      • borderType-定义要添加的边框类型的标志。它可以是以下类型:

        • cv.BORDER_CONSTANT- 添加一个恒定的彩色边框。该值应作为下一个参数value给出。
        • cv.BORDER_REFLECT-边框将是边框元素的镜像反射,如下所示:fedcba|abcdefgh|hgfedcb
        • cv.BORDER_REFLECT_101或者 cv.BORDER_DEFAULT-与上面相同,但略有改动,如下所示: gfedcb | abcdefgh | gfedcba
        • cv.BORDER_REPLICATE -最后一个元素被复制,如下所示: aaaaaa | abcdefgh | hhhhhhh
        • cv.BORDER_WRAP-不好解释,它看起来像这样: cdefgh | abcdefgh | abcdefg
      • value- 如果边框类型为cv.BORDER_CONSTANT,则这个值即为要设置的边框颜色

  • 图像加法

    • 找不同:

      >>> x = np.uint8([250])
      >>> y = np.uint8([10])
      
      >>> print(cv.add(x,y)) #250 + 10 =260 => 255
      [[255]]
      
      >>> print(x + y)
      [4]
      
    • addWeighted(img1,0.7,img2,0.3,0) 权重相加

测量性能
  • img1 = cv.imread('messi5.jpg')
    e1 = cv.getTickCount()#返回执行程序此时时钟数
    for i in xrange(5,49,2):
        img1 = cv.medianBlur(img1,i)
    e2 = cv.getTickCount()#返回执行程序此时时钟数
    t = (e2 - e1)/cv.getTickFrequency()#除每秒时钟数
    print( t )
    # 得到的结果是 0.521107655 秒
    
  • OpenCV自带默认优化,可以使用 cv.useOptimized() 来检查它是否已启用/禁用,并使用 cv.setUseOptimized() 来启用/禁用它

图像处理
  • .cvtColor(input_image, flag) 更改颜色空间

    • flag 为 .COLOR_ 开头
  • 一般更改完颜色空间后使用 .inRange() 返回指定范围内颜色

  • 图像大小变换
    • .getAffineTransform() 仿射变换(Affine Transformation)是指在向量空间中进行一次线性变换(乘以一个矩阵)和一次平移(加上一个向量),变换到另一个向量空间的过程。变换矩阵存为 np.float32 类型的 numpy 数组

    • .warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst 执行仿射变换

      • src - 输入图像。
        M - 变换矩阵。
        dsize - 输出图像的大小。
        flags - 插值方法的组合(int 类型!)
        borderMode - 边界像素模式(int 类型!)
        borderValue - (重点!)边界填充值; 默认情况下,它为0
    • .GetPerspectiveTransform(src, dst) 透视变换(Perspective Transformation)是将成像投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。

      • src:源图像中待测矩形的四点坐标
      • sdt:目标图像中矩形的四点坐标
    • cv2.warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst#获取变换矩阵
      

      参数为:

      • src:输入图像
      • M:变换矩阵
      • dsize:目标图像shape
      • flags:插值方式,interpolation方法INTER_LINEAR或INTER_NEAREST
      • borderMode:边界补偿方式,BORDER_ConSTANT or BORDER_REPLICATE
      • borderValue:边界补偿大小,常值,默认为0
  • 图像阈值

    • retVal, thresh = cv2.threshold(需要处理的图像,阈值,分配的值,阈值处理模式选择)

      • 参数1,需要处理的图像:注意,需要处理的图像需要被转成灰度图像(后面小试一下部分会讲解)

        参数2,阈值:设定阈值,分界值

        参数3,分配的值:如果一个像素的灰度值,大于或者小于(取决于参数4的选择)阈值,会被赋予分配的值

        参数4,

        • cv2.THRESH_BINARY
        • cv2.THRESH_BINARY_INV
        • cv2.THRESH_TRUNC
        • cv2.THRESH_TOZERO
        • cv2.THRESH_TOZERO_INV
      • def adaptiveThreshold(src,maxValue,adaptiveMethod,thresholdType,blockSize,C,dst=None)

        • maxval:Double类型的,阈值的最大值
          adaptiveMethod:Int类型的,这里有两种选择
          1 —— ADAPTIVE_THRESH_MEAN_C(通过平均的方法取得平均值)
          2 —— ADAPTIVE_THRESH_GAUSSIAN_C(通过高斯取得高斯值)
          不过这两种方法最后得到的结果要减掉参数里面的C值

        • thresholdType:Int类型的,方法如下:
          THRESH_BINARY 二进制阈值化 -> 大于阈值为1 小于阈值为0
          THRESH_BINARY_INV 反二进制阈值化 -> 大于阈值为0 小于阈值为1
          THRESH_TRUNC 截断阈值化 -> 大于阈值为阈值,小于阈值不变
          THRESH_TOZERO 阈值化为0 -> 大于阈值的不变,小于阈值的全为0
          THRESH_TOZERO_INV 反阈值化为0 -> 大于阈值为0,小于阈值不变
          blockSize:Int类型的,这个值来决定像素的邻域块有多大。
          注意:这里的blockSize的值要为奇数,否则会给出这样的提示:
          Assertion failed (blockSize % 2 == 1 && blockSize > 1) in cv::adaptiveThreshold
          C:偏移值调整量,计算adaptiveMethod用到的参数。

        实验中,我阈值的type选择第一种,来演示这两种方式得出的结果
        当blockSize的值比较小的时候,两种方法得到的结果的差异不是很大

        当blockSize的值比较大的时候,就会发现,平均的这种会将整体的轮廓加深的程度大于高斯
        直接看图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K6gQJd6p-1633572209561)(https://opencv.apachecn.org/docs/4.0.0/img/Image_Thresholding_2.png)]

        我图片上虽然显示的blockSize为10,不过我在程序里面做了判断,当为偶数的情况,就让它+1变成奇数。

    • Otus二值化

      • import cv2 as cv
        import numpy as np
        from matplotlib import pyplot as plt
        img = cv.imread('noisy2.png',0)
        # 全局阈值
        ret1,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
        # Otsu 阈值
        ret2,th2 = cv.threshold(img,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
        # 经过高斯滤波的 Otsu 阈值
        blur = cv.GaussianBlur(img,(5,5),0)
        ret3,th3 = cv.threshold(blur,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
        # 画出所有的图像和他们的直方图
        images = [img, 0, th1,
                  img, 0, th2,
                  blur, 0, th3]
        titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
                  'Original Noisy Image','Histogram',"Otsu's Thresholding",
                  'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]
        for i in xrange(3):
            plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
            plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
            plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
            plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
            plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
            plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
        plt.show()
        
  • 图像模糊

    • 均值
      • .blur() 默认3*3均值滤波
      • .boxFliter() 不使用3*3的滤波
    • 高斯
      • .GaussianBlur(img,(5,5),0) 正态分布的卷积核,消除高斯噪声
    • 中值滤波
      • .medianBlur(img,5) 像素点所在5*5范围内中间值替换该像素,可有效降低噪声
    • 双边滤波
      • .bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])
        • src:输入图像
        • d:过滤时周围每个像素领域的直径
        • sigmaColor:在color space中过滤sigma。参数越大,临近像素将会在越远的地方mix。
        • sigmaSpace:在coordinate space中过滤sigma。参数越大,那些颜色足够相近的的颜色的影响越大。
      • 保留边缘的消噪,绝绝子,但是速度慢
  • 形态转换了佳人们

    • .erode(img,kernel,iterations = 1) 腐蚀操作
      • 内核在图像内移动,只有内核所在位置均为1时才会为1,否则均为0
      • 有助于消除小的白色噪音(如我们在“颜色空间”一章中所看到的),分离两个连接的对象等
    • .dilate(img,kernel,iterations = 1) 膨胀操作
      • 如果内核下至少有一个像素为“1”,则像素元素为“1”,它还可用于连接对象的断开部分,往往先腐蚀后膨胀
    • .morphologyEx(img, cv.MORPH_OPEN, kernel) 先腐蚀后膨胀
    • .morphologyEx(img, cv.MORPH_CLOSE, kernel) 先膨胀后腐蚀
    • .morphologyEx(img, cv.MORPH_GRADIENT, kernel) 膨胀和腐蚀间的差值
    • .morphologyEx(img, cv.MORPH_TOPHAT, kernel) 原图像和开运算结果的差值
    • .morphologyEx(img, cv.MORPH_BLACKHAT, kernel) 原图像和闭运算结果差值
    • 使用 .getStructuringElement(cv2.MORPH_CROSS,(5,5)) 获取各个形状的原图的 kernel ,
      • 矩形:MORPH_RECT;
      • 交叉形:MORPH_CROSS;
      • 椭圆形:MORPH_ELLIPSE;
  • 隔着整梯度算法是吧

    • Sobel

      • dst = cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])

        • 第一个参数是需要处理的图像;
        • 第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度,一般为.CV_**
        • dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2
      • 原理:图像中的边缘区域,像素值会发生“跳跃”,对这些像素求导,在其一阶导数在边缘位置为极值,这就是Sobel算子使用的原理——极值处就是边缘。

      • 输出数据类型是 cv.CV_8U或 np.uint8。但这有一个小问题。黑白过渡为正斜率(有正值),而白黑过渡为负斜率(有负值)。所以当你把数据转换成 np.uint8 时,所有的负斜率都变成零。简单来说,你失去了边缘。

        如果要检测两条边,更好的选择是将输出数据类型保留为更高的格式,如 cv.CV_16S、cv.CV_64F 等,取其绝对值,然后转换回 cv.CV_8U。下面的代码演示了水平 Sobel滤波器的过程以及结果差异。

    • Scharr

      • .Scharr(src, ddepth, dx, dy)

        • 参数同上
      • Sobel 算子虽然可以有效的提取图像边缘,但是对图像中较弱的边缘提取效果较差。

        这是由于 Sobel 算子在计算相对较小的核的时候,其近似计算导数的精度比较低,例如一个 3 * 3 的 Sobel 算子,在梯度角度接近水平或垂直方向时,其不精确性就非常明显。

        因此引入 Scharr 算子。 Scharr 算子是对 Sobel 算子差异性的增强,两者之间的在检测图像边缘的原理和使用方式上相同。

    • Laplacian

      • dst = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
        • ksize是算子的大小,必须为1、3、5、7。默认为1。
          scale是缩放导数的比例常数,默认情况下没有伸缩系数;
          delta是一个可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中;
          borderType是判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT。
      • 原理:如果对像素值求二阶导数,会发现边缘处的导数值为0,Laplace函数实现的方法是先用Sobel 算子计算二阶x和y导数,再求和
    • Canny

      • 非常的好用 .Canny() 第一个参数为原图像,第二个和第三个参数分别是我们的 minVal 和 maxVal。第四个参数是 aperture_size。它是用于查找图像渐变的 Sobel 内核的大小。默认情况下,它是 3.最后一个参数是 L2gradient,它指定用于查找梯度幅度的等式。

      • 步骤

        • 1.高斯平滑去噪

        • 2.计算梯度强度及方向(非极大抑制)

          • 在每一点上,首先将梯度近似为四个方向,然后将领域中心 x 与沿着其对应的梯度方向的两个像素相比,若中心像素为最大值,则保留,否则中心置0,这样可以抑制非极大值,保留局部梯度最大的点,以得到细化的边缘。
        • 3.经过非极大抑制后图像中仍然有很多噪声点。Canny算法中应用了一种叫双阈值的技术。即设定一个阈值上界和阈值下界(opencv中通常由人为指定的),图像中的像素点如果大于阈值上界则认为必然是边界(称为强边界,strong edge),小于阈值下界则认为必然不是边界,两者之间的则认为是候选项(称为弱边界,weak edge),需进行进一步处理。

        • 4.和强边界相连的弱边界认为是边界,其他的弱边界则被抑制。

    • 轮廓

      • 为了找轮廓一般用二值图像,因此需要先阈值或者Canny
      • contours, hierarchy = cv.findContours( image, mode, method[, contours[, hierarchy[, offset]]] )
        • 参数1:源图像
        • 参数2:轮廓的检索方式一般用 .RETR_TREE ,详细见此处)
        • 参数3:一般用 cv.CHAIN_APPROX_SIMPLE,就表示用尽可能少的像素点表示轮廓
        • contours:图像轮廓坐标,是一个链表
        • hierarchy:[Next, Previous, First Child, Parent],文中有详细解释
    • 轮廓操作

      • 绘制轮廓 .drawContours(img, contours, -1, (0,255,0), 3)

      • 图像的矩

        • 图像矩可用来计算某些特征,例如物体的重心,物体的面积等,可以用 .moments(cnt) 得到所有矩

        • 可以用图像的矩计算出重心:
          Cannot read property 'type' of undefined

    • 轮廓面积 .contourArea()

    • 轮廓周长 .arcLength()

    • 轮廓近似

      • 获取轮廓外围

      • 设置精度(从轮廓到近似轮廓的最大距离)

      • 获取近似轮廓

      • 绘制轮廓

        #参照值:决定是否将一段曲线近为直线
        epsilon=0.1*cv2.arcLength(cnt,True)
        #近似轮廓
        approx=cv2.approxPolyDP(cnt,epsilon,True)
        #将近似出来的轮廓画在复制出来的图片上
        res=cv2.drawContours(draw_img,[approx],-1,(0,0,255),1)
        
    • 凸包

      • hull = cv.convexHull(points[, hull[, clockwise[, returnPoints]]])

        • points: 就是我们传入的轮廓。
        • hull: 是输出,通常我们避免它。
        • clockwise:方向标记。如果为True,则输出凸包为顺时针方向。否则,其方向为逆时针方向。
        • returnPoints:默认情况下为True。然后返回船体点的坐标。如果为False,则返回与船体点相对应的轮廓点的索引。
      • 凸包的定义

        • 换句话,对于空间中的对象.如果对象中的任意两个点构成的线段,也包含在对象内,则称对象是凸的。
      • 凸包外观看起来与轮廓逼近相似,但并非如此(在某些情况下两者可能提供相同的结果)

      • .isContourConvex(cnt) 返回曲线是否是凸多边形

    • 矩形

      • 直角矩形

        x,y,w,h = cv.boundingRect(cnt)
        cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
        
      • 旋转矩形

        rect = cv.minAreaRect(cnt)#返回一个Box2D结构,其中包含以下细节-(中心(x,y),(宽度,高度),旋转角度)
        box = cv.boxPoints(rect)#返回矩形的4个角
        box = np.int0(box)
        cv.drawContours(img,[box],0,(0,0,255),2)
        
      • (x,y),radius = cv.minEnclosingCircle(cnt)
        center = (int(x),int(y))
        radius = int(radius)
        cv.circle(img,center,radius,(0,255,0),2)
        
    • 拟合线

      • rows,cols = img.shape[:2]
        [vx,vy,x,y] = cv.fitLine(cnt, cv.DIST_L2,0,0.01,0.01)
        lefty = int((-x*vy/vx) + y)
        righty = int(((cols-x)*vy/vx)+y)
        cv.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)
        
    • 轮廓属性

      • 长宽比:对象边界矩形的宽度与高度的比率

        x,y,w,h = cv.boundingRect(cnt)
        aspect_ratio = float(w)/h
        
      • 范围:轮廓区域与边界矩形区域的比率

        area = cv.contourArea(cnt)
        x,y,w,h = cv.boundingRect(cnt)
        rect_area = w*h
        extent = float(area)/rect_area
        
      • 固实性:轮廓面积与其凸包面积的比率

        area = cv.contourArea(cnt)
        hull = cv.convexHull(cnt)
        hull_area = cv.contourArea(hull)
        solidity = float(area)/hull_area
        
      • 等效直径是面积与轮廓面积相同的圆的直径

        area = cv.contourArea(cnt)
        equi_diameter = np.sqrt(4*area/np.pi)
        
      • 方向是物体指向的角度。以下方法还给出了主轴和副轴的长度

        (x,y),(MA,ma),angle = cv.fitEllipse(cnt)
        
      • 在某些情况下,我们可能需要构成该对象的所有点。可以按照以下步骤完成:

        • mask = np.zeros(imgray.shape,np.uint8)
          cv.drawContours(mask,[cnt],0,255,-1)
          pixelpoints = np.transpose(np.nonzero(mask))
          # pixelpoints = cv.findNonZero(mask)
          
        • 给出了两种方法,一种使用Numpy函数,另一种使用OpenCV函数(最后注释的行)执行相同的操作。结果也相同,但略有不同。Numpy以(行,列)格式给出坐标,而OpenCV以(x,y)格式给出坐标。因此,基本上答案是可以互换的。注意,row = x,column = y

      • 最大值、最小值及其位置

        min_val, max_val, min_loc, max_loc = cv.minMaxLoc(imgray,mask = mask)
        
      • 平均颜色

        • mean_val = cv.mean(im,mask = mask)
      • 极点是指对象的最顶部,最底部,最右侧和最左侧的点

        • leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])
          rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])
          topmost = tuple(cnt[cnt[:,:,1].argmin()][0])
          bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])
          
      • 凸包缺陷

        • 凸包缺陷就是凸包与轮廓间的部分

          img = cv2.imread("图片名")
          gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
          ret,binary= cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
          contours,h= cv2.findContours(binary,cv2.RETR_LIST,
                                       cv2.CHAIN_APPROX_SIMPLE)
          #获取凸包
          hull= cv2.convexHull(contours[0],returnPoints= False)#一定要写returnPoints= False
          df= cv2.convexityDefects(contours[0],hull)
          
      • 点多边形测试(点与轮廓位置)

        • 查找图像中的点与轮廓之间的最短距离。它返回的距离为:当点在轮廓外时为负;当点在轮廓内时为正;如果点在轮廓上,则返回零。

          dist = cv.pointPolygonTest(cnt,(50,50),True)
          
      • 匹配形状(轮廓)

        • .matchShapes() **结果越低,匹配越好。**可以匹配旋转后的轮廓
        • 涉及到图像的矩,看不太懂
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/300050.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号