本文共 9426 字,大约阅读时间需要 31 分钟。
逼近多边形是轮廊的高度相似,但是有时候,我们希望使用一个多边形的凸包来简化它,凸包跟逼近多边形很相似,只不过它是物体最外层的“凸”多边形。凸包指的是完全包含原有轮廊,并且仅有轮廊上的点所构成的多边形。凸包的每一处都是凸的,即在凸包内连接任意两点的直线都在凸包的内部。在凸包内,任意连接三个点的内角小于180°
1.使用cv2.convexHull()函数,实现图像轮廓凸包的获取。 2.使用cv2.polylines()函数,实现图像轮廓凸包的绘制。凸包的绘制
cv2.polylines(src, [points], isClosed,color, thickness)
src:要处理的图像。
points:点集。 isClosed:布尔型,True表示的是线段闭合,False表示的是仅保留线段。 color:线段颜色,格式是(B,G,R)值。 thickness:数值型,厚度,默认值为1,如果对封闭图形,正方形,三角形等传入-1,则会填充整个图形。import cv2img = cv2.imread('contours2.png', 1)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)cnt = contours[0]hull = cv2.convexHull(cnt)cv2.polylines(img,[hull],True,(255,0,0),2)cv2.imshow('line', img)cv2.waitKey()cv2.destroyAllWindows()
实物凸包检测
import cv2img = cv2.imread('hand.png', 1)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)ret, binary = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)n=len(contours) contoursImg=[]x=0 for i in range(n): area = cv2.contourArea(contours[i]) if area>10000: print(f"轮廓{i}的面积:\n{area}") x=icnt = contours[x]cv2.imshow("binary",binary)hull = cv2.convexHull(cnt)cv2.polylines(img,[hull],True,(0,255,0),2)cv2.drawContours(img,contours,x,(0,0,255), 3)#显示图片cv2.imshow('line', img)cv2.waitKey(0)cv2.destroyAllWindows()
凸缺陷的概念
凸包与轮廓之间的部分,称为凸缺陷。轮廓上距离这条线最远的
点就是凸缺陷的点。convexityDefects = cv2.convexityDefects(contour, convexhull)
contour:轮廓。
convexhull:凸包.import cv2o = cv2.imread('contours2.png') gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)cnt = contours[0]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(o,start,end,[0,0,255],2) cv2.circle(o,far,5,[255,0,0],-1)cv2.imshow('result',o)cv2.waitKey(0)cv2.destroyAllWindows()
import cv2import numpy as npimg = cv2.imread('hand.png') blur=cv2.medianBlur(img,5)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,60,255,cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)n=len(contours) contoursImg=[]x=0 for i in range(n): area = cv2.contourArea(contours[i]) if area>10000: print(f"轮廓{i}的面积:\n{area}") x=icnt = contours[x]hull = cv2.convexHull(cnt,returnPoints = False) defects = cv2.convexityDefects(cnt,hull) #print(defects)for i in range(defects.shape[0]): s,e,f,d = defects[i,0] #print(s,e,f,d) start = tuple(cnt[s][0]) end = tuple(cnt[e][0]) far = tuple(cnt[f][0]) #print(far ,end) cv2.line(img,start,end,[0,0,255],2) cv2.circle(img,far,5,[255,0,0],-1)cv2.imshow('result',img)cv2.waitKey(0)cv2.destroyAllWindows()
可以使用宽高比(AspectRation)来描述轮廓,例如矩形轮廓的宽高比为:
宽高比=宽度(Width)/高度(Height)import cv2o = cv2.imread('binaryhand.png') cv2.imshow("original",o)gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) x,y,w,h = cv2.boundingRect(contours[0])cv2.rectangle(o,(x,y),(x+w,y+h),(255,255,255),3)aspectRatio = float(w)/hprint(aspectRatio)cv2.imshow("result",o)cv2.waitKey()cv2.destroyAllWindows()
可以使用轮廓面积与矩形边界(矩形包围框、矩形轮廓)面积之比Extend来描述图像及其轮廓特征。计算方法为:
Extend =轮廓面积/矩形边界面积import cv2o = cv2.imread('binaryhand.png') cv2.imshow("original",o)gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) x,y,w,h = cv2.boundingRect(contours[0])cv2.drawContours(o,contours[0],-1,(0,0,255),3) cv2.rectangle(o,(x,y),(x+w,y+h),(255,0,0),3)rectArea=w*hcntArea=cv2.contourArea(contours[0])extend=float(cntArea)/rectAreaprint(extend)cv2.imshow("result",o)cv2.waitKey()cv2.destroyAllWindows()
OpenCV提供了函数cv2.minMaxLoc(),用于在指定的对象内查找最大值、最小值及其位置。该函数的语法格式是:
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(imgray, mask = mask)
min_val:最小值。
max_val:最大值。 min_loc:最小值的位置。 max_loc:最大值的位置。 OpenCV提供了函数cv2.mean(),用于计算一个对象的平均颜色或 平均灰度。该函数的语法格式为: mean_val = cv2.mean(im, mask = mask) im:原图像。 mask:掩模。import cv2import numpy as npo = cv2.imread('ct2.jpg') cv2.imshow("original",o)gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) cnt=contours[3] mask = np.zeros(gray.shape,np.uint8)mask=cv2.drawContours(mask,[cnt],-1,255,-1) minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(gray,mask = mask)print("minVal=",minVal)print("maxVal=",maxVal)print("minLoc=",minLoc)print("maxLoc=",maxLoc)masko = np.zeros(o.shape,np.uint8)masko=cv2.drawContours(masko,[cnt],-1,(255,255,255),-1)loc=cv2.bitwise_and(o,masko) cv2.imshow("mask",loc)#显示灰度结果#loc=cv2.bitwise_and(gray,mask) #cv2.imshow("mask",loc)cv2.destroyAllWindows()
meanVal = cv2.mean(o,mask = mask) #mask是区域,所以必须是单通道的print("meanVal=\n",meanVal)
有时,我们希望获取某个对象内的极值点,例如最左端、最右端、
最上端、最下端的四个点。OpenCV提供了相应的函数来找出这些 点,通常的语法格式是: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])
import cv2import numpy as npo = cv2.imread('binaryhand.png') o1 = cv2.imread("face.png")o1 = cv2.resize(o1,(40,40))gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) mask = np.zeros(gray.shape,np.uint8)cnt=contours[0] cv2.drawContours(mask,[cnt],0,255,-1)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=",leftmost)print("rightmost=",rightmost)print("topmost=",topmost)print("bottommost=",bottommost)font=cv2.FONT_HERSHEY_SIMPLEXcv2.putText(o,'A',leftmost, font, 1,(0,0,255),2)o[284:324,229:269]=o1cv2.putText(o,'B',rightmost, font, 1,(0,0,255),2)cv2.putText(o,'C',topmost, font, 1,(0,0,255),2)cv2.putText(o,'D',bottommost, font, 1,(0,0,255),2)cv2.imshow("result",o)cv2.waitKey()cv2.destroyAllWindows()
import cv2import numpy as npimg = cv2.imread('face.png') cv2.imshow("original",img)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,0,255,cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) h,w,c=img.shapemask = np.zeros((h,w,c),np.uint8)for cnt in contours: x,y,w,h = cv2.boundingRect(cnt) cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,255),3) ratio = float(w)/h if ratio<1: cv2.drawContours(mask,[cnt],-1,(0,0,255), -1) #n+=1 print(ratio,"是长的椭圆") else: cv2.drawContours(mask,[cnt],-1,(0,255,255), -1) #n+=1 print(ratio,"是扁的椭圆")cv2.imshow("result",mask)cv2.waitKey()cv2.destroyAllWindows()
import cv2import numpy as npimg = cv2.imread('face.png') cv2.imshow("original",img)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,0,255,cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) h,w,c=img.shapemask = np.zeros((h,w,c),np.uint8)for cnt in contours: x,y,w,h = cv2.boundingRect(cnt) cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,255),3) ratio = float(w)/h rectArea=w*h cntArea=cv2.contourArea(contours[0]) extend=float(cntArea)/rectArea print(extend) if ratio<1: cv2.drawContours(mask,[cnt],-1,(0,0,255), -1) print(ratio,"是长的椭圆") else: cv2.drawContours(mask,[cnt],-1,(0,255,255), -1) print(ratio,"是扁的椭圆") if extend==0.9818696450428397: cv2.drawContours(mask,[cnt],-1,(255,0,255), -1) cv2.imshow("result",mask)cv2.waitKey()cv2.destroyAllWindows()
import cv2import numpy as npimg = cv2.imread('face.png') cv2.imshow("original",img)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray,0,255,cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) h,w,c=img.shapemask = np.zeros((h,w,c),np.uint8)n1,n2,n3=0,0,0for cnt in contours: x,y,w,h = cv2.boundingRect(cnt) cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,255),3) ratio = float(w)/h rectArea=w*h cntArea=cv2.contourArea(contours[0]) extend=float(cntArea)/rectArea print(extend) if extend==0.9818696450428397: n1+=1 cv2.drawContours(mask,[cnt],-1,(255,0,0), -1) elif ratio<1 and extend!=0.9818696450428397: cv2.drawContours(mask,[cnt],-1,(0,0,255), -1) n2+=1 else: cv2.drawContours(mask,[cnt],-1,(0,255,255), -1) n3+=1print(f"有{n1}个矩形,有{n2}个长的椭圆,有{n3}个扁的椭圆")cv2.imshow("result",mask)cv2.waitKey()cv2.destroyAllWindows()
转载地址:http://clklf.baihongyu.com/