MATLAB에서 놀자 : 시계를 쉽게 만들 수 있습니까?

사전 쓰기



전회는 마인 스위퍼 만드는 법을 소개했지만, 이번에는 시계를 쉽게 만들 수 있는지 생각해 본다.
열심히 하면 시계의 모양(엔이나 숫자 등)도 걸 수는 있지만, 여기에서는, 화상으로서 도입한 케이스를 소개한다. 그 이유는, 작성자 오리지날의 시계 패턴 화상으로 일반화할 수 있기 때문이다.

환경



MATLAB의 R2019a 버전
Windows10
MATLAB Toolbox: Image Processing Toolbox

전체 흐름



프로그램 작성 흐름:
1. 원본 시계 이미지 만들기
2. 시계의 중심이나 바늘 등을 정의
3. 시간이 지남에 따라 시계 바늘의 각도 계산 및 위치 업데이트

원본 시계 이미지 만들기



도 1과 같이 간단한 화상을 작성하였다. 이번에 소개하는 사례에서는, 작성자 오리지날의 시계 화상에 대응하도록 하고 있지만, 조건으로서, 원형의 시계만이 대상이 된다.

그림 1 : 저자 오리지널 시계 이미지

시계의 중심이나 바늘 등을 정의



우선, MATLAB의 imfindcircles 함수를 이용하여 상기 오리지널 화상으로부터 그 중심을 구한다.
아래 코드에서는 MATLAB의 내장 함수 IMFINDCIRCLES로 이미지에서 중심을 찾지만 (범용성 향상을 위해)
기본적으로 이미지마다 중심의 위치를 ​​메타데이터로 기록해 두면 그대로 작업해도 괜찮다.
다음은 그 중심으로부터 원주 방향으로 연장되는 3개의 바늘(시, 분, 초)을 정의한다.
시간과 분의 바늘을 시계답게 굵게 하기 위해, 2개의 직선으로 표현한다.
이 두 개의 직선은 원의 중심 측에서 서로 분리되어 있으며 원주 측에서 일체로되어 있습니다.
코드는 다음과 같다 (코멘트도 참조) :
% パラメータ
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에서 매우 쉽게 만들 수 있었던 것이 기쁘다.

좋은 웹페이지 즐겨찾기