前提・実現したいこと
現在、大学で光学系の授業を受けており授業の中で扱った題材を自分で実際に確かめてみたいと思いプログラミングに挑戦しています。今回、作成したいプログラムが「魚眼カメラで撮影した画像を通常のカメラで撮影したように処理(平面展開処理)をするプログラム」となっています。
実装の流れは、魚眼カメラで撮影した画像(src)、通常のカメラで撮影したようにsrcを処理した画像(dst)とすると
1、srcのピクセル座標がdstのどのピクセルに対応するかを計算で求めて、unordered_map<int,Point2d> A_dash_Mapに保存。この時、mapのキーはdstの座標(x,y)をy*画像の横幅+xのように通し番号?として表現した値。キーに対応するPoint2dはsrcのピクセル座標。
2、srcのピクセル値をA_dash_mapを参照しながらdstへとコピーする。
この流れてプログラム自体は完成したのですが無駄が多いようで処理時間が大幅にかかってしまいます。平面展開をする関数のループが多いことと、ループの中身自体でもA_dash_Mapの検索を行っているため処理速度が遅いのかと思いましたが改善方法が思いつきません。高速化できる部分があればアドバイスをいただきたいです。
初心者のため読みにくいソースコードだと思います。
申し訳ありません。
該当のソースコード
C++
1#include<iostream> 2#include<opencv2/opencv.hpp> 3#include<unordered_map> 4#include<string> 5#define _USE_MATH_DEFINES 6#include<math.h> 7 8#define ANGLE 100 9#define FISHEYE_ANGLE 180 10#define CAMERA_ID 1 11#define CAMERAWIDTH 2448 12#define CAMERAHEIGHT 2048 13 14using namespace std; 15using namespace cv; 16 17// 18// 平面展開の対応点を取得する関数 19// 20//この部分は、授業で習った数式で愚直に計算しました。 21unordered_map<int,Point2d>getFisheyePoint() 22{ 23 //焦点距離[pixel] 24 double pixel_size = 3.45; 25 double focus_mm = 1.8; 26 double focus = focus_mm * 1000 / pixel_size; 27 28 //画像中心までの距離を計算 29 double angle = ANGLE * 2 * M_PI / 360; 30 double d = CAMERAWIDTH / (2 * tan(angle / 2)); 31 32 //画像中心と任意の平面座標Aの距離r 33 double r = 0; 34 35 //点Aの画角を計算 36 double c = 0; 37 38 //点Aの回転角phi 39 double phi = 0; 40 41 //点Aに対応する魚眼座標A' 42 Point2d A_dash; 43 44 //A'を格納するA_dash_Map 45 unordered_map<int, Point2d> A_dash_Map; 46 //魚眼座標A'を計算してA_dash_Mapに保存 47 for (int j = 0;j < CAMERAHEIGHT;j++) 48 { 49 for (int i = 0;i < CAMERAWIDTH;i++) 50 { 51 r = sqrt(pow((i - CAMERAWIDTH / 2), 2) + pow((j - CAMERAHEIGHT / 2), 2)); 52 if (r == 0)continue; 53 c = atan(r / d); 54 phi = acos((i - (CAMERAWIDTH / 2)) / r); 55 A_dash.x = round(focus * c * cos(phi)); 56 if (j <= CAMERAHEIGHT / 2) 57 { 58 A_dash.y = round(focus * c * sin(phi)); 59 } 60 else 61 { 62 A_dash.y = -round(focus * c * sin(phi)); 63 } 64 A_dash_Map.insert(make_pair(j * CAMERAWIDTH + i, A_dash)); 65 } 66 } 67 return A_dash_Map; 68} 69 70// 71// カメラ撮影を行う関数 72// 73Mat getCameraImage() 74{ 75 VideoCapture cap(CAMERA_ID); 76 Mat src, gray; 77 cap >> src; 78 cvtColor(src, gray, COLOR_BGR2GRAY); 79 return gray; 80} 81 82// 83// 平面展開をする関数 84// 85Mat openFisheye(Mat src, Mat dst, unordered_map<int, Point2d> A_dash_Map) 86{ 87 for (int index = 0;index < CAMERAHEIGHT * CAMERAWIDTH;index++) 88 { 89 //対応点を取得する際に座標系がずれているのでここで調節しています。 90 dst.data[index] = src.at<uchar>((CAMERAHEIGHT / 2) - A_dash_Map[index].y, A_dash_Map[index].x + (CAMERAWIDTH / 2)); 91 } 92 return dst; 93} 94 95// 96// main関数 97// 98int main() 99{ 100 cout << "計算開始\n"; 101 unordered_map<int, Point2d > fisheyepoint = getFisheyePoint(); 102 Mat src; 103 Mat open; 104 cout << "撮影開始\n"; 105 src = getCameraImage(); 106 Mat dst = Mat::zeros(Size(CAMERAWIDTH, CAMERAHEIGHT), CV_8UC1); 107 open = openFisheye(src, dst, fisheyepoint); 108 imwrite("open.png", open); 109 cout << "展開終了\n"; 110 111 return 0; 112}
補足情報(FW/ツールのバージョンなど)
OS:bootcampにてMacbookair上でWindous10を動かしています
visual studio2019
CPU:第6世代core-i5
メモリ:8GB
回答1件
あなたの回答
tips
プレビュー