算法背后的想法很簡單:
決定要在其中繪制模擬時鐘的窗口的大小。這里的窗口大小是 640 * 640。
因此這個窗口的中心是 (320,320)作為圓心畫一個圓(圓的大小應該小于窗口的大小)現(xiàn)在我們需要在圓的圓周上有時針和秒針的標記 時針和秒針的坐標可以通過使用圓參數(shù)方程得到:
由于中心的坐標是 (Cx,Cy)因此該點的坐標將是
x1=Cx+rCos(θ)
y1= Cy + rsin(θ)
因此,在獲得坐標后,我們需要為分鐘和小時標記畫一條線
對于時針的標記:我們?nèi)⊥鈭A半徑為:315內(nèi)圈半徑為:275
對于分針的標記:我們?nèi)⊥鈭A的半徑為:315內(nèi)圈為:275
注意:
由于 12 小時對應于時針旋轉(zhuǎn) 360 度
因此,一小時分針應旋轉(zhuǎn) 360/12=30 度
因此角度,時針會變化 30 度
每旋轉(zhuǎn) 30 度,我們有 5 分鐘
因此,每分鐘,分針應旋轉(zhuǎn) 30/5=6 度
因此,分針的角度會變化 6 度
180 度 = π 弧度 因此 θ 度= (θ*π/180) 弧度
接下來我們需要用系統(tǒng)時鐘更新我們的時針、分針和秒針。
代碼如下
#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];
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];
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], s1[i]), Point(s2[i], s2[i]), Scalar(0, 255, 0, 0), 1.5, CV_AA, 0);
}
//Draw hour markings
int h1;
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;
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], h1[i]), Point(h2[i], h2[i]), 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;
localtime_s(&timeinfo,&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;
}
效果如圖: