Reading analog clock using opencv

I tried to read the analog clock image and display the time using the digital image using the opencv python, I have done for reading the hours and minutes by separating the hours and minutes hand from the image using HoughLineP() using opencv but I am unable to separate the seconds hand from the image, Here is the code I am working with Please help me to separate the Seconds hand and to read the seconds values

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()

In the above code in nested for loop i have separated the x1,x2,y1,y2 coordinate of the mintues hand and hours hands too but now i need to do the same separation to get the x1,x2,y1,y2 for the seconds hands to I didn’t get any idea for making it kindly help me with it

please put your code here , not a link to your colab (which will no more be there tomorrow, and render your question useless), thank you.

related:

I am the one who asked that question in stackoverflow But i didn’t get proper answer there

again, please try to improve your question here

Check my code and sample image now

maybe a complete different approach ? you could warpPolar() it similar to this:

from there on it’s just sampling vertical lines in some places

Yaa i gone through this but it seems confusing

you can overcome your confusion. it’s a very simple and robust approach, better than any of that Hough transform nonsense they suggested over on SO.