def getContours(img):
img = cv2.resize(img, (0, 0), None, 0.5, 0.5)
imgG = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
imgBlur = cv2.GaussianBlur(imgG,(5,5),1)
imgCanny = cv2.Canny(imgBlur,100,100)
kernel = np.ones((5,5))
imgDial = cv2.dilate(imgCanny,kernel,iterations=3)
imgThre = cv2.erode(imgDial,kernel,iterations=2)
cv2.imshow('img',img)
cv2.imshow('res',imgCanny)
cv2.imshow('res2',imgThre)
getContours(img)
cv2.waitKey(0)
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]]) → image, contours, hierarchy
image-寻找轮廓的图像;
mode-轮廓的检索模式:cv2.RETR_EXTERNAL表示只检测外轮廓
method cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
contourArea()函数的作用:主要用于计算图像轮廓的面积。
arcLength()函数的作用:主要是计算图像轮廓的周长
approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)
主要功能是把一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合
InputArray curve:一般是由图像的轮廓点组成的点集
OutputArray approxCurve:表示输出的多边形点集
double epsilon:主要表示输出的精度,就是另个轮廓点之间最大距离数,5,6,7,,
bool closed:表示输出的多边形是否封闭
boundingRect函数
函数作用:计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的
contours, hiearchy = cv2.findContours(imgThre,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
finalCountours = []
for i in contours:
area = cv2.contourArea(i)
if area> minArea:
# 计算轮廓的周长,true表示轮廓为封闭
peri = cv2.arcLength(i,True)
#进行轮廓的多边拟合
appprox = cv2.approxPolyDP(i,0.02*peri,True)
bbox = cv2.boundingRect(appprox)
if filter > 0 :
if(len(appprox))==filter:
finalCountours.append([len(appprox),area,appprox,bbox,i])
else:
finalCountours.append([len(appprox), area, appprox, bbox, i])
# 对第二个数值面积进行排序,为升序,找出轮廓的最大值
finalCountours = sorted(finalCountours, key=lambda x: x[1], reverse=True)
for con in finalCountours:
cv2.drawContours(img, con[4], -1, (0, 0, 255), 3)
这个函数为重新排序函数,无论给什么顺序的四角坐标,都能整理好!
def reorder(myPoints):
#print(myPoints.shape)
# zeros_like 输出为形状和x一致的矩阵,其元素全部为0
myPointsNew = np.zeros_like(myPoints)
myPoints = myPoints.reshape((4,2))
add = myPoints.sum(1)
myPointsNew[0] = myPoints[np.argmin(add)]
myPointsNew[3] = myPoints[np.argmax(add)]
diff = np.diff(myPoints,axis=1)
myPointsNew[1]= myPoints[np.argmin(diff)]
myPointsNew[2] = myPoints[np.argmax(diff)]
return myPointsNew
def warpImg (img,points,w,h,pad=20):
# print(points)
points =reorder(points)
pts1 = np.float32(points)
pts2 = np.float32([[0,0],[w,0],[0,h],[w,h]])
matrix = cv2.getPerspectiveTransform(pts1,pts2)
imgWarp = cv2.warpPerspective(img,matrix,(w,h))
imgWarp = imgWarp[pad:imgWarp.shape[0]-pad,pad:imgWarp.shape[1]-pad]
return imgWarp
imgcon, cons= getContours(img)
if(len(cons)!=0):
maxbox = cons[0][2]
reorder(maxbox)
cv2.imshow('img', imgcon)
imgWarp = warpImg(imgcon, maxbox, wp, hp)
cv2.imshow('imgWarp',imgWarp)
imgcon2, cons2 = getContours(imgWarp)
if(len(cons2)!=0):
for obj in cons2:
cv2.polylines(imgcon2,[obj[2]],True,(0,255,0),2)
cv2.imshow('img2',imgcon2)
def findDis(pts1,pts2):
return ((pts2[0]-pts1[0])**2 + (pts2[1]-pts1[1])**2)**0.5
if(len(cons2)!=0):
for obj in cons2:
cv2.polylines(imgcon2,[obj[2]],True,(0,255,0),2)
nPoints = reorder(obj[2])
nW = round((findDis(nPoints[0][0] // scale, nPoints[1][0] // scale) / 10), 1)
nH = round((findDis(nPoints[0][0] // scale, nPoints[2][0] // scale) / 10), 1)
cv2.arrowedLine(imgcon2, (nPoints[0][0][0], nPoints[0][0][1]), (nPoints[1][0][0], nPoints[1][0][1]),
(255, 0, 255), 3, 8, 0, 0.05)
cv2.arrowedLine(imgcon2, (nPoints[0][0][0], nPoints[0][0][1]), (nPoints[2][0][0], nPoints[2][0][1]),
(255, 0, 255), 3, 8, 0, 0.05)
x, y, w, h = obj[3]
cv2.putText(imgcon2, '{}cm'.format(nW), (x + 30, y - 10), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.5,
(255, 0, 255), 2)
cv2.putText(imgcon2, '{}cm'.format(nH), (x - 70, y + h // 2), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.5,
(255, 0, 255), 2)
cv2.imshow('img2',imgcon2)
import cv2
import numpy as np
img = cv2.imread('3.png')
img = cv2.resize(img, (0, 0), None, 0.5, 0.5)
minArea = 1000
filter = 4
scale =2
wp=210*scale
hp =297*scale
def getContours(img):
imgG = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
imgBlur = cv2.GaussianBlur(imgG,(5,5),1)
imgCanny = cv2.Canny(imgBlur,100,100)
kernel = np.ones((5,5))
imgDial = cv2.dilate(imgCanny,kernel,iterations=3)
imgThre = cv2.erode(imgDial,kernel,iterations=2)
cv2.imshow('res',imgCanny)
cv2.imshow('res2',imgThre)
contours, hiearchy = cv2.findContours(imgThre,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
finalCountours = []
for i in contours:
area = cv2.contourArea(i)
if area> minArea:
# 计算轮廓的周长,true表示轮廓为封闭
peri = cv2.arcLength(i,True)
#进行轮廓的多边拟合
appprox = cv2.approxPolyDP(i,0.02*peri,True)
bbox = cv2.boundingRect(appprox)
if filter > 0 :
if(len(appprox))==filter:
finalCountours.append([len(appprox),area,appprox,bbox,i])
else:
finalCountours.append([len(appprox), area, appprox, bbox, i])
# 对第二个数值面积进行排序,为升序,找出轮廓的最大值
finalCountours = sorted(finalCountours, key=lambda x: x[1], reverse=True)
for con in finalCountours:
cv2.drawContours(img,con[4],-1, (0, 0, 255), 4)
return img,finalCountours
def reorder(myPoints):
#print(myPoints.shape)
myPointsNew = np.zeros_like(myPoints)
myPoints = myPoints.reshape((4,2))
add = myPoints.sum(1)
myPointsNew[0] = myPoints[np.argmin(add)]
myPointsNew[3] = myPoints[np.argmax(add)]
diff = np.diff(myPoints,axis=1)
myPointsNew[1]= myPoints[np.argmin(diff)]
myPointsNew[2] = myPoints[np.argmax(diff)]
print(myPoints)
print(myPoints)
return myPointsNew
def warpImg (img,points,w,h,pad=20):
# print(points)
points =reorder(points)
pts1 = np.float32(points)
pts2 = np.float32([[0,0],[w,0],[0,h],[w,h]])
matrix = cv2.getPerspectiveTransform(pts1,pts2)
imgWarp = cv2.warpPerspective(img,matrix,(w,h))
imgWarp = imgWarp[pad:imgWarp.shape[0]-pad,pad:imgWarp.shape[1]-pad]
return imgWarp
def findDis(pts1,pts2):
return ((pts2[0]-pts1[0])**2 + (pts2[1]-pts1[1])**2)**0.5
imgcon, cons= getContours(img)
if(len(cons)!=0):
maxbox = cons[0][2]
reorder(maxbox)
cv2.imshow('img', imgcon)
imgWarp = warpImg(imgcon, maxbox, wp, hp)
cv2.imshow('imgWarp',imgWarp)
imgcon2, cons2 = getContours(imgWarp)
if(len(cons2)!=0):
for obj in cons2:
cv2.polylines(imgcon2,[obj[2]],True,(0,255,0),2)
nPoints = reorder(obj[2])
nW = round((findDis(nPoints[0][0] // scale, nPoints[1][0] // scale) / 10), 1)
nH = round((findDis(nPoints[0][0] // scale, nPoints[2][0] // scale) / 10), 1)
cv2.arrowedLine(imgcon2, (nPoints[0][0][0], nPoints[0][0][1]), (nPoints[1][0][0], nPoints[1][0][1]),
(255, 0, 255), 3, 8, 0, 0.05)
cv2.arrowedLine(imgcon2, (nPoints[0][0][0], nPoints[0][0][1]), (nPoints[2][0][0], nPoints[2][0][1]),
(255, 0, 255), 3, 8, 0, 0.05)
x, y, w, h = obj[3]
cv2.putText(imgcon2, '{}cm'.format(nW), (x + 30, y - 10), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.5,
(255, 0, 255), 2)
cv2.putText(imgcon2, '{}cm'.format(nH), (x - 70, y + h // 2), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.5,
(255, 0, 255), 2)
cv2.imshow('img2',imgcon2)
cv2.waitKey(0)