import numpy as np
#Numpy是科学计算库,是一个强大的N维数组对象ndarray
import copy
import cv2
#Python 中赋值语句不复制对象,而是在目标和对象之间创建绑定 (bindings) 关系。对于自身可变或者包含可变项的集合对象,开发者有时会需要生成其副本用于改变操作,进而避免改变原对象。
#copy模块提供了通用的浅层复制和深层复制操作。
def reshape_image(image):
'''归一化图片尺寸:短边400,长边不超过800,短边400,长边超过800以长边800为主'''
width,height=image.shape[1],image.shape[0]#image.shape显示图片尺寸,1宽度、0高度
min_len=width
scale=width*1.0/400
new_width=400
new_height=int(height/scale)
if new_height>800:
new_height=800
scale=height*1.0/800
new_width=int(width/scale)
out=cv2.resize(image,(new_width,new_height))
#cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) 改变图像的大小(高、宽、按比例调整大小)
#src(原图像)、dsize(输出图像所需大小)这个包括可选项为:fx(沿水平轴的比例因子)、fy(沿垂直轴的比例因子);
#interpolation(插值方式:cv.INTER_NEAREST-最近领插值、cv.INTER_LINEAR-双线性插值、cv.INTER_CUBIC-双线性插值、cv.INTER_AREA-cv.INTER_AREA)
return out
def detecte(image):
'''提取所有轮廓'''
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#转换为灰度图
_,gray=cv2.threshold(gray,0,255,cv2.THRESH_OTSU+cv2.THRESH_BINARY_INV)#图像阈值处理
contours,hierachy=cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)#寻找轮廓(寻找轮廓的图像、轮廓的检索方式、轮廓的近似办法)
#返回的三个参数(处理图像、轮廓的点集、各层轮廓的索引)
return contours,hierachy
def compute_1(contours,i,j):
'''最外面的轮廓和子轮廓的比例'''
area1 = cv2.contourArea(contours[i])#求某一个轮廓的面积
area2 = cv2.contourArea(contours[j])
if area2==0:
return False
ratio = area1 * 1.0 / area2
if abs(ratio - 49.0 / 25):#返回数字的绝对值。
return True
return False
def compute_2(contours,i,j):
'''子轮廓和子子轮廓的比例'''
area1 = cv2.contourArea(contours[i])
area2 = cv2.contourArea(contours[j])
if area2==0:
return False
ratio = area1 * 1.0 / area2
if abs(ratio - 25.0 / 9):
return True
return False
def compute_center(contours,i):
'''计算轮廓中心点'''
M=cv2.moments(contours[i])#会得到一个矩以一个字典的形式返回
cx = int(M['m10'] / M['m00'])#重心计算公式
cy = int(M['m01'] / M['m00'])
return cx,cy
def detect_contours(vec):
'''判断这个轮廓和它的子轮廓以及子子轮廓的中心的间距是否足够小'''
distance_1=np.sqrt((vec[0]-vec[2])**2+(vec[1]-vec[3])**2)#平方根计算
distance_2=np.sqrt((vec[0]-vec[4])**2+(vec[1]-vec[5])**2)
distance_3=np.sqrt((vec[2]-vec[4])**2+(vec[3]-vec[5])**2)
if sum((distance_1,distance_2,distance_3))/3<3:
return True
return False
def juge_angle(rec):
'''判断寻找是否有三个点可以围成等腰直角三角形'''
if len(rec)<3:#返回字符串、列表、字典、元组等长度
return -1,-1,-1
for i in range(len(rec)):#可创建一个整数列表;range(start, stop[, step]):start: 计数从 start 开始、stop: 计数到 stop 结束,但不包括 stop、step:步长,默认为1。
for j in range(i+1,len(rec)):
for k in range(j+1,len(rec)):
distance_1 = np.sqrt((rec[i][0] - rec[j][0]) ** 2 + (rec[i][1] - rec[j][1]) ** 2)
distance_2 = np.sqrt((rec[i][0] - rec[k][0]) ** 2 + (rec[i][1] - rec[k][1]) ** 2)
distance_3 = np.sqrt((rec[j][0] - rec[k][0]) ** 2 + (rec[j][1] - rec[k][1]) ** 2)
if abs(distance_1-distance_2)<5:
if abs(np.sqrt(np.square(distance_1)+np.square(distance_2))-distance_3)<5:
return i,j,k
elif abs(distance_1-distance_3)<5:
if abs(np.sqrt(np.square(distance_1)+np.square(distance_3))-distance_2)<5:
return i,j,k
elif abs(distance_2-distance_3)<5:
if abs(np.sqrt(np.square(distance_2)+np.square(distance_3))-distance_1)<5:
return i,j,k
return -1,-1,-1
def find(image,contours,hierachy,root=0):
'''找到符合要求的轮廓'''
rec=[]
for i in range(len(hierachy)):
child = hierachy[i][2]
child_child=hierachy[child][2]
if child!=-1 and hierachy[child][2]!=-1:
if compute_1(contours, i, child) and compute_2(contours,child,child_child):
cx1,cy1=compute_center(contours,i)
cx2,cy2=compute_center(contours,child)
cx3,cy3=compute_center(contours,child_child)
if detect_contours([cx1,cy1,cx2,cy2,cx3,cy3]):
rec.append([cx1,cy1,cx2,cy2,cx3,cy3,i,child,child_child])
'''计算得到所有在比例上符合要求的轮廓中心点'''
i,j,k=juge_angle(rec)
if i==-1 or j== -1 or k==-1:
return
ts = np.concatenate((contours[rec[i][6]], contours[rec[j][6]], contours[rec[k][6]]))
rect = cv2.minAreaRect(ts)
box = cv2.boxPoints(rect)
box = np.int0(box)
result=copy.deepcopy(image)
cv2.drawContours(result, [box], 0, (0, 0, 255), 2)
cv2.drawContours(image,contours,rec[i][6],(255,0,0),2)
cv2.drawContours(image,contours,rec[j][6],(255,0,0),2)
cv2.drawContours(image,contours,rec[k][6],(255,0,0),2)
cv2.imshow('img',image)
cv2.waitKey(0)
cv2.imshow('img',result)
cv2.waitKey(0)
return
if name == '__main__':
image=cv2.imread('1.png')
image=reshape_image(image)
cv2.imshow('start', image)
cv2.waitKey(0)
#运行后只执行到这行之前,之后就不执行了,有知道怎么解决的能帮我下吗?
contours,hierachy=detecte(image)
find(image,contours,np.squeeze(hierachy))