圖片鏈接,因為我無法上傳它> 謝謝https://github.com/HassanAdamm,我可以繼續進一步的代碼,但仍然無法使用 OpenCV 顯示正確的模擬時鐘秒針。使用 HoughLineP() 成功完成時針和分針。我無法將秒針與影像分開。以下是我的作業代碼,希望你們能幫助我!
import cv2
import math
import numpy as np
import tkinter as tk
from matplotlib import pyplot as plt
from math import sqrt, acos, degrees
# Reading the input image and convert the original RGB to a grayscale image
kernel = np.ones((5, 5), np.uint8)
img1 = cv2.imread('input1.jpg')
img = cv2.imread('input1.jpg', 0)
img_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
# Appling a binary threshold to the image
ret, thresh = cv2.threshold(img_gray, 50, 255, cv2.THRESH_BINARY)
# Create mask
height, width = img.shape
mask = np.zeros((height, width), np.uint8)
edges = cv2.Canny(thresh, 100, 200)
# Circle Detection
cimg = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img_gray, cv2.HOUGH_GRADIENT, 1.2, 100)
for i in circles[0,:]:
i[2] = i[2] 4
# cv2.cicle(image, center_coordinates, radius, color, thickness)
cv2.circle(mask, (int(i[0]),int(i[1])), int(i[2]), (255,255,255), thickness = -1)
# Copy that image using that mask
masked_data = cv2.bitwise_and(img1, img1, mask = mask)
# Apply threshold
_,thresh = cv2.threshold(mask, 1, 255, cv2.THRESH_BINARY)
# Find Contour
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
x, y, w, h = cv2.boundingRect(contours[0])
# Crop masked_data
crop = masked_data[y 30 : y h -30, x 30 : x w - 30]
height, width, channel = crop.shape
blur_crop = cv2.GaussianBlur(crop, (5, 5), 0)
edges = cv2.Canny(blur_crop, 50, 150)
# Line segments
line_image = np.copy(crop) * 0
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 15, np.array([]), 100, 10)
l = []
xl1, xl2, yl1, yl2 = 0, 0, 0, 0 #long -> l
xm1, xm2, ym1, ym2 = 0, 0, 0, 0 #medium -> m
xs1, xs2, ys1, ys2 = 0, 0, 0, 0 #short -> s
# Getting the values from the line
for line in lines:
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)
l.sort(reverse=True)
s, m, h = 0, 0, 0
for f in range(len(l)):
for line in lines:
# getting the values from the line
x1, y1, x2, y2 = line[0]
#cv2.line(crop, (x1, y1), (x2, y2), (0, 255, 0), 3)
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, (xl1, yl1), (xl2, yl2), (0, 255, 0), 5)
h = 1
break
# Calculate center point
xcenter = width/2
ycenter = height/2
# Determine the cooridnates of the end point (farther from the center)
def coordinates (x1, y1, x2, y2):
a = abs(xcenter - x1)
b = abs(xcenter - x2)
if (a > b):
x_coor = x1
y_coor = y1
else:
x_coor = x2
y_coor = y2
return x_coor, y_coor
xhour, yhour = coordinates(xs1, ys1, xs2, ys2)
xmin, ymin = coordinates(xl1, yl1, xl2, yl2)
xsec, ysec = coordinates(xl1, yl1, xl2, yl2)
cv2.line(crop, (xs1, ys1), (xs2, ys2), (0, 255, 0), 5)
# Calculate the Hour, Minute, Second-hands by the law of cosines
def law_of_cosines (x, y):
l1 = sqrt(((xcenter - x)**2) ((ycenter - y)**2))
l2 = ycenter
l3 = sqrt(((xcenter - x)**2) ((0 - y)**2))
cos_theta = ( (l1**2) (l2**2) - (l3**2) )/(2*l1*l2)
theta_radian = acos(cos_theta)
theta = math.degrees(theta_radian)
return theta
theta_hour = law_of_cosines(xhour, yhour)
theta_min = law_of_cosines(xmin, ymin)
theta_sec = law_of_cosines(xsec, ysec)
def right_or_not (x):
if (x > xcenter):
right = 1
else:
right = 0
return right
hour_right = right_or_not(xhour)
min_right = right_or_not(xmin)
sec_right = right_or_not(xsec)
def time_cal (x, y, z):
if (z == xhour):
if (x == 1):
a = int(y/30)
else:
a = 12 - int(y/30)
if a == 0:
a = 12
else:
if (x == 1):
a = int(y/6)
else:
a = 60 - int(y/6)
if (z == xcenter):
a = 30
return a
hour = time_cal(hour_right, theta_hour, xhour)
minute = time_cal(min_right, theta_min, xmin)
sec = time_cal(sec_right, theta_sec, xsec)
# Display window
canvas = tk.Tk()
canvas.title("Analog to Digital")
canvas.geometry("500x250")
digit = tk.Label(canvas, font = ("ds-digital", 65, "bold"), bg = "white", fg = "blue", bd = 80)
digit.grid(row = 0, column = 1)
# Display result
def display(hour, minute, sec):
value = "{0:0=2d}:{1:0=2d}:{2:0=2d}".format(hour, minute, sec)
digit.config(text=value)
print(value)
display(hour, minute, sec)
canvas.mainloop()
for line in lines:
for x1,y1,x2,y2 in line:
cv2.line(line_image, (x1,y1), (x2,y2), (255,0,0), 1)
lines_edges = cv2.addWeighted(crop, 0.8, line_image, 1, 0)
cv2.imshow('Line Image', line_image)
cv2.imshow('Crop', crop)
cv2.waitKey(0)
uj5u.com熱心網友回復:
這種事情有很多可能的陷阱。因為每只手生成兩條線,但并不完全平行,并且某些互動可能會使它們顯得更短,等等。
但在你的情況下,我敢打賭問題要簡單得多:
xhour, yhour = coordinates(xs1, ys1, xs2, ys2)
xmin, ymin = coordinates(xl1, yl1, xl2, yl2)
xsec, ysec = coordinates(xl1, yl1, xl2, yl2)
我很確定,其中之一應該是coordinates(xm1, ym1, xm2, ym2)
在您發表評論后進行編輯。所以,我們處在一個更糟糕的地方。因為您所擁有的是計算機視覺問題,而不僅僅是 python 問題。對此沒有明確的解決方案。但是,您可以做一些提示。
- 您可以確定時鐘的中心(我認為您已經完成了,畫了一個圓圈),并且還使用到中心的距離而不是線的長度。
- 您可以利用它來過濾不通過中心或幾乎不通過中心的線
- 由于線條是手的邊界,并且是略微三角形的,因此它們與中心的距離有多近表明它是哪只手。時針和分針的線并不完全穿過圓的中心。秒針線更靠近中心。
- 此外,您應該期望每手至少有 2 行(實際上更多,這就是霍夫的作業方式)。一個在中心上方,另一個在下方。因此,您可以利用它來增強角度計算(通過計算穿過中心的中線)和長度計算的可靠性。避免用同一只手數兩次
- 此外,您可以計算所有線的角度:如果有 3 個明顯分開的角度,您就知道您正在尋找的所有角度都在那里。長針的分針和秒針(您可以區分它們,因為我們的小時更三角形和更粗的形狀,而秒針的形狀更窄。這導致小時的線條方向變化比秒的更大)。短時針。
- 您也可以嘗試利用秒針的“尾巴”,并嘗試檢查是否在與指標相反的方向上發現了一些暗像素。如果你不這樣做,它就不是二手的。
- 您還可以使用形態學運算子,在 canny/hough 之前侵蝕黑色像素。這樣你就知道秒針已經消失了,因為它太窄了。你會從那里找到兩只手。然后在沒有腐蝕的情況下重做這項作業。你發現的多余的手是秒針
- 當然,也有一些手疊加處理的情況。如果你確信,在嘗試了一些想法之后,如果有 3 手牌,你會找到 3 手牌,那么,你可以相信 2 手牌在同一個位置。您還可以使用您之前檢測的知識(您知道手應該如何移動)
- 最后,如果你不是特別想只使用線檢測,你也可以簡單地觀察一些圓圈上的像素。一個圓心是時鐘的中心,其半徑盡可能大但不足以包括數字,應該用兩只手(小時和秒)交叉,很容易發現那個(分鐘)比另一個(秒)厚。如果只有一個,那么您知道小時和秒是相同的。較小的圓圈應由 3 只手交叉。額外的一個是時針。如果找不到額外的,并且有 2 根指標(與大圓圈相同),則時針與分針或秒針重疊。如果是二手的,那么它應該會變得更厚。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/514733.html
標籤:Python图片麻木的
