画好了轮廓之后(关于画轮廓的内容),我们需要做的是把时针,分针,秒针画出来,单纯地画出来其实也很简单,只要确定终点就行了,起点就是圆心。
先看效果图:
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秒这么高精确度的秒数,然后我也加上,就可以实现了。
同时,我个人尝试过编译@冰不语 的代码 @冰不语的文章,但是会有错误,同时他的博客下面也有人提出了,和我遇到一样的错误。我去尝试按照 评论的方法修改,仍然不行,最终我找到了解决方法,如果有小伙伴也遇到了可以下载附件看一看,对比对比,其实错误原因是获取高精确度的秒数导致的。 附件里包含了:原作者的代码,@冰不语的代码,和我自己的代码。