python - 使用opencv python读取模拟时钟图像并显示时间
问题描述
我尝试使用opencv python读取模拟时钟图像并使用数字图像显示时间,我已经通过使用opencv使用HoughLineP()将时针和分针与图像分开来读取小时和分钟,但我无法将秒针与图像分开,这是我正在使用的代码请帮助我将秒针分开并读取秒值
import cv2
import math
import numpy as np
import matplotlib.pyplot as plt.
from math import sqrt, acos, degrees
import tkinter as tk
kernel = np.ones((5,5),np.uint8)
img = cv2.imread('input3.jpg')
ret, thresh = cv2.threshold(gray_img, 50, 255, cv2.THRESH_BINARY)
height, width = gray_img.shape
mask = np.zeros((height,width), np.uint8)
edges = cv2.Canny(thresh, 100, 200)
cimg=cv2.cvtColor(gray_img, cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(gray_img, cv2.HOUGH_GRADIENT, 1.2, 100)
for i in circles[0,:]:
# print(i) # -> [429.00003 240.6 226.20001]
i[2] = i[2] + 4
# used to detect the circle in the image
cv2.circle(mask, (int(i[0]), int(i[1])), int(i[2]), (255,255,255), thickness=-1)
masked_data = cv2.bitwise_and(img, img, mask=mask)
_,thresh = cv2.threshold(mask,1,255,cv2.THRESH_BINARY)
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
# Crop masked_data
crop = masked_data[y + 30 : y + h - 30, x + 30 : x + w - 30
i=crop
height, width, channels = i.shape
ret, mask = cv2.threshold(i, 10, 255, cv2.THRESH_BINARY)
edges = cv2.Canny(i,100,200)
kernel = np.ones((11,11),np.uint8)
kernel1 = np.ones((13,13),np.uint8)
edges = cv2.dilate(edges,kernel,iterations = 1)
edges = cv2.erode(edges,kernel1,iterations = 1)
minLineLength = 1000
maxLineGap = 10
lines = cv2.HoughLinesP(edges,
1,
np.pi/180,
15,
minLineLength,
maxLineGap)
l=[]
# l -> long, s -> short
xl1, xl2, yl1, yl2 = 0, 0, 0 , 0
xs1, xs2, ys1, ys2=0, 0, 0 , 0
for line in lines:
# getting the values from the line
x1, y1, x2, y2 = line[0]
dx = x2 - x1
if(dx<0):
dx = dx * -1
dy = y2 - y1
if(dy < 0):
dy = dy * -1
hypo = sqrt(dx ** 2 + dy ** 2 )
l.append(hypo)
a=len(l) # -> 295
l.sort(reverse=True)
m=0
h=0
for f in range(a):
for line in lines:
# getting the values from the line
x1, y1, x2, y2 = line[0]
dx = x2 - x1
if(dx < 0):
dx = dx * -1
dy = y2 - y1
if(dy < 0):
dy = dy * -1
hypo2 = sqrt(dx ** 2 + dy ** 2 )
if(hypo2 == l[0]):
m = hypo2
xl1 = x1
xl2 = x2
yl1 = y1
yl2 = y2
# getting line region
cv2.line(crop, (xl1, yl1), (xl2, yl2), (255, 0, 0), 3)
if(m==l[0]):
if(hypo2 ==l[f]):
if((sqrt((xl2 - x2)**2 + (yl2 - y2)**2)) > 20):
if((sqrt((xl1 - x1)**2 + (yl1 - y1)**2))>20):
xs1 = x1
xs2 = x2
ys1 = y1
ys2 = y2
# getting line region
cv2.line(crop, (xs1, ys1), (xs2, ys2), (0, 255, 0), 3)
h=1
break
if(h==1):
break
xcenter = int(width / 2)
ycenter = int(height / 2)
hour1 = abs(xcenter - xs1)
hour2 = abs(xcenter - xs2)
if(hour1 > hour2):
xhour = xs1
yhour = ys1
else:
xhour = xs2
yhour = ys2
min1 = abs(xcenter - xl1)
min2 = abs(xcenter - xl2)
if(min1 > min2):
xmin = xl1
ymin = yl1
else:
xmin = xl2
ymin = yl2
l1 = sqrt( ((xcenter - xhour) ** 2) + ((ycenter - yhour) ** 2) )
l2 = ycenter
l3 = sqrt( ((xcenter - xhour) ** 2) + ((0 - yhour) ** 2) )
cos_theta_hour = ( ( (l1) ** 2 ) + ( (l2) ** 2 ) - ( (l3) ** 2) ) / ( 2 * (l1) * (l2) )
theta_hours_radian = acos(cos_theta_hour)
theta_hours = math.degrees(theta_hours_radian)
if(xhour > xcenter):
right=1
else:
right=0
if(right==1):
hour = int(theta_hours / (6*5))
if(right==0):
hour = 12 - (int(theta_hours / (6*5)))
if(hour==0):
hour=12
l1 = sqrt( ((xcenter - xmin) ** 2) + ((ycenter - ymin) ** 2) )
l2 = ycenter
l3 = sqrt( ((xcenter - xmin) ** 2) + ((0 - ymin) ** 2) )
cos_theta_min = ( ( (l1) ** 2 ) + ( (l2) ** 2 ) - ( (l3) ** 2) ) / ( 2 * (l1) * (l2) )
theta_min_radian = acos(cos_theta_min)
theta_min = math.degrees(theta_min_radian)
if(xmin > xcenter):
right=1
else:
right=0
if(right==1):
minute = int(theta_min / ((6*5)/5))
if(right==0):
minute = 60 - (int(theta_min / ((6*5)/5)))
if(xmin == xcenter):
minutes=30
if (minute < 10):
def display():
value = "{}:0{}".format(hour,minute)
digit.config(text = value)
else:
def display():
value = "{}:{}".format(hour,minute)
digit.config(text = value)
canvas = tk.Tk()
canvas.title("Analog to Digital")
canvas.geometry("300x250")
digit = tk.Label(canvas, font=("ds-digital", 65, "bold"), bg="black", fg="blue", bd = 80)
digit.grid(row=0, column = 1)
display()
canvas.mainloop()
解决方案
考虑到您检索小时和分钟值的方法是成功的,这里有一个查找秒值的简单解决方案。与时钟图像的二手
相关的某些属性需要在估算其值之前进行一些准备。第一个是颜色。因为手是红色的,所以你有一个很好的引导点将它与图像的其余部分分开。如果您可以使用该功能掩盖图像中二手的红色(在此处阅读更多信息),您将只剩下一个干净的二手图像。之后,您可以使用将其转换为黑白cv2.inRange()
cv2.cvtColor()
功能。现在,第二个问题可能是二手的细线。您可以使用Morphological Transformations解决这个问题。使用Erosion _ 功能,您可以扩大图像的白色区域并加厚二手。之后,使用您使用的任何方法来查找分针和时针的值,您就可以开始了。
推荐阅读
- flutter - Flutter无法以颜色显示字符串颜色代码
- python - 如何在 for 循环中编写 json 文件?
- javascript - D3 on("点击", 切换
- flutter - 键盘出现在 Flutter HTML 编辑器 -FLUTTER 的前面
- javascript - 为什么我的 Google App 脚本自动刷新代码不起作用?
- tinymce-3 - 如何在 Tinymce3.0 中设置默认字体和字体大小?
- java - 在 Android Studio 中获取按钮以执行操作
- android - 更改 gaddle 的 appId 时奇怪的 Android 颜色行为
- elasticsearch - 如何在 Elasticsearch 中将 id 设置为文档的唯一值
- macos - 使用 com.apple.developer.driverkit.userclient-access 配置配置文件应该如何?