畫好了輪廓之後(關於畫輪廓的內容),我們需要做的是把時針,分針,秒針畫出來,單純地畫出來其實也很簡單,只要確定終點就行了,起點就是圓心。
先看效果圖:
Talk is cheap,show you the code.
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<time.h>
#include<sys/timeb.h>
#include<sys\utime.h>
using namespace cv;
int main()
{
Mat clock_background(500, 500, CV_8UC3, Scalar::all(0));//創一個背景
int radius = clock_background.cols / 2;//設半徑
Point center(clock_background.cols / 2, clock_background.rows / 2);//設圓心
circle(clock_background, center, radius, Scalar(255, 100, 0), 1, 8, 0);//畫時鐘外輪廓
circle(clock_background, center, 5, Scalar(0, 0, 255), -1, 8, 0);//畫圓心
Point second_begin, second_end;//設刻度的起點,終點
int scale_long = 10;//刻度的長度
int scale_width = 2;//刻度的寬度
//畫一個背景
for (int second_Scale = 0; second_Scale < 60; second_Scale++)
{
if (second_Scale % 5 == 0)//每五個刻度就變長度,也就是整點1,2,3,···,12這些數字對應的刻度長一點
{
scale_long = 20;
scale_width = 5;
}
else
{
scale_long = 10;
scale_width = 2;
}
second_begin.x = center.x + radius * cos(6 * second_Scale* CV_PI / 180);//刻度的起點x座標賦值
second_begin.y = center.y + radius * sin(6 * second_Scale* CV_PI / 180);//刻度的起點y座標賦值
second_end.x = center.x + (radius - scale_long) * cos(6 * second_Scale* CV_PI / 180);//刻度的終點x座標賦值
second_end.y = center.y + (radius - scale_long) * sin(6 * second_Scale* CV_PI / 180);//刻度的終點y座標賦值
line(clock_background, second_begin, second_end, Scalar(50, 205, 50), scale_width);//連接起點終點
}
int secong_hand_long = radius*0.9, min_hand_long= radius*0.7, hour_hand_long= radius*0.5;//秒針,分針,時針的長度設置
Point secong_hand_end, min_hand_end, hour_hand_end;//秒針分針時針的終點
Mat clk = clock_background.clone();//新建一個clk刷新
float seconds, min, hour, millisec;//秒,分,時,更精確的秒(千分之一秒)
time_t time_seconds = time(0);
struct tm now_time;
struct timeb tmb;
while (1)
{
//獲取系統時間
ftime(&tmb);
time_seconds = tmb.time;
localtime_s(&now_time, &time_seconds);
seconds = (float)now_time.tm_sec;//系統時鐘賦值給 seconds
min = (float)now_time.tm_min;//系統時鐘賦值給 min
hour = (float)now_time.tm_hour;//系統時鐘賦值給 hour
millisec = tmb.millitm;//
printf_s("s=%f\t", seconds);
printf_s("m=%f\t", min);
printf_s("h=%f\t", hour);
seconds = seconds + millisec / 1000;
min = min + seconds / 60.0;
if (hour > 12) hour = hour - 12;
hour = hour + min / 60.0;
//秒針
secong_hand_end.x = (int)(center.x + (float)secong_hand_long * cos(3 * CV_PI / 2 + seconds * CV_PI / 30));
secong_hand_end.y = (int)(center.y + (float)secong_hand_long * sin(3 * CV_PI / 2 + seconds * CV_PI / 30));
line(clk, center, secong_hand_end, Scalar(147, 231, 255), 1.5, CV_AA, 0);
//分針
min_hand_end.x = (int)(center.x + min_hand_long * cos(3*CV_PI/2+min*CV_PI/30));
min_hand_end.y = (int)(center.y + min_hand_long * sin(3*CV_PI/2+min*CV_PI/30));
line(clk, center, min_hand_end, Scalar(147, 231, 255), 4, CV_AA, 0);
//時針
hour_hand_end.x = (int)(center.x + hour_hand_long * cos(3*CV_PI/2+hour*CV_PI/6));
hour_hand_end.y = (int)(center.y + hour_hand_long * sin(3*CV_PI/2+hour*CV_PI/6));
line(clk, center, hour_hand_end, Scalar(147, 231, 255), 12, CV_AA, 0);
imshow("clock", clk);
clk.setTo(0);
clk = clock_background.clone();
waitKey(1000);//這裏如果參數爲10,則看到的是秒針連續地轉動;如果是1000,則效果是秒針一秒一秒地跳動
}
到了這裏,其實主要是獲取到的秒,分,時看你怎麼用,把它的具體數值轉換成角度,再根據角度寫出終點的座標即可實現。
一開始寫代碼的時候我也是隻獲取系統的時分秒,沒有精確到小數點後的,也就是得到 1秒,2秒,3秒。這樣的效果導致時針分針不會根據實際時間變化,什麼意思呢?
比如說時間 17時23分12秒,
時針直直的指在數字5,分針指在23,秒針指在12,
還不明白?看看現實的鐘你會發現。除了五點整之外,時針還會直直的指在5那裏嗎?
然後再對比下 @冰不語 的代碼,發現它還獲取了 比如說 1.213秒這麼高精確度的秒數,然後我也加上,就可以實現了。
同時,我個人嘗試過編譯@冰不語 的代碼 @冰不語的文章,但是會有錯誤,同時他的博客下面也有人提出了,和我遇到一樣的錯誤。我去嘗試按照 評論的方法修改,仍然不行,最終我找到了解決方法,如果有小夥伴也遇到了可以下載附件看一看,對比對比,其實錯誤原因是獲取高精確度的秒數導致的。 附件裏包含了:原作者的代碼,@冰不語的代碼,和我自己的代碼。