2019年12月29日日曜日

転倒検知=ROSロボティックス

下記写真の様に転倒した後の検知は比較的簡単ですが、転倒しそう若しくは転倒の瞬間の検知が難題。
転倒しそう若しくは転倒の瞬間を捉える為には正常な歩行とはどういうものか?若しくは直立するメカニズムを理解して、直立が不完全若しくは歩行が困難な状態を導いてその状態を検知する事が必要だと思います。
直立歩行はバランスの上に成り立っています。
また現在ロボットでより人間に近い歩行の研究が進んでいて、多関節ロボットで実践しようとしています。HONDAのASIMO君が有名ですね。
バランスは、つまり重心移動を制御する事です。
倒立振子というものがありセンサーのデータでバランスを保ちます。
動画貼っておきます。
https://youtu.be/302rgfFKBZE

もう少し人を基準に近づけてみましょう。


今年のメーカーズフェア東京に出展の方が多関節の人型ロボットで自然な動作で制御を進めていたのでそれが参考になりそう。
人型ロボットの人間の様な動きはまだまだ発展途上です。単一作業のロボットは卵を割らない様に握ったり微細な動きは正確にできる様になりました。
重心の動きを制御するとより自然な歩行になります。つまり重心移動の理想形。
わたこさんから使用許諾頂きました。
https://twitter.com/WatakoLab

理論上はサーモグラフィーの歩行のデーターからボーン推定(骨の位置)から重心移動を推定して安定していない閾値を超えると転倒の可能性ありとすれば良い。。。

具体的な計算と方法がそう簡単には行かないでしょうね。。。
画像認識の領域で話題となっている “OpenPose”、みなさまご存知でしょうか?
OpenPoseはカーネギーメロン大学(CMU)の Zhe Caoら が「Realtime Multi-Person pose estimation」の論文で発表した、深層学習を用いて人物のポーズを可視化してくれる手法です。
https://ledge.ai/author/daichi-yamaoka/
さてどこまで何ができるのでしょうか?

2019年12月22日日曜日

関西電機工業のiPhoneアプリがでけました。

色々な制限を乗り越えてアップルから承認が出ました。
アップルのアプリの制限は厳しく、アプリのバグ以外にもセキュリティーや個人情報保護の観点で細かい規定があり出して見ないと分からない事が多く。9月から進めて先日やっと承認が降りました。

今回のアプリは今までのデザリングをつかったサーモグラフィー機能にAIを組み込みました。特質するのは学習モデルを後から追加出来る機構を組み込みました。手前味噌ですがアップルの機械学習を使ったアプリの中では世界初だと思います。
通常はアプリのアップデートでセットした学習モデルを一緒に組込むのが一般的ですが、ユーザーが学習モデルを追加する事が出来ませんでした。
こちらで用意したグーグルドライブから✊✌️✋や車、自転車、人や横断歩道をセットした学習モデルをダウンロード出来る様にもしています。

当然ですが、世界中でダウンロード出来ます。
アップルストアーでkansaidenkiで検索すると出てきます。

これからまたNVIDIA Jetsonに戻って応用技術のアップグレードを再開します。
これからのアウトプット(作品の発表)のスピードはもっと遅くなります。
インプットがもっと必要だと思っています。つまり製品の良し悪しは掛けた時間に比例するためです。ここまで来るのに3年半以上の歳月が掛かっています。





2019年12月16日月曜日

Docker container/Kubernates

今回はドッカーコンテナーについて、Dockerとは船のドックと同じ意味。
その上にコンテナー(容器)が乗っている。

抽象的ですね。

今は一つのOS上にアプリケーションソフトが動いているという従来の方法だとアプリケーションが上手く動かない様になっています。適切に全てを順番にインストールすると上手く行くのですがそれぞれ個々のパソコンのバージョンが違ったりドライバーや関連するライブラリーがインストールされていなかったりするとそれらが無い為にメインのアプリケーションは動けない様になります。
個々のパソコンのセキュリティーやその会社のセキュリティーの為に必要なコンポーネントを揃えないといけないのですが、複雑になりすぎてインストール出来ない問題を解決する方法がドッカーコンテナーの考え方です。

コンテナーの中にはOS、アプリケーションと関連するファイルを全て入れ込んで(ドッカーイメージというそうです。)それをローカルで走らせると(この状態をドッカーコンテナーというそうです。)
コンテナーの中のOS、アプリケーションやファイルはバージョンやそれぞれの関連性をドッカーイメージを作る際に最適な条件でセットします。ローカル側はそのドッカーシステムを動かすローカルドッカーをインストールしておくと適切にコンテナーを動かす事が出来ます。

自分なりに理解すると仮想環境(ドッカー)を用意してその仮想環境でアプリケーションを走らせる?通常仮想環境がOSでその上にアプリケーションを走らせるのですが、ドッカーはそのOSの部分も含んで動作させるのでより安定して動かす事が出来ます。

具体的にどう便利になるかというとこのドッカーコンテナーはローカルパソコンでもネット上のサーバーでも同じ様に動作する事が出来ます。
平たくいうと今のクラウドシステムはこのドッカーが必要不可欠になっています。
アマゾンAWS,マイクロソフトAzure、グーグルGCSは実質この技術の上になりたっています。
ローカルドッカーはWindows,MacやLinuxでインストールする事が出来ます。
まだ概念と初歩的な操作方法を順に進めているだけで全体を理解出来ていませんがこれはクラウドを理解する上で必須なので時間を掛けて進めて行くつもりです。


2019年12月12日木曜日

java script

google spreadsheetのスクリプトを使って簡単なカレンダー追加機能を作って見ました。といっても元データはhttps://blitzgate.co.jp/blog/1827/
https://stabucky.com/wp/archives/7247を足しただけ。ちょっと変更しただけですが、もっとなんとか出来そう?
今後はここも必要かな?
https://system.blog.uuum.jp/entry/2017/03/17/110000

もう少し調べると色々出来そうですが...
スプレッドシートからデータを抽出してカレンダーに入力、入力されたカレンダーのイベントと同期するというよりスプレッドシートのデータを毎回入力する。その際カレンダーのイベントにスプレッドシートと同じイベントがなければ消す感じ。同期というよりスプレッドシートを常に反映するのでその方が良いのかな?

2019年12月7日土曜日

opencvについて

関数C++があるのでやはり一からの作業ですね。
モザイク処理やドローンのmapping softを色々探していますが、leptonの荒い画像で2Dのマッピングソフトは売ってなさそう。高解像度の画像だと3Dにもしてくれる。
https://qiita.com/ChaoticActivity/items/68f10d7452680fa1d52d
double,floatの指定ルールを確認しないとハマってしまいそうです。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
using namespace std;

#define ROI_MARGIN_X1 (0.2*v_w)
#define ROI_MARGIN_X1_X2 (0.2*v_w)
#define ROI_MARGIN_Y (0.2*v_h)
#define ROI_SIZE_X ((v_w-ROI_MARGIN_X1*2-ROI_MARGIN_X1_X2)/2)
#define ROI_SIZE_Y (v_h-ROI_MARGIN_Y*2)
#define ROI_MARGIN_X2 (ROI_MARGIN_X1+ROI_SIZE_X+ROI_MARGIN_X1_X2)

#define map_offset_x 1500
#define map_offset_y 3000

double r(double x1,double y1,double x2,double y2){
    return pow((pow((x1-x2),2)+pow((y1-y2),2)),0.5);
}

int main()
{
    VideoCapture cap("a.mp4"); //同じDirectoryにfileがない場合("../Downloads/a.mp4");
    int v_w=cap.get(CV_CAP_PROP_FRAME_WIDTH);
    int v_h=cap.get(CV_CAP_PROP_FRAME_HEIGHT);
    Mat img;
    Mat result_img1;
    Mat result_img2;
    Mat resize_img;
    int d_x=0;
    int d_y=0;
    int position_x=0;
    int position_y=0;
    double angle=0; //右回りが正
    Mat map_img = Mat::zeros(3800, 3000, CV_8UC3);
    Mat dst_img= Mat(r(v_h,v_w,0,0),r(v_h,v_w,0,0), CV_8UC3);
    Rect dst_ROI(r(v_h,v_w,0,0)/2-v_w/2, r(v_h,v_w,0,0)/2-v_h/2, v_w, v_h);
    Mat element = Mat::ones(3,3,CV_8UC1);
 
    //初回でのテンプレートマッチング用のROIを作成
    cap>>img ;
    Mat last_roi_img1(img,Rect(ROI_MARGIN_X1,ROI_MARGIN_Y,ROI_SIZE_X,ROI_SIZE_Y));
    Mat last_roi_img2(img,Rect(ROI_MARGIN_X2,ROI_MARGIN_Y,ROI_SIZE_X,ROI_SIZE_Y));
 
    int max_frame=cap.get(CV_CAP_PROP_FRAME_COUNT);
    for(int i=1; i<max_frame;i++){ cap>>img;
     
        //テンプレートマッチング1----------------------------------------------
        matchTemplate(img,last_roi_img1,result_img1, CV_TM_CCOEFF_NORMED);
        Point max_pt1;
        double maxVal1;
        minMaxLoc(result_img1, NULL, &maxVal1, NULL, &max_pt1);
        //1つ目ここまで-----------------------------------------------------
     
        //テンプレートマッチング2----------------------------------------------
        matchTemplate(img,last_roi_img2,result_img2, CV_TM_CCOEFF_NORMED);
        Point max_pt2;
        double maxVal2;
        minMaxLoc(result_img2, NULL, &maxVal2, NULL, &max_pt2);
        //2つ目ここまで-----------------------------------------------------
     
        //次フレームでのテンプレートマッチング用のROIを保存1
        Mat roi_img1(img,Rect(ROI_MARGIN_X1,ROI_MARGIN_Y,ROI_SIZE_X,ROI_SIZE_Y));
        last_roi_img1=roi_img1.clone();
        //次フレームでのテンプレートマッチング用のROIを保存2
        Mat roi_img2(img,Rect(ROI_MARGIN_X2,ROI_MARGIN_Y,ROI_SIZE_X,ROI_SIZE_Y));
        last_roi_img2=roi_img2.clone();
     
        angle-=atan((double)(max_pt1.y-max_pt2.y)/(max_pt1.x-max_pt2.x));
     
        //位置推定
        d_x=(ROI_MARGIN_X1-max_pt1.x)/2+(ROI_MARGIN_X2-max_pt2.x)/2;
        d_y=(ROI_MARGIN_Y-max_pt1.y);
        position_x+=d_x*cos(angle)-d_y*sin(angle);
        position_y+=d_x*sin(angle)+d_y*cos(angle);
     
        cout <<i<<" / " <<max_frame<<" (" << position_x << ", " << position_y << ") angle = "<<angle<<endl;
     
        //ここからパノラマ作成
        Mat rot_dst_img(dst_img,dst_ROI);
        img.copyTo(rot_dst_img);
     
        // 回転:  [deg] と スケーリング: 1.0 [倍]
        float angle_d = -angle*180.0/3.141592, scale = 1.0;
        // 中心:画像中心
        cv::Point2f center(dst_img.cols*0.5, dst_img.rows*0.5);
        // 2次元の回転行列を計算
        const cv::Mat affine_matrix = cv::getRotationMatrix2D( center, angle_d, scale );
        warpAffine(dst_img, rot_dst_img, affine_matrix, dst_img.size());
     
        Mat map_roi_img(map_img,Rect(position_x+map_offset_x-dst_img.cols/2,position_y+map_offset_y-dst_img.rows/2,dst_img.cols,dst_img.rows));
        Mat mask=rot_dst_img.clone();
        cvtColor(mask,mask,CV_BGR2GRAY);
        threshold(mask,mask,1,255,THRESH_BINARY);
        erode(mask,mask, element, Point(-1,-1), 1);
        rot_dst_img.copyTo(map_roi_img,mask);
        resize(map_img, resize_img, cv::Size() ,0.2,0.2);
        //imshow("Map", map_img);
        imshow("Map", resize_img); //画面が大きいのでリサイズ
     
        waitKey(1);
    }
    imwrite("map.png", map_img);
    //imshow("Map", map_img);
    imshow("Map", resize_img);
    waitKey(0);
    return 0;
}

OpenCV が少し動かせる様になったのでmacにインストールしようとしてまたハマる。。。
マルチプラットフォームなのでubuntu, windows, Macにインストールできるはずで簡単にインストールできると思ったら大間違い。今回opencvもバージョンで色々違うのを思い知らされた。opencv2から3も違うのは先週までで思い知らされたのにmacでbrewで簡単にインストール出来ると勘違い。
wiwaoMacBookAir:~ wiwao$ brew install opencv
で関連するものをインストール
==> Installing dependencies for opencv: cmake, eigen, gflags, glog, metis, gmp, isl, mpfr, libmpc, gcc, openblas, suite-sparse, ceres-solver, aom, libpng, freetype, fontconfig, frei0r, gettext, libunistring, libidn2, libtasn1, nettle, libffi, p11-kit, libevent, unbound, gnutls, fribidi, pcre, python, glib, lzo, pixman, cairo, graphite2, icu4c, harfbuzz, libass, libbluray, libsoxr, libvidstab, libogg, libvpx, opencore-amr, jpeg, libtiff, little-cms2, openjpeg, opus, rtmpdump, flac, libsndfile, libsamplerate, rubberband, sdl2, speex, giflib, webp, leptonica, tesseract, x264, x265, xvid, ffmpeg, numpy, ilmbase, openexr and tbb
その後OpenCVをインストール
バージョンは4.1.2
そもそもコンパイルが出来ず。
error: #error "OpenCV 4.x+ requires enabled C++11 support"
 #  error "OpenCV 4.x+ requires enabled C++11 support"
brewでインストールしているのにc++11でないとエラーってどうなの?
そこもインストールをしてくれないの?
でbrew uninstall opencvで一度取り除いてopencv3をインストールし直し。
その操作も注意深くしないと。。。
opencv@3 ?
インストールパッケージをopencvとだけするとその時点でインストール可能な最新版がインストールされます.記事執筆時点では,4.1.0でした.
$ brew list --versions | grep opencv
opencv 4.1.0_1

他のバージョンが欲しい場合

OpenCV2やOpenCV3が必要な場合は,
$ brew install opencv@2
$ brew install opencv@3
でbrew install opencv@3
ワーングが。。。そういえばパスをbashrcに書き込んだのがopencv4のままなので一旦消去してecho 'export PATH="/usr/local/opt/opencv@3/bin:$PATH"' >> ~/.bash_profile
を書き込んだけどなんか違う感じ。最初は気づかなかったけど。

OpenCVを使ったC++コードをコンパイルする(CMake, GCC, pkg-config)



でパッケージのパスを通さないと行けないのに/usr/local/opt/opencv@3/bin:$PATHなんでbin ?
export PKG_CONFIG_PATH="/usr/local/opt/opencv@3/lib/pkgconfig"
にしないと行けないのに気がついた。
For compilers to find opencv@3 you may need to set:
  export LDFLAGS="-L/usr/local/opt/opencv@3/lib"
  export CPPFLAGS="-I/usr/local/opt/opencv@3/include"

For pkg-config to find opencv@3 you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/opencv@3/lib/pkgconfig"
は一応書き込んだ。
でもさっきはopencv4.1.2で場所のときは、
OpenCVインストール時に/usr/local/lib/pkgconfigopencv4.pcというファイルが作成されているのでこれをPKG_CONFIG_PATHに与えます。
以下のコマンドを実行してください。
とある。
と言う事は今回は上記の様に/usr/local/opt/opencv@3/lib/pkgconfigになるはず。
:warning: 注意: exportで値を追加した環境変数はターミナルを閉じるまでは値を保持し続けます。
逆に言えば、ターミナルを開くたびに上記のexport (以下省略)を実行しなければいけません。
echo export PKG_CONFIG_PATH==/usr/local/opt/opencv@3/lib/pkgconfig >> ~/.bashrc
にしないとターミナルを閉じると毎回exportしないと行けないの、今回これで少し勉強になった。
echo export PKG_CONFIG_PATH==/usr/local/opt/opencv@3/lib/pkgconfig >> ~/.bashrc
nano ~/.bashrc
一番下の行にexport PKG_CONFIG_PATH==/usr/local/opt/opencv@3/lib/pkgconfigをコピペして保存すれば、次回からUbuntu(Mac)を起動するときに自動で実行されます。
nano ~/.bashrcでも確認出来ました。
意外とnano の操作で焦った。でexitするのはcontrolボタンとXキーでその後。

この画面でどのキーで抜け出すか分からない以外とリターンキーだけ。escキーでも良いのか?
2017071104

Warning: opencv@3 dependency gcc was built with a different C++ standard
library (libstdc++ from clang). This may cause problems at runtime.
==> Caveats
opencv@3 is keg-only, which means it was not symlinked into /usr/local,
because this is an alternate version of another formula.

If you need to have opencv@3 first in your PATH run:
  echo 'export PATH="/usr/local/opt/opencv@3/bin:$PATH"' >> ~/.bash_profile

For compilers to find opencv@3 you may need to set:
  export LDFLAGS="-L/usr/local/opt/opencv@3/lib"
  export CPPFLAGS="-I/usr/local/opt/opencv@3/include"

For pkg-config to find opencv@3 you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/opencv@3/lib/pkgconfig"

==> Summary
🍺  /usr/local/Cellar/opencv@3/3.4.5_6: 656 files, 235.5MB
wiwaoMacBookAir:~ wiwao$ c++ $(pkg-config --cflags --libs opencv4) imshow.cpp
Package opencv4 was not found in the pkg-config search path.
Perhaps you should add the directory containing `opencv4.pc'
to the PKG_CONFIG_PATH environment variable
No package 'opencv4' found
clang: error: no such file or directory: 'imshow.cpp'
clang: error: no input files

wiwaoMacBookAir:~ wiwao$ nano ~/.bashrc

でここまではなんとか出来たと思うのですが、コンパイルが通りません。。。
ここの簡単なファイルをテストしてるのですが、全角スペースのエラーって別のエラー
って。。。
imshow.cpp:3:4: warning: treating Unicode character as whitespace       [-Wunicode-whitespace]
https://swallow-incubate.com/archives/blog/20181221/

一度スペースを全部取り除いてもエラーが変わらないので再度コピペでコンパイルは通る様になりましたが、
wiwaomacbookair:~ wiwao$ ./a.out
-bash: ./a.out: No such file or directory
wiwaomacbookair:~ wiwao$ cd Desktop
wiwaomacbookair:Desktop wiwao$ ./a.out
^C

wiwaomacbookair:Desktop wiwao$ 

ないも出ない。。。。。。。。。。。。。。。。。。。。。
と言う事は相対パスがおかしいって事かな
と言う事で画像ファイルをDesktopに移すと出来ました。
やりやれです。

相対パスと絶対パスは勉強し直しです。Ubuntuでも適当にしてるからダメですね。
https://webliker.info/78726/


img = cv::imread("../Downloads/suwawachan.jpg");

追伸:
いろいろ変えているういちにどれが効いているか分かりません。

g++ imshow.cpp `pkg-config --cflags --libs opencv`
でもいいのですが、


echo export PKG_CONFIG_PATH==/usr/local/opt/opencv@3/lib/pkgconfig >> ~/.bashrc
が効いていません。??bashrcには書いてあります。
wiwaomacbookair:~ wiwao$ cd Desktop
wiwaomacbookair:Desktop wiwao$ g++ imshow.cpp `pkg-config --cflags --libs opencv`

Package opencv was not found in the pkg-config search path.

Perhaps you should add the directory containing `opencv.pc'

to the PKG_CONFIG_PATH environment variable
No package 'opencv' found
imshow.cpp:1:10: fatal error: 'opencv2/opencv.hpp' file not found
#include <opencv2/opencv.hpp>
         ^~~~~~~~~~~~~~~~~~~~
1 error generated.
wiwaomacbookair:Desktop wiwao$ export PKG_CONFIG_PATH="/usr/local/opt/opencv@3/lib/pkgconfig"
wiwaomacbookair:Desktop wiwao$ g++ imshow.cpp `pkg-config --cflags --libs opencv`
wiwaomacbookair:Desktop wiwao$ ./a.out
^C
wiwaomacbookair:Desktop wiwao$ 
毎回export??

bash_profileでないといけない??????
適当にググると「とにかく何でも .bash_profile に書いとけばおk」みたいな嘘を書いたブログ記事がわんさか出てくるのでここに正解を書いておきます。

.bash_profile

.bash_profile はログイン時にのみ実行されます。具体的な用途は:
  • 環境変数を設定する (export する変数)
環境変数はプロセス間で勝手に受け継がれるのでログイン時のみ設定すれば十分です。

.bashrc

.bashrc は対話モードの bash を起動する時に毎回実行されます。具体的な用途は:
  • 環境変数でない変数を設定する (export しない変数)
  • エイリアスを定義する
  • シェル関数を定義する
  • コマンドライン補完の設定をする
これらは bash を起動する度に毎回設定する必要があるものです。

その他



でも
export PKG_CONFIG_PATH==/usr/local/opt/opencv@3/lib/pkgconfig
Macだから????

2019年12月4日水曜日

C++ エディッタ geanyを入れる

C++をコンパイルするのにどのエディッターでも悩む。わからない。Ubuntu用で適当なものとしてはEclipse参考書おすすめ。
小野さんの設定ではGeanyが入っている。Geanyを調べて見ると軽くて使いやすいとの評判なので小野さんも使っているのでしょう。
でインストールと調べているとリポジトリはapt-get install geanyだけ、でもブログ等では
sudo add-apt-repository ppa:geany-dev/ppa
で最新にしてからとなっている。でも最新版は少し不安なので最新版でないものを標準でインストール
sudo apt-get install geany geany-plugins-common
プラグインがあるようで一応プラグインをインストール。
build設定はせず。

こんな作業もおっかなびっくりです。
C++の勉強もすこしづづ始める。

空撮動画からカメラ位置を推定

と正に今回の目的のものを教えてもらいましたが理解はイマイチ。
当面の目的はopenCVのC++の勉強といったところですが
ここでは全然理解出来ず。

ここで少しコードの理解が出来ました。中々理解し易い本も見つけれませんでしたが分かりやすかったです。vol5まで読んで見る。
OPENCVの本は難解で少しずつ始めます。どの本を買うか思案中で長いお付き合いになりそう。。。
空撮動画で現場写真のパノラマ写真に結合して出来ると幸せなのですが、g++ aerial.cpp `pkg-config --cflags opencv` `pkg-config --libs opencv`でコンパイルエラーが出ます。
ヘッダーファイルが無いとエラーが出ますがどうもそれ以外の原因の様?
コンパイルする前にpathを通すか?

。。。で結局はヘッダーファイルがopencv2.4とopencv3.4.0の違いで
opencv2.4では
#include "opencv/cv.h" #include "opencv/highgui.h"
をopencv3.4.0では一つになりました。
#include <opencv2/opencv.hpp>

./a.out
で途中まで画像が出てきました。
がエラーでストップ。。。。。。。。。
OpenCV Error: Assertion failed (corrsize.height <= img.rows +
templ.rows – 1 && corrsize.width <= img.cols + templ.cols – 1) in
crossCorr, file c:/OpenCV/opencv /modules/imgproc/src/templmatch.cpp,
line 589 terminate called after throwing an instance of ‘cv::Exception’
what(): c:/OpenCV/opencv/modules/imgproc/src/templmatch.cpp:589:
error: (-215) corrsize.height <= img.rows + templ.rows – 1 &&
corrsize.width <= img.cols + te mpl.cols – 1 in function crossCorr
中身の関数や変数の違いは分からず。。。
解釈としては、
stdio殿が指摘されている通りで、エラーの内容を理解される事をお勧めします。
マッチングする映像の縦横(画像のmatの.colsとrows)と探す基の縦横をまず確認されてください。
エラー内容の通りとなっていると思います。
なのですが、中身の違いが分からずffmpegでファイルのサイズを調整すると動きました。
ffmpeg -i DJI_0010.mp4 -filter:v "crop=720:500:0:40" wt.mp4
ffmpeg -ss 00:00:20.000 -i wt.mp4 -t 00:0:09.000 7.mp4

ファイルのサイズを半分にして3/4,7/8とすると動きました。フレームレートも30fpsから20fpsでも秒数を少なくしても動きます。空間座標の設定方法はイマイチ理解は出来ていませんがその空間座標からはみ出してもエラーが出るようです。
pngファイルも生成されました。
imputファイルとpnpファイルはcppフォルダーに入れてテスト。
手法としてはopencvのパノラマ作成におけるモザイキング処理、すなわち、画像同士の貼り合わせ処理です。
今回はテンプレートマッチングですがステッチングと言う方法で写真の端々を繋いでパノラマ写真を作る方法がありHUGINやその他のソフトがあるようでHUGINを試してみましたが、動画を丁度良いサイズにクロップして順番に並べましたが使い勝手が良いとは言えませんでした。

今回のモザイキング処理は動画で違いのある部分を付け足して言う処理なので動けば理想的!

ですが。。。
中々手強いです。
先ず動画の四隅をトリミングする必要があります。四隅が黒だとモザイキング処理がうまく行かず破綻します。
上手くいくとこんな感じ、
回転行列を使って回転も処理するようになっていますが滑らかな画像でないとダメ。
また大きく回転しても正確に推定出来ません。ソフトでどんどん補正処理を追加して行けば良いかもしれませんが、スクラッチで開発は無理です。適当なソフトも並行して探します。
サンプルテストの1.png,2.png,7pngはそこそこのレベルですが、ファイルの容量の制約はソフトを本格的に改修しないといけませんが、それが出来るかどうか?これだけで結構な専門家が居る処理なので。。。。

1png
空間座標は無駄にでかいですが、小さくするとエラーが出ます。

もとの動画も置いておきます。
2png



3png

4png



6png



7png




四隅のエッジの画像比較は単調な太陽光パネルでは難しいのかもしれません。
どこまでチューニング出来るかが問題です。

あっ、コード貼っときます。
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
using namespace std;

#define ROI_MARGIN_X1 (0.2*v_w)
#define ROI_MARGIN_X1_X2 (0.2*v_w)
#define ROI_MARGIN_Y (0.2*v_h)
#define ROI_SIZE_X ((v_w-ROI_MARGIN_X1*2-ROI_MARGIN_X1_X2)/2)
#define ROI_SIZE_Y (v_h-ROI_MARGIN_Y*2)
#define ROI_MARGIN_X2 (ROI_MARGIN_X1+ROI_SIZE_X+ROI_MARGIN_X1_X2)

#define map_offset_x 1500
#define map_offset_y 3000

double r(double x1,double y1,double x2,double y2){
    return pow((pow((x1-x2),2)+pow((y1-y2),2)),0.5);
}

int main()
{
    VideoCapture cap("7.mp4");
    int v_w=cap.get(CV_CAP_PROP_FRAME_WIDTH);
    int v_h=cap.get(CV_CAP_PROP_FRAME_HEIGHT);
    Mat img;
    Mat result_img1;
    Mat result_img2;
    int d_x=0;
    int d_y=0;
    int position_x=0;
    int position_y=0;
    double angle=0; //右回りが正
    Mat map_img = Mat::zeros(4000, 3000, CV_8UC3); //pngの空間指定
    Mat dst_img= Mat(r(v_h,v_w,0,0),r(v_h,v_w,0,0), CV_8UC3);
    Rect dst_ROI(r(v_h,v_w,0,0)/2-v_w/2, r(v_h,v_w,0,0)/2-v_h/2, v_w, v_h);
    Mat element = Mat::ones(3,3,CV_8UC1);
    
    //初回でのテンプレートマッチング用のROIを作成
    cap>>img ;
    Mat last_roi_img1(img,Rect(ROI_MARGIN_X1,ROI_MARGIN_Y,ROI_SIZE_X,ROI_SIZE_Y));
    Mat last_roi_img2(img,Rect(ROI_MARGIN_X2,ROI_MARGIN_Y,ROI_SIZE_X,ROI_SIZE_Y));
    
    int max_frame=cap.get(CV_CAP_PROP_FRAME_COUNT);
    for(int i=1; i<max_frame;i++){ cap>>img;
        
        //テンプレートマッチング1----------------------------------------------
        matchTemplate(img,last_roi_img1,result_img1, CV_TM_CCOEFF_NORMED);
        Point max_pt1;
        double maxVal1;
        minMaxLoc(result_img1, NULL, &maxVal1, NULL, &max_pt1);
        //1つ目ここまで-----------------------------------------------------
        
        //テンプレートマッチング2----------------------------------------------
        matchTemplate(img,last_roi_img2,result_img2, CV_TM_CCOEFF_NORMED);
        Point max_pt2;
        double maxVal2;
        minMaxLoc(result_img2, NULL, &maxVal2, NULL, &max_pt2);
        //2つ目ここまで-----------------------------------------------------
        
        //次フレームでのテンプレートマッチング用のROIを保存1
        Mat roi_img1(img,Rect(ROI_MARGIN_X1,ROI_MARGIN_Y,ROI_SIZE_X,ROI_SIZE_Y));
        last_roi_img1=roi_img1.clone();
        //次フレームでのテンプレートマッチング用のROIを保存2
        Mat roi_img2(img,Rect(ROI_MARGIN_X2,ROI_MARGIN_Y,ROI_SIZE_X,ROI_SIZE_Y));
        last_roi_img2=roi_img2.clone();
        
        angle-=atan((double)(max_pt1.y-max_pt2.y)/(max_pt1.x-max_pt2.x));
        
        //位置推定
        d_x=(ROI_MARGIN_X1-max_pt1.x)/2+(ROI_MARGIN_X2-max_pt2.x)/2;
        d_y=(ROI_MARGIN_Y-max_pt1.y);
        position_x+=d_x*cos(angle)-d_y*sin(angle);
        position_y+=d_x*sin(angle)+d_y*cos(angle);
        
        cout <<i<<" / " <<max_frame<<" (" << position_x << ", " << position_y << ") angle = "<<angle<<endl;
        
        //ここからパノラマ作成
        Mat rot_dst_img(dst_img,dst_ROI);
        img.copyTo(rot_dst_img);
        
        // 回転:  [deg] と スケーリング: 1.0 [倍]
        float angle_d = -angle*180.0/3.141592, scale = 1.0;
        // 中心:画像中心
        cv::Point2f center(dst_img.cols*0.5, dst_img.rows*0.5);
        // 2次元の回転行列を計算
        const cv::Mat affine_matrix = cv::getRotationMatrix2D( center, angle_d, scale );
        warpAffine(dst_img, rot_dst_img, affine_matrix, dst_img.size());
        
        Mat map_roi_img(map_img,Rect(position_x+map_offset_x-dst_img.cols/2,position_y+map_offset_y-dst_img.rows/2,dst_img.cols,dst_img.rows));
        Mat mask=rot_dst_img.clone();
        cvtColor(mask,mask,CV_BGR2GRAY);
        threshold(mask,mask,1,255,THRESH_BINARY);
        erode(mask,mask, element, Point(-1,-1), 1);
        rot_dst_img.copyTo(map_roi_img,mask);
        imshow("Map",map_img);
        
        waitKey(1);
    }
    imwrite("map.png", map_img);
    imshow("Map",map_img);
    waitKey(0);
    return 0;
}

出力としては回転行列のアングルを吐きます。
1 / 225 (0, 0) angle = 0
2 / 225 (0, 0) angle = -0.00347221
3 / 225 (0, 0) angle = -0.00694442
4 / 225 (0, 0) angle = -0.0104166
5 / 225 (0, -1) angle = -0.0104166
6 / 225 (0, -1) angle = -0.0138888
7 / 225 (0, -2) angle = -0.0138888
8 / 225 (0, -3) angle = -0.017361
9 / 225 (0, -5) angle = -0.017361
10 / 225 (0, -7) angle = -0.017361
11 / 225 (0, -9) angle = -0.017361
12 / 225 (0, -11) angle = -0.017361
13 / 225 (0, -13) angle = -0.017361
14 / 225 (0, -15) angle = -0.017361
15 / 225 (0, -17) angle = -0.017361
16 / 225 (0, -19) angle = -0.017361
17 / 225 (0, -21) angle = -0.017361
18 / 225 (0, -23) angle = -0.017361
19 / 225 (0, -26) angle = -0.017361
20 / 225 (0, -28) angle = -0.017361
21 / 225 (0, -30) angle = -0.0208212
22 / 225 (0, -32) angle = -0.0242934
23 / 225 (0, -35) angle = -0.0242934
24 / 225 (0, -38) angle = -0.0242934
25 / 225 (0, -41) angle = -0.0242934
26 / 225 (0, -44) angle = -0.0242934
27 / 225 (0, -47) angle = -0.0242934
28 / 225 (0, -50) angle = -0.0277657
29 / 225 (0, -54) angle = -0.0277657
30 / 225 (0, -58) angle = -0.0277657
31 / 225 (0, -62) angle = -0.0277657
32 / 225 (0, -65) angle = -0.0277657
33 / 225 (0, -69) angle = -0.0277657
34 / 225 (0, -73) angle = -0.0277657
35 / 225 (0, -77) angle = -0.0312379
36 / 225 (0, -82) angle = -0.0312379
37 / 225 (0, -87) angle = -0.0312379
38 / 225 (0, -92) angle = -0.0312379
39 / 225 (0, -97) angle = -0.0312379
40 / 225 (0, -102) angle = -0.0312379
41 / 225 (0, -107) angle = -0.0312379
42 / 225 (0, -112) angle = -0.0312379
43 / 225 (0, -117) angle = -0.0312379
44 / 225 (0, -122) angle = -0.0312379
45 / 225 (0, -127) angle = -0.0312379
46 / 225 (0, -132) angle = -0.0312379
47 / 225 (0, -137) angle = -0.0312379
48 / 225 (0, -142) angle = -0.0312379
49 / 225 (0, -147) angle = -0.0312379
50 / 225 (0, -152) angle = -0.0312379
51 / 225 (0, -157) angle = -0.0312379
52 / 225 (0, -162) angle = -0.0312379
53 / 225 (0, -167) angle = -0.0312379
54 / 225 (0, -172) angle = -0.0312379
55 / 225 (0, -177) angle = -0.0312379
56 / 225 (0, -182) angle = -0.0312379
57 / 225 (0, -187) angle = -0.0312379
58 / 225 (0, -192) angle = -0.0312379
59 / 225 (-1, -197) angle = -0.0312379
60 / 225 (-2, -203) angle = -0.0277657
61 / 225 (-2, -208) angle = -0.0277657
62 / 225 (-2, -213) angle = -0.0277657
63 / 225 (-2, -218) angle = -0.0277657
64 / 225 (-3, -223) angle = -0.0277657
65 / 225 (-3, -228) angle = -0.0277657
66 / 225 (-3, -233) angle = -0.0277657
67 / 225 (-3, -238) angle = -0.0277657
68 / 225 (-3, -243) angle = -0.0277657
69 / 225 (-3, -248) angle = -0.0277657
70 / 225 (-3, -253) angle = -0.0277657
71 / 225 (-3, -258) angle = -0.0277657
72 / 225 (-3, -263) angle = -0.0277657
73 / 225 (-3, -268) angle = -0.0277657
74 / 225 (-3, -273) angle = -0.0277657
75 / 225 (-3, -279) angle = -0.0277657
76 / 225 (-4, -285) angle = -0.0277657
77 / 225 (-4, -291) angle = -0.0277657
78 / 225 (-5, -297) angle = -0.0277657
79 / 225 (-5, -303) angle = -0.0277657
80 / 225 (-5, -308) angle = -0.0277657
81 / 225 (-5, -314) angle = -0.0277657
82 / 225 (-5, -319) angle = -0.0277657
83 / 225 (-5, -325) angle = -0.0277657
84 / 225 (-5, -331) angle = -0.0277657
85 / 225 (-5, -337) angle = -0.0277657
86 / 225 (-5, -343) angle = -0.0242934
87 / 225 (-5, -348) angle = -0.0242934
88 / 225 (-5, -354) angle = -0.0242934
89 / 225 (-5, -359) angle = -0.0242934
90 / 225 (-5, -364) angle = -0.0242934
91 / 225 (-5, -370) angle = -0.0208212
92 / 225 (-5, -376) angle = -0.017349
93 / 225 (-5, -381) angle = -0.017349
94 / 225 (-5, -386) angle = -0.017349
95 / 225 (-5, -391) angle = -0.017349
96 / 225 (-5, -397) angle = -0.0138768
97 / 225 (-5, -402) angle = -0.0138768
98 / 225 (-5, -407) angle = -0.0138768
99 / 225 (-5, -413) angle = -0.0104046
100 / 225 (-5, -419) angle = -0.0104046
101 / 225 (-5, -424) angle = -0.0104046
102 / 225 (-5, -430) angle = -0.0104046
103 / 225 (-5, -436) angle = -0.0069324
104 / 225 (-5, -442) angle = -0.0069324
105 / 225 (-5, -447) angle = -0.0069324
106 / 225 (-5, -453) angle = -0.0069324
107 / 225 (-5, -459) angle = -0.00346019
108 / 225 (-5, -465) angle = -0.00346019
109 / 225 (-5, -471) angle = -0.00346019
110 / 225 (-5, -477) angle = -0.00346019
111 / 225 (-5, -483) angle = -0.00346019
112 / 225 (-5, -489) angle = -0.00346019
113 / 225 (-5, -495) angle = -0.00346019
114 / 225 (-5, -501) angle = -0.00346019