简单的图像几何校正实践

简单的图像几何校正

几何校正是指遥感成像过程中,受多种因素的综合影响,原始图像上地物的几何位置、形状、大小、尺寸、方位等特征与其对应的地面地物的特征往往是不一致的,这种不一致就是几何变形,也称几何畸变。

几何校正是遥感中的专业名词。一般是指通过一系列的数学模型来改正和消除遥感影像成像时因摄影材料变形、物镜畸变、大气折光、地球曲率、地球自转、地形起伏等因素导致的原始图像上各地物的几何位置、形状、尺寸、方位等特征与在参照系统中的表达要求不一致时产生的变形。

———— 百度百科

投影变换几何校正

参考博客:https://blog.csdn.net/weixin_37195422/article/details/53930891

不过此博客未给出相应实践,所以自己实践一个

实践

因为要使用图像处理,以及矩阵和求解线性方程组,所以需要外部库(也可以纯自己弄,不过很麻烦)

图像库:stb_image ,我的这篇博有说https://blog.csdn.net/qq_40953281/article/details/87902580

矩阵计算库:Eigen, 推荐的教程https://zzk.cnblogs.com/s?w=blog%3Ahoukai%20Eigen

这两个都是只需要导入头文件就可以,不需要配置其他的东西,简单易用

参考博客里面的图片是CSDN压缩过的了,像素信息已经改变,新参数如下

  • 规格 383*268

  • x0

    39 82
    32 106
    266 90
    270 54

  • x1

    38 55
    38 100
    270 100
    270 55

代码如下

#include <iostream>
#include <string>
#include <stdlib.h>
#include <vector>
#include <Eigen3/Dense>

#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>

using namespace std;
using namespace Eigen;

string filePath;
int w, h, n;
const int points = 4;
vector<pair<int, int>> rectBefore;	// 变换前的四边形
vector<pair<int, int>> rectAfter;	// 变换后的矩形位置
Vector4d cX,cY;						// x,y对于的四个参数

void copyTo(unsigned char *src, int x0, int y0, unsigned char *des, int x1, int y1) {
	if ((x1 < 0 || x1 >= w) || (y1 < 0 || y1 >= h)) return; // 出界不考虑
	if ((x0 < 0 || x0 >= w) || (y0 < 0 || y0 >= h)) return; // 出界不考虑
	for (int i = 0; i < n; i++) {
		des[w*n*y1 + n * x1 + i] = src[w*n*y0 + n * x0 + i];
	}
}

pair<int,int> getPos(int x, int y) {
	int x1 = cX[0] * x + cX[1] * y + cX[2] * x*y + cX[3];
	int y1 = cY[0] * x + cY[1] * y + cY[2] * x*y + cY[3];
	return make_pair(x1, y1);
}

int main()
{
	cin >> filePath;
	unsigned char *data = stbi_load(filePath.c_str(), &w, &h, &n, 0);
	unsigned char *copy = NULL;
	if (data == NULL) {
		cout << stbi_failure_reason() << endl;
	}
	else {
		// 复制一份变换用
		copy = (unsigned char*)malloc(w*n*h);
		memset(copy, 0, w*n*h);
		// 获取变换前坐标
		for (int i = 0; i < points; i++) {
			int x, y; cin >> x >> y;
			rectBefore.push_back(make_pair(x, y));
		}
		// 获取变换后坐标,与上一一对应
		for (int i = 0; i < points; i++) {
			int x, y; cin >> x >> y;
			rectAfter.push_back(make_pair(x, y));
		}
		Matrix4d mid;	// 中间矩阵
		Vector4d resX, resY;	// 转换后的xy坐标
		for (int i = 0; i < 4; i++) {
			mid(i, 0) = rectBefore[i].first;
			mid(i, 1) = rectBefore[i].second;
			mid(i, 2) = rectBefore[i].first*rectBefore[i].second;
			mid(i, 3) = 1;
			resX(i) = rectAfter[i].first;
			resY(i) = rectAfter[i].second;
		}
		// 求解线性方程组
		cX = mid.lu().solve(resX);
		cY = mid.lu().solve(resY);
		// 开始转换
		for (int i = 0; i < w; i++) {
			for (int j = 0; j < h; j++) {
				pair<int, int> newPos = getPos(i, j);
				copyTo(data, newPos.first, newPos.second, copy, i, j);
			}
		}
		stbi_write_png("out.png", w, h, n, copy, 0);
		stbi_image_free(data);
		free(copy);
	}
	system("pause");
	return 0;
}

效果如下

双重水印了。。
在这里插入图片描述
在这里插入图片描述

发布了39 篇原创文章 · 获赞 144 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_40953281/article/details/87923734