OpenCV实践之路——画出时钟并动态同步系统时间

55 篇文章 205 订阅
45 篇文章 6 订阅

本文并非原创,是在外网上看到的一个实例。原文参见Clock。不是翻译,也不是转载,只是自己实现了下,一点小记录。代码略有改动。

过程大致分为两步:第一步,画出时钟;第二步,同步系统时间。其中第一步是跟opencv相关,第二步不太了解,不作过多记录。

一个简单的时钟就是线段和圆的组合。包括最外围的圆,60根刻度线(其中12根整点刻度线)和时针分针秒针三根长的线段。

画圆最简单:创建一个长宽相等的图片,以图片中心为中心,以一半的图片长宽为半径画圆即可。

画线段就相对麻烦许多,因为一共要画60+12+3=75根线段。opencv的画线函数line()需要知道线段的起始点,而我们需要画的75根直线的起始点各不相同,我们需要一一计算出来。如果我们的圆是以我们数学上的笛卡尔坐标系的原点为中心,以r为半径画的圆,大概就是下面这样:



已知角度α的情况下我们可以很容易算到P点的坐标:

x =  r * cos(α)

y = r * sin(α)

但是我们知道opencv中图像的坐标原点在左上角,那么我们可以变化下坐标系,得到下面的公式:

x = r + r * cos(α)

y = r + r * sin(α)

一分钟60秒,秒针刻度就是把外围的圆60等分,每两个刻度的夹角是6度。同理整点刻度就是把圆12等分,夹角为30度。

我们可以用半径相差不大的一大一小两个圆来算出每一根刻度线的起始点坐标,然后就可以用line()画出它们了。整点刻度同理。

画出刻度线之后获取系统时间,然后根据时间实时画出时针分针秒针。这一部分不太了解,就不多说了。代码如下:

#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>
#include<sys\utime.h>

using namespace std;
using namespace cv;

int main()
{
	Mat clk(640, 640, CV_8UC3,Scalar(180,120,50)); //Mat to store clock image
	Mat back_up(640, 640, CV_8UC3, Scalar(180, 120, 50)); //Mat to store backup image

	Point cent(clk.rows/2, clk.cols/2);
	Point perim(clk.cols/2, 0);
	int rad = clk.cols / 2;
	float sec_angle = 270;
	float min_angle = 330;
	float hour_angle = 210;

<span style="white-space:pre">	</span>//画秒针刻度
	vector<Point> pt1,pt2;
	for (int i = 0; i < 60; i++)
	{
		int x1 = cent.x + rad*cos(i * 6 * CV_PI / 180.0);
		int y1 = cent.y + rad*sin(i * 6 * CV_PI / 180.0);
		pt1.push_back(Point(x1, y1));

		int x2 = cent.x + (rad - 20)*cos(i * 6 * CV_PI / 180.0);
		int y2 = cent.y + (rad - 20)*sin(i * 6 * CV_PI / 180.0);
		pt2.push_back(Point(x2, y2));

		line(clk, pt1[i], pt2[i], Scalar(0, 255, 0, 0), 1.5, CV_AA, 0);
	}
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>//画整点刻度
	vector<Point> pt3,pt4;
	for (int i = 0; i < 12; i++)
	{
		int x3 = cent.x + (rad - 40)*cos(i * 30 * CV_PI / 180.0);
		int y3 = cent.y + (rad - 40)*sin(i * 30 * CV_PI / 180.0);
		pt3.push_back(Point(x3, y3));

		line(clk, pt1[(i*5)], pt3[i], Scalar(0, 255, 0, 0), 5, CV_AA, 0);
	}
<span style="white-space:pre">	</span>//画最外围的圆和圆心的三针连接点
	circle(clk, cent, rad, Scalar(50, 50, 255, 0), 6, CV_AA, 0); //Dreaw outercircle of clock
	circle(clk, cent, 2, 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){
		//获取本地时间
		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;

		//画秒针
		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);


		//画分针
		perim.x = (int)round(cent.x + (rad - 30) * cos(min_angle * CV_PI / 180.0));
		perim.y = (int)round(cent.y + (rad - 30) * sin(min_angle * CV_PI / 180.0));
		line(clk, cent, perim, Scalar(0, 255, 255, 0), 4, CV_AA, 0);


		//画时针
		perim.x = (int)round(cent.x + (rad - 100) * cos(hour_angle * CV_PI / 180.0));
		perim.y = (int)round(cent.y + (rad - 100) * sin(hour_angle * CV_PI / 180.0));
		line(clk, cent, perim, Scalar(0, 255, 255, 0), 12, 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(999); // 这里如果参数为10,则看到的是秒针连续地转动;如果是1000,则效果是秒针一秒一秒地跳动
		if (c == 27)break;
	}

	return 0;
}



11:24,正是现在的时间。


2016年3月3日添加动态图:




  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
opencv是一个开源的计算机视觉库,opencv2.4.9是其中的一个版本。在opencv2.4.9中,有一个模块叫做stitching,用于图像拼接。 图像拼接是将多张图像按照一定的顺序和方式进行合并,形成一张更大视野覆盖范围的图像。拼接的过程需要解决图像间的重叠区域匹配、图像变换与叠加等问题。 在opencv2.4.9的stitching模块中,主要有以下几个重要的类: 1. Stitcher类:拼接器类,用于执行拼接的主要操作。它提供了一系列的方法,如设置拼接的模式、添加要拼接的图像等。 2. FeaturesFinder类:特征点检测类,用于在图像中寻找特征点。该类利用SIFT、SURF等算法来检测图像中的关键点,以便进行匹配。 3. FeaturesMatcher类:特征点匹配类,用于对图像中的特征点进行匹配。该类使用KNN算法进行特征点的匹配,并利用RANSAC算法进一步筛选特征点,剔除误匹配。 4. Estimator类:变换估计类,用于估计图像间的变换参数。该类可以通过特征点的对应关系,计算图像间的旋转矩阵、平移矩阵等变换参数。 5. Blender类:图像融合类,用于将拼接后的图像进行融合。该类可以进行多种融合方式,如线性融合、多频融合等。 通过以上的类和方法,opencv2.4.9的stitching模块能够完成图像拼接的过程。整个过程包括特征点检测、特征点匹配、变换参数估计和图像融合等步骤。 需要指的是,本文只是对opencv2.4.9的stitching模块进行了初步的介绍,具体的源码分析需要深入研究。整个源码工程庞大,包含很多细节和算法,需要对计算机视觉和图像处理有较深入的理解才能进行分析和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值