OpenCV

您所在的位置:网站首页 ai图像轮廓化 OpenCV

OpenCV

2024-07-14 20:37| 来源: 网络整理| 查看: 265

1.什么是轮廓? 轮廓可以简单认为成将连续的点(连着边界)连在一起的曲线,具有相同的颜色或者灰度。轮廓在形状分析和物体的检测和识别中很有用。 为了更加准确,要使用二值化图像。在寻找轮廓之前,要进行阈值化处理或者 Canny 边界检测。函数 cv2.fifindContours() 有三个参数,第一个是输入图像,第二个是轮廓检索模式,第三个是轮廓近似方法。函数 cv2.drawContours() 可以被用来绘制轮廓。它可以根据你提供的边界点绘制任何形状。它的第一个参数是原始图像,第二个参数是轮廓,一个 Python 列表。第三个参数是轮廓的索引(在绘制独立轮廓是很有用,当设置为 -1 时绘制所有轮廓)。接下来的参数是轮廓的颜色和厚度等。 import cv2 img = cv2.imread('opencv.jpg') imggray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imggray,0,255,cv2.THRESH_OTSU) #cv2.CHAIN_APPROX_NONE,所有的边界点都会被存储 #cv2.CHAIN_APPROX_SIMPLE只存储端点 contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) # -1代表绘制所有轮廓 img1 = cv2.drawContours(img,contours,-1,(0,0,0),3) cv2.imshow('img1',img1) cv2.waitKey(0) cv2.destroyAllWindows()

在这里插入图片描述

2.轮廓特征:

2.1 矩

#轮廓重心 cnt = contours[0] M = cv2.moments(cnt) print(M) cx = int(M['m10']/M['m00']) cy = int(M['m01']/M['m00']) print (cx,cy)

{‘m00’: 165073.0, ‘m10’: 35573231.5, ‘m01’: 31611479.5, ‘m20’: 10221375184.333332, ‘m11’: 6812273832.25, ‘m02’: 8071464432.333333, ‘m30’: 3304059528335.75, ‘m21’: 1957393347799.8333, ‘m12’: 1739400585167.8333, ‘m03’: 2318528158187.75, ‘mu20’: 2555343796.083332, ‘mu11’: 0.0, ‘mu02’: 2017866108.083333, ‘mu30’: 0.0009765625, ‘mu21’: 0.00018310546875, ‘mu12’: 0.0, ‘mu03’: 0.0, ‘nu20’: 0.0937771975630983, ‘nu11’: 0.0, ‘nu02’: 0.07405259087393658, ‘nu30’: 8.82083976632943e-17, ‘nu21’: 1.653907456186768e-17, ‘nu12’: 0.0, ‘nu03’: 0.0} 215 191

2.2 轮廓面积 轮廓的面积可以使用函数 cv2.contourArea() 计算得到,也可以使用矩(0 阶矩),M[‘m00’]。 #轮廓面积 area = cv2.contourArea(cnt) print (area)

165073.0

2.3 轮廓周长 也被称为弧长。可以使用函数 cv2.arcLength() 计算得到。这个函数的第二参数可以用来指定对象的形状是闭合(True),还是打开的(一条曲线)。 #轮廓周长 perimeter = cv2.arcLength(cnt,True) print (perimeter)

1628.0

2.4 轮廓近似 将轮廓形状近似到另外一种由更少点组成的轮廓形状,新轮廓的点的数目由我们设定的准确度来决定。使用的Douglas-Peucker算法。 为了帮助理解,假设我们要在一幅图像中查找一个矩形,但是由于图像的种种原因,我们不能得到一个完美的矩形,而是一个“坏形状”(如下图所示)。现在你就可以使用这个函数来近似这个形状()了。这个函数的第二个参数叫epsilon,它是从原始轮廓到近似轮廓的最大距离。它是一个准确度参数。选择一个好的 epsilon 对于得到满意结果非常重要。 #轮廓近似 img = cv2.imread('giao.jpg') imggray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imggray,0,255,cv2.THRESH_OTSU) contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cnt = contours[0] epsilon = 0.1*cv2.arcLength(cnt,True) approx = cv2.approxPolyDP(cnt,epsilon,True) cv2.polylines(img,[approx],True,(0,0,255),2) cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows()

下边,第二幅图中的绿线是当 epsilon = 10% 时得到的近似轮廓,第三幅图是当 epsilon = 1% 时得到的近似轮廓。第三个参数设定弧线是否闭合。 在这里插入图片描述

2.5 凸包 凸包与轮廓近似相似,但不同,虽然有些情况下它们给出的结果是一样的。函数 cv2.convexHull() 可以用来检测一个曲线是否具有凸性缺陷,并能纠正缺陷。 #凸包img = cv2.imread('giao.jpg') img2 = cv2.imread('giao.jpg') imggray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imggray,0,255,cv2.THRESH_OTSU) contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cnt = contours[0] hull = cv2.convexHull(cnt) cv2.polylines(img2,[hull],True,(0,0,255),2) cv2.imshow('img',img2) cv2.waitKey(0) cv2.destroyAllWindows()

在这里插入图片描述 对此可以参考链接:https://segmentfault.com/a/1190000015663722

2.6 凸性检测 #凸性检测 k = cv2.isContourConvex(cnt) print (k)

False

2.7 直边界矩形 #边界矩形,直边矩形 img3 = cv2.imread('str.jpg') imggray = cv2.cvtColor(img3,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imggray,0,255,cv2.THRESH_OTSU) contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cnt = contours[1] #(x,y)为矩形左上角的坐标,(w,h)是矩形的宽和高。 x,y,w,h = cv2.boundingRect(cnt) img4 = cv2.rectangle(img3,(x,y),(x+w,y+h),(0,255,0),2) cv2.imshow('img',img4) cv2.waitKey(0) cv2.destroyAllWindows()

在这里插入图片描述

2.8 最小外接矩形 这个边界矩形是面积最小的,因为它考虑了对象的旋转。用到的函数为cv2.minAreaRect()。返回的是一个 Box2D 构,其中包含矩形左上角角点的坐标(x,y),矩形的宽和高(w,h),以及旋转角度。但是要绘制这个矩形需要矩形的 4 个角点,可以通过函数 cv2.boxPoints() 获得。 #最小外接矩形 import numpy as np img3 = cv2.imread('str.jpg') imggray = cv2.cvtColor(img3,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imggray,0,255,cv2.THRESH_OTSU) contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cnt = contours[1] rect = cv2.minAreaRect(cnt) box = cv2.boxPoints(rect) box = np.int0(box) cv2.fillPoly(img3,[box],(0,0,255)) cv2.imshow('img',img3) cv2.waitKey(0) cv2.destroyAllWindows()

在这里插入图片描述

2.9 最小外接圆 #最小外接圆 img3 = cv2.imread('str.jpg') imggray = cv2.cvtColor(img3,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imggray,0,255,cv2.THRESH_OTSU) contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cnt = contours[1] (x,y),radius = cv2.minEnclosingCircle(cnt) center = (int(x),int(y)) radius = int(radius) img4 = cv2.circle(img3,center,radius,(0,255,0),2) cv2.imshow('img',img4) cv2.waitKey(0) cv2.destroyAllWindows()

在这里插入图片描述

2.10 椭圆拟合 #椭圆拟合 img3 = cv2.imread('str.jpg') imggray = cv2.cvtColor(img3,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imggray,0,255,cv2.THRESH_OTSU) contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cnt = contours[1] ellipse = cv2.fitEllipse(cnt) im = cv2.ellipse(img3,ellipse,(0,255,0),2) cv2.imshow('img',im) cv2.waitKey(0) cv2.destroyAllWindows()

在这里插入图片描述

2.11 直线拟合 #直线拟合 img3 = cv2.imread('str.jpg') rows,cols = img3.shape[:2] imggray = cv2.cvtColor(img3,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imggray,0,255,cv2.THRESH_OTSU) contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cnt = contours[1] [vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01) lefty = int((-x*vy/vx) + y) righty = int(((cols-x)*vy/vx)+y) img = cv2.line(img3,(cols-1,righty),(0,lefty),(0,255,0),2) cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows()

在这里插入图片描述

3.轮廓性质3.1 宽高比 #宽高比 x,y,w,h = cv2.boundingRect(cnt) aspect_ratio = float(w)/h print (aspect_ratio) 3.2 轮廓面积与边界矩形面积的比 area = cv2.contourArea(cnt) x,y,w,h = cv2.boundingRect(cnt) rect_area = w*h extent = float(area)/rect_area print (extent) 3.3 轮廓面积与凸包面积的比 area = cv2.contourArea(cnt) hull = cv2.convexHull(cnt) hull_area = cv2.contourArea(hull) solidity = float(area)/hull_area print (solidity) 3.4 与轮廓面积相等的圆形直径 area = cv2.contourArea(cnt) equi_diameter = np.sqrt(4*area/np.pi) print (equi_diameter) 3.5 方向 (x,y),(MA,ma),angle = cv2.fitEllipse(cnt) print ((x,y),(MA,ma),angle) 3.6 轮廓的掩膜与像素点 img = cv2.imread('str.jpg',0) mask = np.zeros(img.shape,np.uint8) mask = cv2.drawContours(mask,[cnt],0,255,-1) cv2.imshow('mask',mask) cv2.waitKey(0) cv2.destroyAllWindows()

在这里插入图片描述

3.7 最大值和最小值及它们的位置 min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(img,mask=mask) print (min_val,max_val,min_loc,max_loc) 3.8 平均颜色及平均灰度 mean_val = cv2.mean(img,mask=mask) print (mean_val) 3.9 极点 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]) print (leftmost,rightmost,topmost,bottommost) 3.10 凸缺陷 前面我们已经学习了轮廓的凸包,对象上的任何凹陷都被成为凸缺陷。OpenCV 中有一个函数 cv.convexityDefect() 可以帮助我们找到凸缺陷。如果要查找凸缺陷,在使用函数 cv2.convexHull 找凸包时,参数returnPoints 一定要是 False。它会返回一个数组,其中每一行包含的值是 [起点,终点,最远的点,到最远点的近似距离。 #凸缺陷 import cv2 import numpy as np img = cv2.imread('fb.jpg') img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(img_gray,0,255,cv2.THRESH_OTSU) contours,hierarchy = cv2.findContours(thresh,2,1) cnt = contours[6] hull = cv2.convexHull(cnt,returnPoints=False) defects = cv2.convexityDefects(cnt,hull) for i in range(defects.shape[0]): s,e,f,d = defects[i,0] start = tuple(cnt[s][0]) end = tuple(cnt[e][0]) far = tuple(cnt[f][0]) cv2.line(img,start,end,[0,255,0],2) cv2.circle(img,far,5,[0,0,255],-1) cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows()

在这里插入图片描述

3.11 Point Polygon Test 求解图像中的一个点到一个对象轮廓的最短距离。如果点在轮廓的外部,返回值为负。如果在轮廓上,返回值为 0。如果在轮廓内部,返回值为正。此函数的第三个参数是measureDist如果设置为True,就会计算最短距离。如果是 False,只会判断这个点与轮廓之间的位置关系(返回值为 +1,-1,0)。 # Point Polygon Test dist = cv2.pointPolygonTest(cnt,(50,50),True) print (dist) 3.12 形状匹配 函数 cv2.matchShape() 可以帮我们比较两个形状或轮廓的相似度。如果返回值越小,匹配越好。它是根据 Hu 矩来计算的。 # 形状匹配 import cv2 import numpy as np img = cv2.imread('fb.jpg') img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(img_gray,0,255,cv2.THRESH_OTSU) contours,hierarchy = cv2.findContours(thresh,2,1) cnt1 = contours[6] img2 = cv2.imread('2.jpg',0) ret, thresh2 = cv2.threshold(img2, 127, 255,0) contours,hierarchy = cv2.findContours(thresh,2,1) cnt2 = contours[0] ret1 = cv2.matchShapes(cnt1,cnt2,1,0.0) ret2 = cv2.matchShapes(cnt1,cnt1,1,0.0) print (ret1,ret2)

0.3493676665950478 0.0 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3