LoginSignup
10
6

More than 3 years have passed since last update.

MATLABで遊ぼう:簡単に時計を作れるか

Posted at

前書き

前回はマインスイーパの作り方を紹介したが、今回は時計を簡単に作れるかを考えてみる。
頑張れば時計の模様(円や数字など)もかけることはできるが、ここでは、画像として導入したケースを紹介する。その理由は、作成者オリジナルの時計模様画像に一般化できるためである。

環境

MATLABのR2019aバージョン
Windows10
MATLAB Toolbox: Image Processing Toolbox

全体のフロー

プログラム作成のフロー:
1.オリジナルの時計画像を作成
2.時計の中心や針などを定義
3.時間と共に時計の針の角度計算や位置更新

オリジナルの時計画像を作成

図1のような簡単な画像を作成した。今回紹介する事例では、作成者オリジナルの時計画像に対応するようにしているが、条件として、円形の時計のみが対象となる。
BaseWatch3.jpg
図1:著作者オリジナルの時計画像

時計の中心や針などを定義

まずは、MATLABのimfindcircles関数を利用して上記オリジナル画像よりその中心を求める。
以下コードではMATLABのビルトイン関数IMFINDCIRCLESで画像から中心を求めているが(汎用性の高度化を目的で)、
基本的に、画像ごと、中心の位置をメタデータとして記録しておけば、そのまま取り組んでも大丈夫。
次は、その中心から円周方向に伸びる3本の針(時、分、秒)を定義する。
時と分の針を時計らしく太めにするため、二本の直線で表現する。
これらの二本の直線は円の中心側でお互い隔ており、円周側で一体になっている。
コードは以下になる(コメントもご参照):

% パラメータ
offst = 1;
rH  = 60;
rM  = 80;
rS  = 110;
radrange = [100 180];

% 自作のオリジナル画像を取り組む
I = imread('BaseWatch3.jpg');%図1の画像はこのファイルにある
I = flipud(I);
[c,r] = imfindcircles(I,radrange);%画像中心計算
%画像の取り組み
figure('ToolBar','none','menubar','none')
hI = imshow(I); %画像表示
set(gca,'YDir','normal') %画像表示におけるY軸の方向を通常の直交座標に合わせる
hold on
plot(c(1),c(2),'k.','Markersize',15) %中心に例えば黒い丸を描く
%針の定義・初期化
hlH1= line([c(1) c(1)],[c(2) c(2)], 'Color','Blue', 'Linewidth',2);%時の針⓵
hlH2= line([c(1) c(1)],[c(2) c(2)], 'Color','Blue', 'Linewidth',2);%時の針⓶
hlM1= line([c(1) c(1)],[c(2) c(2)], 'Color','Red', 'Linewidth',1);%分の針⓵
hlM2= line([c(1) c(1)],[c(2) c(2)], 'Color','Red', 'Linewidth',1);%分の針⓶
hlS = line([c(1) c(1)],[c(2) c(2)], 'Color','Black', 'Linewidth',1);%秒の針

時間と共に時計の針の角度計算や位置更新

MATLABで簡単に現在時刻を読み込んだり、その中から、時、分や秒の値を分離することができる。
この値に応じて、それぞれの針の位置を更新すればいい。
それぞれの針は、片方(円中心側)の位置が常に円の中心にあるので、求めるべきことは、それぞれの針の円周側の位置(X,Y座標)がどうなるかとのことである。

そのため下記ワークフローを考える:
(1)時、分や秒について、その現在値に基づいてそれぞれの針の角度を求める。
このため、以下の関数getAngles()をご参照。

(2)求めた角度と針の長さ情報を利用して、円柱座標から直交座標に変換によって、針の円周側の位置を求める(X,Y座標)。

(3)それぞれの針の新規位置に関する表示を更新する
最後に、Whileループの中に上記(1)~(3)を繰り返していけば、時計の出来上がりである。

※ちなみに、今回は40行以下で済んだとのこと。

while isvalid(hI)
    %時、分、秒の値を分離
    hms = datestr(now,'hh-MM-ss');
    hr  = str2double(hms(1:2));
    if hr > 12
        hr = hr - 12;
    end
    mn  = str2double(hms(4:5));
    ss  = str2double(hms(7:8));

    %時間の針の処理
    [aH,aM,aS]  = getAngles(hr,mn,ss); 
    [x, y] = pol2cart(aH,rH);
    adjustPosition(c,x,y,[hlH1,hlH2],offst+1);
    %分の針の処理
    [x, y] = pol2cart(aM,rM);
    adjustPosition(c,x,y,[hlM1,hlM2],offst);
    %秒の針の処理
    [x, y] = pol2cart(aS,rS);
    adjustPosition(c,x,y,hlS,offst);
end

getAngles()関数

function [aH,aM,aS]  = getAngles(hr,mn,ss)
aH = deg2rad(90 - hr*30 - mn*0.5 - ss*(1/120));
aM = deg2rad(90 - mn*6 - ss*(1/10));
aS = deg2rad(90 - ss*6);
end

adjustPosition()関数

function adjustPosition(c,x,y,hndls,offst)
p   = [c(1)+x c(2)+y];
if numel(hndls)>1
    set(hndls(1),'XData',[c(1)-offst p(1)],'YData',[c(2)-offst p(2)]);
    set(hndls(2),'XData',[c(1)+offst p(1)],'YData',[c(2)+offst p(2)]);
else
    set(hndls,'XData',[c(1) pS(1)],'YData',[c(2) pS(2)]);
end
drawnow
end

最後に出来上がるのが、こんな時計。シンプルではあるものの、MATLABでとても簡単に作れるたのがうれしい。
image.png

10
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
6