本程序的思路是:
1.利用模板匹配找到目标图片中的钟表
2. 将目标图片中的钟表截取下来,利用cv2.HoughCircles()把钟表的圆形轮廓,圆半径,圆心识别出来
3.利用cv2.HoughLinesP函数找圆形轮廓中的直线,根据指针与圆心的关系,即过圆心的直线就是钟表指针这个判断条件减小一些误差
4.最后计算得到的直线斜率可知直线的度数,然后可设计一个公式将度数与钟表刻度进行转换(我还没做,做完再更新吧)
注意:
本程序其实极其简陋,精确度极差!!!!!
import cv2
import numpy
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('demo/1.jpg')
target = cv2.imread('demo/11.jpg')
th, tw = target.shape[:2]
# 进行模板匹配
result = cv2.matchTemplate(target, img, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
tl = min_loc
br = (tl[0] + tw, tl[1] + th)
# 绘制矩形
cv2.rectangle(img, tl, br, (0, 0, 255), 2)
img = img[tl[1] + 2:tl[1] + th - 2, tl[0] + 2:tl[0] + tw - 2]
grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯滤波,中值滤波
grey = cv2.GaussianBlur(grey, (3, 3), 0)
# 轮廓检测
_, th = cv2.threshold(grey, 0, 255, cv2.THRESH_TOZERO + cv2.THRESH_OTSU)
edges = cv2.Canny(th, 50, 125)
# 膨胀 腐蚀
# element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# edges = cv2.erode(edges, element)
# edges = cv2.dilate(edges, element)
# 找圆
circles1 = cv2.HoughCircles(grey, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=30, minRadius=15, maxRadius=80)
circles = circles1[0, :, :]
circles = np.uint16(np.around(circles))
for i in circles[:]:
cv2.circle(grey, (i[0], i[1]), i[2], (0, 255, 0), 3) # 画圆
cv2.circle(grey, (i[0], i[1]), 2, (255, 255, 255), 10) # 画圆心
minLineLength = 100
maxLineGap = 32
# 找直线
lines = cv2.HoughLinesP(edges, 1.0, np.pi / 180, 20, minLineLength, maxLineGap)
for line in lines:
for x1, y1, x2, y2 in line:
if not ((x2 - i[0]) ^ 2 + (y2 - i[1]) ^ 2) > i[2] ^ 2: # 在圆以外的直线不考虑
if (x1 - i[0]) / (y1 - i[1]) - (x2 - i[0]) / (y2 - i[1]) <= 1: # 找与圆心在一条直线上的直线,即尽可能排除指针以外的干扰
cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 1)
x1 = float(x1)
x2 = float(x2)
y1 = float(y1)
y2 = float(y2)
# 计算斜率
if x2 - x1 == 0:
print("直线是竖直的")
result = 90
elif y2 - y1 == 0:
print("直线是水平的")
result = 0
else:
k = -(y2 - y1) / (x2 - x1)
# 求反正切,再将得到的弧度转换为度
result = np.arctan(k) * 57.29577
print("直线倾斜角度为:" + str(result) + "度")
cv2.namedWindow("img", 0)
cv2.namedWindow("img1", 0)
cv2.imshow("img", edges)
cv2.imshow("img1", img)
cv2.waitKey(0)
cv2.destroyAllWindows()