虽然OpenCV的绘图函数不少时候能帮上忙,它们毕竟终究只是配角。直到看到外国友人的一篇blog,我沉默了。
将其代码拿出来跑效果是这样的(.gif):
只能说,人有多大胆,地有多大产。
其实实现方法也很简单,调用系统的时间,利用三角函数转化成角度,再用OpenCV的绘图函数将钟画出来,更准确地说,是一帧一帧把指针画上去,画一遍擦一遍。
以下是代码,供参考:
#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/imgproc/imgproc.hpp"
#include <stdio.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/time.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(320,0);
int rad =320;
float sec_angle=270;
float min_angle=330;
float hour_angle=210;
//Draw second markings
int s1[60][2]={{320,25},{351,27},{381,31},{411,39},{440,51},{468,65},{493,81},{517,101},{539,123}, \
{559,147},{575,173},{589,200},{601,229},{609,259},{613,289},{615,320},{613,351},{609,381},{601,411}, \
{589,440},{575,468},{559,493},{539,517},{517,539},{493,559},{468,575},{440,589},{411,601},{381,609}, \
{351,613},{320,615},{289,613},{259,609},{229,601},{200,589},{173,575},{147,559},{123,539},{101,517}, \
{81,493},{65,468},{51,440},{39,411},{31,381},{27,351},{25,320},{27,289},{31,259},{39,229},{51,200}, \
{65,173},{81,147},{101,123},{123,101},{147,81},{172,65},{200,51},{229,39},{259,31},{289,27},};
int s2[60][2]={{320,5},{353,7},{385,12},{417,20},{448,32},{478,47},{505,65},{531,86},{554,109}, \
{575,135},{593,163},{608,192},{620,223},{628,255},{633,287},{635,320},{633,353},{628,385},{620,417}, \
{608,448},{593,478},{575,505},{554,531},{531,554},{505,575},{478,593},{448,608},{417,620},{385,628}, \
{353,633},{320,635},{287,633},{255,628},{223,620},{192,608},{163,593},{135,575},{109,554},{86,531}, \
{65,505},{47,478},{32,448},{20,417},{12,385},{7,353},{5,320},{7,287},{12,255},{20,223},{32,192}, \
{47,163},{65,135},{86,109},{109,86},{135,65},{162,47},{192,32},{223,20},{255,12},{287,7}};
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]={{320,45},{458,82},{558,183},{595,320},{558,458},{458,558},{320,595},{183,558}, \
{82,458},{45,320},{82,183},{182,82}};
int h2[12][2]={{320,5},{478,47},{593,163},{635,320},{593,478},{478,593},{320,635},{163,593}, \
{47,478},{5,320},{47,163},{162,47}};
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); //Dreaw 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 to 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; //Conver minute to angle
if(hour>12)hour = hour-12;
hour_angle=(hour*30)+(minute*.5)+270; //Conver 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;
//Fond out the co-ordinates in the circle perimeter for second and draw the line from center
perim.x = (int)round(cent.x + (rad-5) * cos(sec_angle * CV_PI / 180.0));
perim.y = (int)round(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);
//Fond out the co-ordinates on the circle perimeter for minute and draw the line from center
perim.x = (int)round(cent.x + (rad-50) * cos(min_angle * CV_PI / 180.0));
perim.y = (int)round(cent.y + (rad-50) * sin(min_angle * CV_PI / 180.0));
line(clk,cent,perim, Scalar(0,255,255,0), 4,CV_AA,0);
//Fond out the co-ordinates on the circle perimeter for hour and draw the line from center
perim.x = (int)round(cent.x + (rad-75) * cos(hour_angle * CV_PI / 180.0));
perim.y = (int)round(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;
}