zoukankan      html  css  js  c++  java
  • 十九 对象测量

    找到轮廓之后,怎么测量弧长面积多边形拟合,中心距等等

    原点矩就是几何图形的重心;
    中心矩反映几何图形上点的分布规律,相当于将坐标原点移到重心上,此时的原点矩。

     

     二、相关函数

    1、几何计算

    (1)cv.contourArea(contour)  获取每个轮廓面积

    (2)cv.boundingRect(contour)  获取轮廓的外接矩形

    矩形边框(Bounding Rectangle)是说,用一个最小的矩形,把找到的形状包起来。还有一个带旋转的矩形,面积会更小,效果见下图

    contour轮廓点的位置信息,是一个二值图;

    返回四个值,分别是x,y,w,h;

    x,y是矩阵左上点的坐标,w,h是矩阵的宽和高

    然后利用cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)画出矩形

    参数解释

    第一个参数:img是原图

    第二个参数:(x,y)是矩阵的左上点坐标

    第三个参数:(x+w,y+h)是矩阵的右下点坐标

    第四个参数:(0,255,0)是画线对应的rgb颜色

    第五个参数:2是所画的线的宽度

    (3)cv.moments(contour)  求取轮廓的图像矩

    (4)cv.arcLength(contour,True)  求取轮廓的周长,指定闭合

    2、approPolyDP轮廓逼近方法

    def approxPolyDP(curve, epsilon, closed, approxCurve=None): # real signature unknown; restored from __doc__

    第一个参数curve:输入的点集,直接使用轮廓点集contour

    第二个参数epsilon:指定的精度,也即是原始曲线与近似曲线之间的最大距离

    第三个参数closed:若为true,则说明近似曲线是闭合的,反之,若为false,则断开

    第四个参数approxCurve:输出的点集,当前点集是能最小包容指定点集的。画出来即是一个多边形

    • 输出的点集,当前点集是能最小包容指定点集的。画出来即是一个多边形

    • approxCurve = cv.approxPolyDP(contour,4,True)   #4是与阈值的间隔大小,越小越易找出,True是是否找闭合图像
      print(approxCurve)  #打印每个轮廓的特征点
      print(approxCurve.shape)  #打印该点集的shape,第一个数是代表了点的个数,也就是边长连接逼近数
      [[[138 208]]
      
       [[138 234]]
      
       [[265 234]]
      
       [[264 207]]]
      (4, 1, 2)  #矩形,四个点逼近图像
      [[[124 154]]
      
       [[124 183]]
      
       [[325 183]]
      
       [[325 154]]]
      (4, 1, 2)
      [[[ 61 125]]
      
       [[  9 279]]
      
       [[114 280]]]
      (3, 1, 2)  #3是三角形
      [[[123 102]]
      
       [[111 118]]
      
       [[117 128]]
      
       [[129 131]]
      
       [[139 124]]
      
       [[141 114]]
      
       [[134 104]]]
      (7, 1, 2)  #7,8,9都是圆形类
      [[[303  78]]
      
       [[291  87]]
      
       [[289  99]]
      
       [[298 111]]
      
       [[310 113]]
      
       [[322 105]]
      
       [[324  91]]
      
       [[314  79]]]
      (8, 1, 2)
      [[[308  28]]
      
       [[298  35]]
      
       [[295  48]]
      
       [[303  59]]
      
       [[314  61]]
      
       [[325  54]]
      
       [[327  39]]]
      (7, 1, 2)
      [[[198  21]]
      
       [[165  38]]
      
       [[153  75]]
      
       [[170 107]]
      
       [[185 116]]
      
       [[210 119]]
      
       [[244 100]]
      
       [[254  63]]
      
       [[235  31]]]
      (9, 1, 2)
      [[[ 27  21]]
      
       [[ 27  87]]
      
       [[101  87]]
      
       [[101  21]]]
      (4, 1, 2)
      [[[418  15]]
      
       [[416 190]]
      
       [[454 192]]
      
       [[455  16]]]
      (4, 1, 2)
      [[[359  14]]
      
       [[346  58]]
      
       [[345 138]]
      
       [[356 190]]
      
       [[363 192]]
      
       [[374 156]]
      
       [[376  82]]
      
       [[369  24]]]
      (8, 1, 2)

    三、获取图像外接矩形boundingRect和几何矩moments

     1 import cv2 as cv
     2 import numpy as np
     3 
     4 def meaure(image):
     5     gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
     6     #全局自适应阈值 参数0可改为任意数字但不起作用,gray是灰度图,像素值最大是255,所以写255
     7     ret , binary = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)
     8     print('threshold value',ret)
     9     cv.imshow('binary image',binary)
    10     outimage,contours,hirachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
    11     for i , contour in enumerate(contours):
    12         area = cv.contourArea(contour)  #获取每个轮廓的面积
    13         x,y,w,h = cv.boundingRect(contour)
    14         rate = min(w,h)/max(w,h)    #获得外接矩形的宽高比,可以起到一定的筛选作用
    15         print('rectangle rate: %s'%rate)
    16         mm = cv.moments(contour)    #求取轮廓的几何矩
    17         print(type(mm))
    18         print(mm)
    19         cx = mm['m10']/mm['m00']    #重心坐标
    20         cy = mm['m01']/mm['m00']    #重心坐标
    21         cv.circle(image,(np.int(cx),np.int(cy)),2,(0,255,255),-1)   #半径是2,-1表示填充,画个圆点
    22         cv.rectangle(image,(x,y),(x+w,y+h),(0,0,255),2)
    23         print('contour area',area)
    24     cv.imshow('measured_image',image)
    25 img = cv.imread('contours.png')
    26 cv.imshow('input_image',img)
    27 meaure(img)
    28 cv.waitKey(0)
    29 cv.destroyAllWindows()
     1 threshold value 55.0
     2 rectangle rate: 0.7071290944123314
     3 <class 'dict'>
     4 {'nu21': 0.0, 'm00': 189588.0, 'mu02': 2116370844.0, 'm21': 3174612636832.0, 'm10': 49672056.0, 'mu12': 0.0, 'm20': 17253329548.0, 'm11': 9139658304.0, 'mu11': 0.0, 'nu03': 0.0, 'nu20': 0.11794171220400729, 'mu20': 4239250876.0, 'nu30': 0.0, 'nu11': 0.0, 'mu03': 0.0, 'nu12': 0.0, 'mu21': 0.0, 'm01': 34884192.0, 'm30': 6741739800600.0, 'm03': 2349275910240.0, 'mu30': 0.0, 'm02': 8535062172.0, 'nu02': 0.05888030888030888, 'm12': 2236186289064.0}
     5 contour area 189588.0
     6 rectangle rate: 0.2328767123287671
     7 <class 'dict'>
     8 {'nu21': 0.00012337159954486592, 'm00': 4638.5, 'mu02': 395646.24861073494, 'm21': 63361445232.433334, 'm10': 1068926.6666666665, 'mu12': -41552.704846039414, 'm20': 254451863.5833333, 'm11': 266174910.2083333, 'mu11': -657.9870841801167, 'nu03': -5.5731840906128935e-08, 'nu20': 0.3774605687931838, 'mu20': 8121321.660058409, 'nu30': 4.147758615136351e-05, 'nu11': -3.058174388962807e-05, 'mu03': -81.66712951660156, 'nu12': -2.835668094870454e-05, 'mu21': 180783.62808203697, 'm01': 1155042.1666666665, 'm30': 62380696103.3, 'm03': 71916234563.05, 'mu30': 60779.53545379639, 'm02': 288015007.4166666, 'nu02': 0.01838873822421945, 'm12': 66371716951.6}
     9 contour area 4638.5
    10 rectangle rate: 0.15555555555555556
    11 <class 'dict'>
    12 {'nu21': 3.8371793569830693e-05, 'm00': 2678.5, 'mu02': 89193.07461163402, 'm21': 36282586368.316666, 'm10': 616088.3333333333, 'mu12': 2005.2493966259062, 'm20': 145711489.91666666, 'm11': 153407428.875, 'mu11': 322.1481836140156, 'nu03': -8.185951318082867e-08, 'nu20': 0.5580295542656055, 'mu20': 4003506.1685074866, 'nu30': -3.5402871905680954e-06, 'nu11': 4.490269272561691e-05, 'mu03': -30.394729614257812, 'nu12': 5.40056587103005e-06, 'mu21': 14247.584001541138, 'm01': 666951.3333333333, 'm30': 35357167196.200005, 'm03': 41418876646.700005, 'mu30': -1314.5212783813477, 'm02': 166161278.5833333, 'nu02': 0.012432195574127027, 'm12': 38219324350.316666}
    13 contour area 2678.5
    14 rectangle rate: 0.1572052401746725
    15 <class 'dict'>
    16 {'nu21': -5.0325287139101995e-16, 'm00': 7978.0, 'mu02': 814035.5000000596, 'm21': 106182743120.5, 'm10': 2042368.0, 'mu12': -1.5228986740112305e-05, 'm20': 557389727.6666666, 'm11': 389071104.0, 'mu11': 5.960464477539063e-08, 'nu03': -2.68401531408544e-15, 'nu20': 0.5427233689755546, 'mu20': 34543519.66666669, 'nu30': 5.36803062817088e-15, 'nu11': 9.364660558983717e-16, 'mu03': -1.52587890625e-05, 'nu12': -2.6787730966751167e-15, 'mu21': -2.86102294921875e-06, 'm01': 1519809.0, 'm30': 160378052352.0, 'm03': 55619469850.5, 'mu30': 3.0517578125e-05, 'm02': 290337650.0, 'nu02': 0.012789550494243657, 'm12': 74326438400.0}
    17 contour area 7978.0
    18 rectangle rate: 0.6910112359550562
    19 <class 'dict'>
    20 {'nu21': 0.012773324262564329, 'm00': 11273.5, 'mu02': 20750773.8061198, 'm21': 17397875250.05, 'm10': 823135.1666666666, 'mu12': -351678.8153767586, 'm20': 67251828.58333333, 'm11': 210835642.2083333, 'mu11': -3017.880377650261, 'nu03': -0.03671091137116082, 'nu20': 0.05626305607377813, 'mu20': 7150573.196509272, 'nu30': -8.927214266694102e-06, 'nu11': -2.3745673003470692e-05, 'mu03': -495384129.6209717, 'nu12': -2.606149258816397e-05, 'mu21': 172365705.06794214, 'm01': 2887605.5, 'm30': 5954474083.55, 'm03': 204900612520.65002, 'mu30': -120465.55381679535, 'm02': 760384917.9166666, 'nu02': 0.1632738968112304, 'm12': 55517645149.51666}
    21 contour area 11273.5
    22 rectangle rate: 1.0
    23 <class 'dict'>
    24 {'nu21': -0.00012249343654428105, 'm00': 937.0, 'mu02': 71058.39887940139, 'm21': 2608467731.1666665, 'm10': 135997.16666666666, 'mu12': 5936.621304638684, 'm20': 19807560.666666664, 'm11': 17909800.0, 'mu11': -243.08831376582384, 'nu03': 0.00011619106641937682, 'nu20': 0.07834979461427596, 'mu20': 68788.69082770124, 'nu30': -0.00022638241437502373, 'nu11': -0.00027687573680371845, 'mu03': 3122.63853597641, 'nu12': 0.00022089728041426173, 'mu21': -3292.0149297602475, 'm01': 123397.5, 'm30': 2894852254.65, 'm03': 2168205818.75, 'mu30': -6084.034451007843, 'm02': 16321798.0, 'nu02': 0.08093497478772188, 'm12': 2368904858.633333}
    25 contour area 937.0
    26 rectangle rate: 0.9767441860465116
    27 <class 'dict'>
    28 {'nu21': 6.394444079962859e-05, 'm00': 1337.5, 'mu02': 143608.10929387622, 'm21': 17579855687.9, 'm10': 466171.8333333333, 'mu12': 2721.5148126482964, 'm20': 162620703.91666666, 'm11': 50394767.125, 'mu11': -5.531905494630337, 'nu03': -6.349478218615885e-05, 'nu20': 0.07899706959873945, 'mu20': 141318.35153687, 'nu30': -4.34086448861369e-05, 'nu11': -3.0923395201008077e-06, 'mu03': -4154.057602882385, 'nu12': 4.159836159363943e-05, 'mu21': 4183.47589077428, 'm01': 144588.3333333333, 'm30': 56778276750.950005, 'm03': 1736279429.2, 'mu30': -2839.9500732421875, 'm02': 15774102.416666666, 'nu02': 0.0802770459848727, 'm12': 5497902267.733334}
    29 contour area 1337.5
    30 rectangle rate: 1.0
    31 <class 'dict'>
    32 {'nu21': 0.00017643873342657596, 'm00': 1171.5, 'mu02': 108556.00897472398, 'm21': 7454198465.65, 'm10': 414346.8333333333, 'mu12': 11056.098625324667, 'm20': 146660034.25, 'm11': 21059689.791666664, 'mu11': 35.98085905984044, 'nu03': -0.00019657490281580083, 'nu20': 0.08019241081548555, 'mu20': 110057.04696020484, 'nu30': -0.0002541097288689007, 'nu11': 2.621723834062283e-05, 'mu03': -9233.870977252722, 'nu12': 0.00023536732516071226, 'mu21': 8287.998500894755, 'm01': 59542.83333333333, 'm30': 51949902144.450005, 'm03': 170360064.45000002, 'mu30': -11936.500625610352, 'm02': 3134888.9166666665, 'nu02': 0.07909868844053526, 'm12': 1108790894.15}
    33 contour area 1171.5
    34 rectangle rate: 0.9827586206896551
    35 <class 'dict'>
    36 {'nu21': -5.9617117618475176e-05, 'm00': 10188.0, 'mu02': 8080978.927321911, 'm21': 44361328538.15, 'm10': 2369605.833333333, 'mu12': 65883.69320464134, 'm20': 559585560.1666666, 'm11': 187859907.5833333, 'mu11': -6170.492562055588, 'nu03': 5.789763072450438e-05, 'nu20': 0.08135089273197578, 'mu20': 8443843.895822525, 'nu30': -6.649191036488463e-06, 'nu11': -5.944864503802395e-05, 'mu03': 606573.080696106, 'nu12': 6.288623516809079e-06, 'mu21': -624587.5391366482, 'm01': 807720.6666666666, 'm30': 134080649922.85, 'm03': 6999607777.200001, 'mu30': -69661.23208618164, 'm02': 72118344.0, 'nu02': 0.0778549269736214, 'm12': 16772943834.616667}
    37 contour area 10188.0
    38 rectangle rate: 0.9069767441860465
    39 <class 'dict'>
    40 {'nu21': 2.5029581296177077e-06, 'm00': 6468.0, 'mu02': 3195020.3257575743, 'm21': 2470652874.1666665, 'm10': 485015.3333333333, 'mu12': -51429.50591498613, 'm20': 40173096.0, 'm11': 29828671.666666664, 'mu11': -296.2417027428746, 'nu03': 3.7404301111953477e-06, 'nu20': 0.09091174159972219, 'mu20': 3803294.891706176, 'nu30': -7.103004931735946e-07, 'nu11': -7.081188784375375e-06, 'mu03': 12584.80737566948, 'nu12': -1.528577011835907e-05, 'mu21': 8421.289796680212, 'm01': 397789.0, 'm30': 3582848603.8, 'm03': 2094094606.5, 'mu30': -2389.830746650696, 'm02': 27659474.333333332, 'nu02': 0.07637190134652665, 'm12': 2074010642.2666667}
    41 contour area 6468.0
    42 rectangle rate: 0.22885572139303484
    43 <class 'dict'>
    44 {'nu21': 5.8846255461310086e-06, 'm00': 8996.5, 'mu02': 29965362.62111345, 'm21': 256564644068.48334, 'm10': 4439805.333333333, 'mu12': 212314.99474525452, 'm20': 2192577070.9166665, 'm11': 519527440.5416666, 'mu11': -3233.247374713421, 'nu03': -2.842289825086851e-06, 'nu20': 0.018743698111458488, 'mu20': 1517058.9236574173, 'nu30': -1.4152503746804512e-07, 'nu11': -3.9947698646528944e-05, 'mu03': -21819.87815475464, 'nu12': 2.765646741919632e-05, 'mu21': 45175.48184904456, 'm01': 1052739.3333333333, 'm30': 1083542072586.7001, 'm03': 24934332010.7, 'mu30': -1086.46875, 'm02': 153153280.5833333, 'nu02': 0.37023064958903834, 'm12': 75581154283.31667}
    45 contour area 8996.5
    46 rectangle rate: 0.19117647058823528
    47 <class 'dict'>
    48 {'nu21': 4.9640674350614795e-06, 'm00': 6161.5, 'mu02': 16228397.796561554, 'm21': 120405497566.23334, 'm10': 2520171.833333333, 'mu12': 189011.2604341507, 'm20': 1031361607.9166666, 'm11': 294213998.7916666, 'mu11': 1439.863492667675, 'nu03': -0.00013813884205259537, 'nu20': 0.014827896369745835, 'mu20': 562927.4773755074, 'nu30': -2.1518071719240386e-06, 'nu11': 3.7926993287653485e-05, 'mu03': -411653.62416648865, 'nu12': 6.342661674397237e-05, 'mu21': 14792.916459165514, 'm01': 719312.3333333333, 'm30': 422307195112.95, 'm03': 15486711827.2, 'mu30': -6412.3834228515625, 'm02': 100203117.08333333, 'nu02': 0.42746714354095977, 'm12': 40985524515.4}
    49 contour area 6161.5

     四、多边形逼近approxPolyDP

     1 import cv2 as cv
     2 import numpy as np
     3 
     4 def measure(image):
     5     #变成灰度图像,通过大律法得到二值图像
     6     gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
     7     ret , binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
     8     cv.imshow('binary image',binary)
     9     #将二值图像变成bgr,因为后面要用各种颜色画轮廓,所以需要变成BGR
    10     dst = cv.cvtColor(binary,cv.COLOR_GRAY2BGR)
    11     cv.imshow('binary_to_bgr',dst)
    12     #寻找轮廓
    13     outimage,contours,hireachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
    14     for i,contour in enumerate(contours):
    15         mm = cv.moments(contour)    #求的是每个轮廓的几何矩
    16         cx = mm['m10']/mm['m00']    #重心坐标x
    17         cy = mm['m01']/mm['m00']    #重心坐标y
    18         cv.circle(dst,(np.int(cx),np.int(cy)),2,(0,255,255),-1)     #画重心点,填充的方法
    19         #多边形逼近
    20         #arg:
    21         #   每个轮廓的位置信息contour
    22         #   4是与阈值的间隔大小,越小就越容易找出,True是 是否找闭合图像
    23         approxcure = cv.approxPolyDP(contour,4,True)
    24         print(approxcure.shape)     #每个轮廓的信息
    25 
    26         if approxcure.shape[0] >= 7:        #>=7 就都是圆了
    27             cv.drawContours(dst,contours,i,(0,0,255),2)
    28         elif approxcure.shape[0] == 4:      #4说明有四个点,是矩形;3是三个点,三角形
    29             cv.drawContours(dst,contours,i,(0,255,0),2)
    30         else:
    31             cv.drawContours(dst,contours,i,(255,0,0),2)
    32     cv.imshow('measure_image',dst)
    33 
    34 img = cv.imread('contours.png')
    35 cv.imshow('input_image',img)
    36 measure(img)
    37 cv.waitKey(0)
    38 cv.destroyAllWindows()
     1 (4, 1, 2)
     2 (4, 1, 2)
     3 (4, 1, 2)
     4 (3, 1, 2)
     5 (7, 1, 2)
     6 (8, 1, 2)
     7 (8, 1, 2)
     8 (13, 1, 2)
     9 (4, 1, 2)
    10 (4, 1, 2)
    11 (9, 1, 2)
    12 (4, 1, 2)

     

  • 相关阅读:
    UOJ.26.[IOI2014]Game(交互 思路)
    Good Bye 2016 F.New Year and Finding Roots(交互)
    Codeforces.835E.The penguin's game(交互 按位统计 二分)
    Codeforces.744B.Hongcow's Game(交互 按位统计)
    Codeforces.862D.Mahmoud and Ehab and the binary string(交互 二分)
    正睿OI 提高 Day1T3 ZYB玩字符串(DP)
    划分vlan
    2三层交换机实现vlan间的路由
    交换机基础-交换机远程telnet
    自动化运维环境的搭建问题处理
  • 原文地址:https://www.cnblogs.com/pacino12134/p/9889125.html
Copyright © 2011-2022 走看看