我们通过相机拍摄的图片存在各种畸变,其中投影畸变使得原本平行的直线不再平行,就会产生照片中近大远小的效果。本文将具体介绍如何利用OPenCV实现从投影图像恢复仿射特性,接下来跟着小编一起学习吧
将这四个点的坐标按照a、b、c、d、c、a、d、b的顺序填入points_3d[8]坐标数组中,第一次运行结束。
第二次运行的主函数:
int main()
{
Mat src = imread("distortion.jpg", IMREAD_GRAYSCALE);
IplImage *src1 = cvLoadImage("distortion.jpg");
//第一步,通过鼠标获取图片中某个点的坐标,运行第一步时注释掉Rectify(points_3d, src, src1);,将获取到的八个点写入
//points_3d[8]矩阵中,因为是齐次坐标,x3 = 1
//GetMouse(src1);
//输入畸变图上的8个关键点
Point3d points_3d[8] = { Point3d(99, 147, 1), Point3d(210, 93, 1), Point3d(144, 184, 1), Point3d(261, 122, 1),
Point3d(144, 184, 1), Point3d(99, 147, 1), Point3d(261, 122, 1), Point3d(210, 93, 1) };
//第二步,校正图像,运行此步骤时注释掉GetMouse(src1);,解除注释Rectify(points_3d, src, src1);
Rectify(points_3d, src, src1);
imshow("yuantu", src);
waitKey(0);
}
校正函数:
void Rectify(Point3d* points, Mat src, IplImage* img)
{
//通过输入的8个点得到4条连线
vector<vector<float>> lines;
int num_lines = 4;
for(int i = 0; i < num_lines; i++)
{
//获取两点连线
GetLineFromPoints(points[2 * i], points[2 * i + 1], lines);
}
//分别求取两个交点
vector<Point3f> intersect_points;
int num_intersect_points = 2;
for (int i = 0; i < num_intersect_points; i++)
{
//计算交点
GetIntersectPoint(lines[2 * i], lines[2 * i + 1], intersect_points);
}
//通过两个交点连线求消失线
vector<vector<float>> vanishing_line;
GetLineFromPoints(intersect_points[0], intersect_points[1], vanishing_line);
//恢复矩阵
float H[3][3] = {{1, 0, 0},
{0, 1, 0},
{vanishing_line[0][0], vanishing_line[0][1], vanishing_line[0][2]}};
Mat image = Mat::zeros(src.rows, src.cols, CV_8UC1);
GetRectifingImage(vanishing_line[0], src, image);
int i = 0;
}
void GetLineFromPoints(Point3d point1, Point3d point2, vector<vector<float>> &lines)
{
vector<float> line;
//定义直线的三个齐次坐标
float l1 = 0;
float l2 = 0;
float l3 = 0;
l1 = (point1.y * point2.z - point1.z * point2.y);
l2 = (point1.z * point2.x - point1.x * point2.z);
l3 = (point1.x * point2.y - point1.y * point2.x);
//归一化
l1 = l1 / l3;
l2 = l2 / l3;
l3 = 1;
line.push_back(l1);
line.push_back(l2);
line.push_back(l3);
lines.push_back(line);
}
void GetIntersectPoint(vector<float> line1, vector<float> line2, vector<Point3f> &intersect_points)
{
Point3f intersect_point;
//定义交点的三个齐次坐标
float x1 = 0;
float x2 = 0;
float x3 = 0;
x1 = (line1[1] * line2[2] - line1[2] * line2[1]);
x2 = (line1[2] * line2[0] - line1[0] * line2[2]);
x3 = (line1[0] * line2[1] - line1[1] * line2[0]);
//归一化
x1 = x1 / x3;
x2 = x2 / x3;
x3 = 1;
intersect_point.x = x1;
intersect_point.y = x2;
intersect_point.z = x3;
intersect_points.push_back(intersect_point);
}
int Round(float x)
{
return (x > 0.0) ? floor(x + 0.5) : ceil(x - 0.5);
}
void GetRectifingImage(vector<float> line, Mat src, Mat dst)
{
Size size_src = src.size();
for (int i = 0; i < size_src.height; i++)
{
for (int j = 0; j < size_src.width; j++)
{
float x3 = line[0] * j + line[1] * i + line[2] * 1;
int x1 = Round(j / x3);
int x2 = Round(i / x3);
if (x1 < size_src.width && x1 >= 0 && x2 < size_src.height && x2 >= 0)
{
dst.at<uint8_t>(x2, x1) = src.at<uint8_t>(i, j);
}
}
}
imshow("src", src);
imshow("dst", dst);
waitKey(0);
}
运行结果如下图:
提取码:qltt
到此这篇关于利用C++ OpenCV 实现从投影图像恢复仿射特性的文章就介绍到这了,更多相关C++ OpenCV 投影图像恢复仿射特性内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!
沃梦达教程
本文标题为:利用C++ OpenCV 实现从投影图像恢复仿射特性


猜你喜欢
- Qt计时器使用方法详解 2023-05-30
- C语言手把手带你掌握带头双向循环链表 2023-04-03
- C语言qsort()函数的使用方法详解 2023-04-26
- Easyx实现扫雷游戏 2023-02-06
- C语言详解float类型在内存中的存储方式 2023-03-27
- 我应该为我的项目使用相对包含路径,还是将包含目录放在包含路径上? 2022-10-30
- c++ const 成员函数,返回一个 const 指针.但是返回的指针是什么类型的 const? 2022-10-11
- ubuntu下C/C++获取剩余内存 2023-09-18
- 详解C语言中sizeof如何在自定义函数中正常工作 2023-04-09
- C++ 数据结构超详细讲解顺序表 2023-03-25