This tutorial is about making an Analog wall clock
synchronized with the system clock using OpenCV.
The idea
behind the Algorithm is very simple:
Decide the size of the window in which you want to draw the Analog clock.The size of the window here is 640 * 640.
Thus the centre of this window is (320,320) which is also taken as the centre of a circle
Draw a Circle (The size of the circle should be less than that of the window)
Now we need to have the markings for Hour and Seconds hands on the circumference of the circle
The coordinates of Hours and Second hand can be obtained by using circles parametric equation:
Decide the size of the window in which you want to draw the Analog clock.The size of the window here is 640 * 640.
Thus the centre of this window is (320,320) which is also taken as the centre of a circle
Draw a Circle (The size of the circle should be less than that of the window)
Now we need to have the markings for Hour and Seconds hands on the circumference of the circle
The coordinates of Hours and Second hand can be obtained by using circles parametric equation:
i.e
x=rCos(θ) ; y=rsin(θ)
Since
co-ordinates of the centre is (Cx,Cy)
Hence the
co-ordinates of the point would be
x1=Cx+rCos(θ)
y1=
Cy + rsin(θ)
Thus after getting the Co-ordinates we need to draw a line for the minute and hour marking
For the marking of an Hour hand:
We take the
radius of outer circle as:315
And Inner
Circle’s radius as :275
For the
marking of a minute hand:
We take the
radius of the outer circle as :315
And inner
circle as :275
Note: Since
12 hours corresponds to 360 degree rotation of an hour hand
Thus for an hour minute hand should rotate by
360/12=30 degree
Thus the angle, the hour hand would vary by is 30
degree
For every 30 degree rotation we have 5 minutes
Thus for each minute, the minute hand should rotate
by 30/5=6
degree
Thus the angle, the minute hand would vary by is 6
degree
180
degree = π radians
Next we
need to update our hour,minute and second hand with that of the system clock.
Here is the Code below:
#include <iostream> #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/imgproc/imgproc.hpp" #include <stdio.h> #include <ctime> #include <sys/timeb.h> using namespace std; using namespace cv; int main() { Mat clk(640,640,CV_8UC3); //Mat to store clock image Mat back_up(640,640,CV_8UC3); //Mat to store backup image Point cent(320,320); Point perim(0,0); int rad =320; float sec_angle,min_angle,hour_angle; //Draw second markings int s1[60][2]; for (int i=0; i<60; i++) for (int j=0; j<2; j++) if(j%2==0) s1[i][j]=320+295*cos(6.0*i*3.14/180) ; else s1[i][j]=320+295*sin(6.0*i*3.14/180); int s2[60][2]; for (int i=0; i<60; i++) for (int j=0; j<2; j++) if(j%2==0) s2[i][j]=320+315*cos(6.0*i*3.14/180) ; else s2[i][j]=320+315*sin(6.0*i*3.14/180); for(int i=0;i<60;i++){ line(clk,Point(s1[i][0],s1[i][1]),Point(s2[i][0],s2[i][1]), Scalar(0,255,0,0), 1.5,CV_AA,0); } //Draw hour markings int h1[12][2]; for (int i=0; i<12; i++) for (int j=0; j<2; j++) if(j%2==0) h1[i][j]=320+275*cos(30.0*i*3.14/180) ; else h1[i][j]=320+275*sin(30.0*i*3.14/180); int h2[12][2]; for (int i=0; i<12; i++) for (int j=0; j<2; j++) if(j%2==0) h2[i][j]=320+315*cos(30.0*i*3.14/180) ; else h2[i][j]=320+315*sin(30.0*i*3.14/180); for(int i=0;i<12;i++){ line(clk,Point(h1[i][0],h1[i][1]),Point(h2[i][0],h2[i][1]), Scalar(0,255,0,0), 4,CV_AA,0); } circle(clk,cent,rad-5,Scalar(0,0,255,0),4,CV_AA,0); //Draw outercircle of clock circle(clk,cent,1,Scalar(0,255,0,0),5,CV_AA,0); //Draw inner circle back_up=clk.clone(); // Clone to backup image time_t rawtime; struct tm * timeinfo; float second; float minute; float hour; float millisec; struct timeb tmb; while(1){ //Access system time and store it to a local variable ftime(&tmb); rawtime=tmb.time; timeinfo = localtime ( &rawtime ); second = timeinfo->tm_sec; minute = timeinfo->tm_min; hour = timeinfo->tm_hour; millisec = tmb.millitm; second=second+millisec/1000; sec_angle=(second*6)+270; //Convert second to angle minute=minute+second/60; min_angle=minute*6+270; //Convert minute to angle if(hour>12)hour = hour-12; hour_angle=(hour*30)+(minute*.5)+270; //Convert hour to angle if(sec_angle>360)sec_angle=sec_angle-360; if(min_angle>360)min_angle=min_angle-360; if(hour_angle>360)hour_angle=hour_angle-360; //Find out the co-ordinates in the circle perimeter for second and draw the line from center perim.x = (int)(cent.x + (rad-5) * cos(sec_angle * CV_PI / 180.0)); perim.y = (int)(cent.y + (rad-5) * sin(sec_angle * CV_PI / 180.0)); line(clk,cent,perim, Scalar(0,255,255,0), 1.5,CV_AA,0); //Find out the co-ordinates on the circle perimeter for minute and draw the line from center perim.x = (int)(cent.x + (rad-50) * cos(min_angle * CV_PI / 180.0)); perim.y = (int)(cent.y + (rad-50) * sin(min_angle * CV_PI / 180.0)); line(clk,cent,perim, Scalar(0,255,255,0), 4,CV_AA,0); //Find out the co-ordinates on the circle perimeter for hour and draw the line from center perim.x = (int)(cent.x + (rad-75) * cos(hour_angle * CV_PI / 180.0)); perim.y = (int)(cent.y + (rad-75) * sin(hour_angle * CV_PI / 180.0)); line(clk,cent,perim, Scalar(0,255,255,0), 8,CV_AA,0); imshow("Clock",clk); //Show result in a window clk.setTo(0); // set clk image to zero for next drawing clk=back_up.clone(); // Clone the previously drawned markings from back-up image char c=waitKey(10); // Wait for few millisecond and go back to loop. if(c==27)break; } return 0; }
Output: