-
-
Save goldengrape/b666a0e822f6da7b56c0c626b7b140a5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// main.cpp | |
// warp_in_one_window | |
// | |
// Created by GoldenGrape on 2020/6/8. | |
// Copyright © 2020 goldengrape. All rights reserved. | |
// | |
#include "opencv2/imgproc.hpp" | |
#include "opencv2/imgcodecs.hpp" | |
#include "opencv2/highgui.hpp" | |
#include "opencv2/calib3d.hpp" | |
#include <iostream> | |
using namespace std; | |
using namespace cv; | |
vector<Point2f> d_corner(4); | |
vector<Point2f> o_corner(4); | |
float width, height; | |
bool dragging=false; | |
int selected_corner_i=-1; | |
Mat H, H_inv; | |
void init_corners(vector<Point2f> &corner, float width, float height); | |
void point_warp(Point2f &p_target, const Point2f &p, const Mat &H); | |
void onMouse(int event, int x, int y, int, void*); | |
int main(int argc, const char * argv[]) { | |
// 读取图像 | |
String filename="/Volumes/macTF/lena.png"; | |
Mat img=imread(filename); | |
width=img.cols; height=img.rows; | |
// 初始设置参考点为四角 | |
init_corners(d_corner,width,height); | |
init_corners(o_corner, width, height); | |
// 初始化映射矩阵, 实际上是单位矩阵 | |
H = findHomography(o_corner, d_corner); | |
H_inv=H; | |
// 设置鼠标控制 | |
String win_name="Only one window"; | |
namedWindow(win_name); | |
setMouseCallback(win_name, onMouse, 0); | |
// 显示变换图像 | |
bool endProgram = false; | |
while(!endProgram){ | |
// 控制按键 | |
char c = (char)waitKey( 10 ); | |
// 按q、Q、esc退出 | |
if ((c == 'q') | (c == 'Q') | (c == 27)) | |
{ | |
endProgram = true; | |
} | |
// 按r、R旋转 | |
if ((c == 'r') | (c == 'R')) | |
{ | |
o_corner.push_back(o_corner[0]); | |
o_corner.erase(o_corner.begin()); | |
} | |
// 计算映射矩阵H和逆矩阵H_inv | |
H = findHomography(o_corner, d_corner); //get homography | |
H_inv= findHomography(d_corner, o_corner); | |
// 将原始图像映射到新位置上 | |
Mat warped_image; | |
warpPerspective(img, warped_image, H, Size(width,height)); | |
imshow(win_name, warped_image); | |
} | |
return 0; | |
} | |
void init_corners(vector<Point2f> &corner, float width, float height){ | |
// 初始化时, 将四角作为参考点 | |
corner[0]=Point2f(0,0); | |
corner[1]=Point2f(width,0); | |
corner[2]=Point2f(width,height); | |
corner[3]=Point2f(0,height); | |
} | |
void onMouse(int event, int x, int y, int, void*){ | |
// 有点复杂 | |
// 当鼠标按下时在变形图上找到一点(x,y), 然后找到这一点在原始图上的位置o_corner | |
// 当鼠标拖动时, 相当于要将原始图上o_corner映射到鼠标点位置 | |
if(event == EVENT_LBUTTONDOWN){ | |
// 以四个象限来规定鼠标点的所属 | |
if (x<width/2){ | |
selected_corner_i=(y < height/2)?0:3; | |
} else if (x>=width/2){ | |
selected_corner_i=(y < height/2)?1:2; | |
} | |
dragging= true; | |
d_corner[selected_corner_i]=Point2f((float)x,(float)y); | |
// 通过映射矩阵的逆矩阵H_inv, 计算当前(x,y)点在原始图的位置 | |
point_warp(o_corner[selected_corner_i], | |
d_corner[selected_corner_i], | |
H_inv); | |
} else if (event==EVENT_LBUTTONUP) { | |
dragging= false; | |
} | |
if (dragging & (event == EVENT_MOUSEMOVE) ){ | |
d_corner[selected_corner_i]=Point2f((float)x,(float)y); | |
} | |
} | |
void point_warp(Point2f &p_target, const Point2f &p, const Mat &H){ | |
// 映射矩阵H是一个3x3的矩阵, | |
// s*[p_target.x, p_target.y, 1]= H * [p.x, p.y, 1] | |
// 乘出来以后要对第三项归一化 | |
Mat p_vector = (Mat_ <double>(3, 1) << p.x,p.y, 1); | |
p_vector = H * p_vector; | |
p_target.x=(float)(p_vector.at<double>(0)/p_vector.at<double>(2)); | |
p_target.y=(float)(p_vector.at<double>(1)/p_vector.at<double>(2)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment