You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
5.3 KiB
149 lines
5.3 KiB
import sys
|
|
import random
|
|
import cv2
|
|
import numpy as np
|
|
import matplotlib.pyplot as plt
|
|
|
|
|
|
def clock_identify(img_path):
|
|
clock = cv2.imread(img_path, 1) # 读取图片
|
|
|
|
# 0、高斯滤波去噪
|
|
clock = cv2.GaussianBlur(clock, (5, 5), 0, 0)
|
|
cv2.imwrite('./output/mid1.jpg', clock)
|
|
# 1、灰度化
|
|
GrayImage = cv2.cvtColor(clock, cv2.COLOR_BGR2GRAY)
|
|
cv2.imwrite('./output/mid2.jpg', GrayImage)
|
|
# 2、Roberts边缘提取
|
|
kernelx = np.array([[-1, 0], [0, 1]], dtype=int)
|
|
kernely = np.array([[0, -1], [1, 0]], dtype=int)
|
|
x = cv2.filter2D(GrayImage, cv2.CV_16S, kernelx)
|
|
y = cv2.filter2D(GrayImage, cv2.CV_16S, kernely)
|
|
absX = cv2.convertScaleAbs(x)
|
|
absY = cv2.convertScaleAbs(y)
|
|
Roberts = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
|
|
cv2.imwrite('./output/mid3.jpg', Roberts)
|
|
# 3、二值化
|
|
for i in range(0, Roberts.shape[0]):
|
|
for j in range(0, Roberts.shape[1]):
|
|
if Roberts[i][j] >= 30:
|
|
Roberts[i][j] = 255
|
|
else:
|
|
Roberts[i][j] = 0
|
|
cv2.imwrite('./output/mid4.jpg', Roberts)
|
|
# 4、霍夫直线检测
|
|
linesP = cv2.HoughLinesP(image=Roberts, rho=1, theta=np.pi / 180, threshold=150, minLineLength=clock.shape[0] / 6,
|
|
maxLineGap=10) # (在canny边缘检测的结果上进行边缘链接)
|
|
|
|
for i_P in linesP:
|
|
for x1, y1, x2, y2 in i_P:
|
|
cv2.line(clock, (x1, y1), (x2, y2), (0, 0, 255), 3)
|
|
|
|
# 5、霍夫圆检测
|
|
circlesP = cv2.HoughCircles(image=Roberts, method=cv2.HOUGH_GRADIENT, dp=2, minDist=500, param1=100, param2=100,
|
|
minRadius=200, maxRadius=500)
|
|
circlesP = circlesP.reshape(-1, 3)
|
|
circlesP = np.uint16(np.around(circlesP))
|
|
|
|
print(circlesP)
|
|
for i in circlesP:
|
|
cv2.circle(clock, (i[0], i[1]), i[2], (0, 0, 255), 5) # 画圆
|
|
cv2.imwrite('./output/clock.jpg', clock)
|
|
cv2.imwrite('./output/edge.jpg', Roberts)
|
|
|
|
def getDist(point1, point2):
|
|
return np.sqrt((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2)
|
|
|
|
def angle(v1, v2):
|
|
cosvalue = (v1[0] * v2[0] + v1[1] * v2[1]) / (
|
|
np.sqrt(v1[0] ** 2 + v1[1] ** 2) * np.sqrt(v2[0] ** 2 + v2[1] ** 2))
|
|
return np.arccos(cosvalue)
|
|
|
|
def isSimilar(line1, line2, center):
|
|
nearpoint1 = [line1[0], line1[1]]
|
|
farpoint1 = [line1[2], line1[3]]
|
|
nearpoint2 = [line2[0], line2[1]]
|
|
farpoint2 = [line2[2], line2[3]]
|
|
if getDist(nearpoint1, center) > getDist(farpoint1, center):
|
|
nearpoint1, farpoint1 = farpoint1, nearpoint1
|
|
if getDist(nearpoint2, center) > getDist(farpoint2, center):
|
|
nearpoint2, farpoint2 = farpoint2, nearpoint2
|
|
vector1 = [farpoint1[0] - nearpoint1[0], farpoint1[1] - nearpoint1[1]]
|
|
vector2 = [farpoint2[0] - nearpoint2[0], farpoint2[1] - nearpoint2[1]]
|
|
if angle(vector1, vector2) < 0.09:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
line_group = [[], [], []]
|
|
center = [circlesP[0][0], circlesP[0][1]]
|
|
print(center)
|
|
for i_P in linesP:
|
|
for group in line_group:
|
|
if len(group) == 0:
|
|
group.append(i_P[0])
|
|
break
|
|
else:
|
|
if (isSimilar(i_P[0], group[0], center)):
|
|
group.append(i_P[0])
|
|
break
|
|
|
|
for group in line_group:
|
|
for line in group:
|
|
print(line)
|
|
print("--------------")
|
|
|
|
def getAvgLength(group):
|
|
ans = 0
|
|
for line in group:
|
|
ans = ans + getDist([line[0], line[1]], [line[2], line[3]])
|
|
return ans / len(group)
|
|
|
|
def getAngle(line):
|
|
nearpoint = [line[0], line[1]]
|
|
farpoint = [line[2], line[3]]
|
|
if getDist(nearpoint, center) > getDist(farpoint, center):
|
|
nearpoint, farpoint = farpoint, nearpoint
|
|
vector = [farpoint[0] - nearpoint[0], farpoint[1] - nearpoint[1]]
|
|
if vector[0] == 0 and vector[1] > 0:
|
|
return np.pi
|
|
if vector[0] > 0 and vector[1] > 0:
|
|
return np.pi / 2 + np.arctan(vector[1] / vector[0])
|
|
if vector[0] > 0 and vector[1] == 0:
|
|
return np.pi / 2
|
|
if vector[0] > 0 and vector[1] < 0:
|
|
return np.arctan(vector[0] / (-vector[1]))
|
|
if vector[0] == 0 and vector[1] < 0:
|
|
return 0
|
|
if vector[0] < 0 and vector[1] < 0:
|
|
return 2 * np.pi - np.arctan((-vector[0]) / (-vector[1]))
|
|
if vector[0] < 0 and vector[1] == 0:
|
|
return 1.5 * np.pi
|
|
if vector[0] < 0 and vector[1] > 0:
|
|
return np.pi + np.arctan((-vector[0]) / vector[1])
|
|
|
|
class pointer:
|
|
def __init__(self, group):
|
|
self.length = getAvgLength(group)
|
|
self.angle = getAngle(group[0])
|
|
|
|
clockhands = []
|
|
for group in line_group:
|
|
clockhands.append(pointer(group))
|
|
|
|
clockhands.sort(key=lambda x: x.length)
|
|
|
|
hour = (clockhands[0].angle / (2 * np.pi)) * 12
|
|
minites = (clockhands[1].angle / (2 * np.pi)) * 60
|
|
seconds = (clockhands[2].angle / (2 * np.pi)) * 60
|
|
seconds = int(seconds)
|
|
minites = int(minites)
|
|
hour = int(hour)
|
|
|
|
with open('./output/time.txt', 'w') as f:
|
|
f.write("识别出来的时间为: " + str(hour) + ":" + str(minites) + ":" + str(seconds))
|
|
f.close()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
clock_identify(sys.argv[1]) |