• 十九 对象测量


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

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

     

     二、相关函数

    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)

     

  • 相关阅读:
    AChartEngine方法的使用及事件汇总
    免费的Android UI库及组件推荐
    消灭Bug!十款免费移动应用测试框架推荐
    AChartEngine 安卓折线图 柱形图等利器
    添加几个有用的网址
    演示Android百度地图操作功能
    Android 如何在Eclipse中查看Android API源码 及 support包源码
    Android入门之GPS定位详解
    软考之数据库部分
    SSE && WebSockets
  • 原文地址:https://www.cnblogs.com/pacino12134/p/9889125.html
Copyright © 2020-2023  润新知