2017年7月31日月曜日

射影変換してみた

スマホのカメラなどでとった写真で斜めになっているものを、正面からみたように変換する射影変換というものがあります。
日産の車の360度アラウンドビューモニターとかで使われているあれですね。

個人でアラウンドビューモニター作ってやろうじゃないの。
ということでいつものように、C++で射影変換書いてみました。

http://wildpie.hatenablog.com/entry/20141112/1415802846
理論とかはこのページに書いてあります。

ベクトルって難しいなぁ。
理論をよく読んでC++で実装します。
といっても関数はOpenCVにあるしね。




このように写真にある四か所の点の座標を与えると勝手に正面から見た画像に変換してくれます。



--------------------------------

#include <stdio.h>
#include <vector>

#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION

#include "core.hpp"
#include "imgproc.hpp"
#include "tracking.hpp"

#include "stb_image.h"
#include "stb_image_write.h"


#define xx 300
#define yy 300

using namespace std;


void changeb_g(unsigned char* p,int x,int y,int c)
{
int ct = x*y;
int i;
unsigned char t;
for (i = 0; i < ct; i++){
t = p[0];
p[0] = p[2];
p[2] = t;
p[3] = 255;
p += c;
}
}

int main()
{
printf("Hello Open CV!\n");
unsigned char*p;
int x=-1, y=-1;
int n;
int i, j;
//load image
p = stbi_load("test.png", &x, &y, &n, 4);
if (p == NULL || x < 1 || y < 1)return 1;

// R<-->B
changeb_g(p, x, y, 4);

cv::Mat img = cv::Mat(y, x, CV_8UC4);

cv::Mat res;

//copy data
memcpy(img.data, p, x * 4 * y);
stbi_image_free(p);

cv::Size sz = cv::Size(xx, yy);

cv::Point2f pts1[] = { { 175, 122 }, { 265, 125 }, { 179, 255 }, { 269, 238 }};
cv::Point2f pts2[] = { { 0, 0 }, { xx, 0 }, { 0, yy }, { xx, yy } };

cv::Mat M = cv::getPerspectiveTransform(pts1, pts2);
cv::warpPerspective(img, res,M, sz);

// R<-->B
changeb_g(res.data, xx, yy, 4);
stbi_write_png("result.png", xx, yy, 4, res.data, 4 * xx);


return 0;
}

--------------------------------



たしかに正しくできた感じ。

0 件のコメント:

コメントを投稿