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


0 件のコメント:

コメントを投稿