【影像配准】目标影像在参考影像中的自动定位与裁剪(附有完整代码)

       在影像配准时通常要求输入的参考影像和待配准影像是同一地区且尺寸相等,但是在实际应用

时如果要求输入的参考影像和待配准影像是同一地区且尺寸相等的话,则需人工手动裁剪,无形中

增加了工作量!!!

       所以在配准前需要增加一个自动裁剪功能,即输入的参考影像很大,然后根据输入的待配准影

像从参考影像中裁剪出目标区域,然后进行配准!!!

预备知识:了解像素坐标与投影坐标间的转换关系!!!

转换关系见:

像素坐标转投影坐标、投影坐标转像素坐标(附有完整代码及测试结果)_一米九零小胖子的博客-CSDN博客_tfw文件

一、利用待配准影像的投影信息从参考影像中裁剪出目标区域原理 

1、获取待配准影像的左上角投影坐标和右下角投影坐标;

2、该投影坐标即为参考影像中相应区域的左上角投影坐标和右下角投影坐标;

3、把投影坐标转化为像素坐标;

4、利用gdal从原参考影像中裁剪出目标区域(.tif); 

二、利用待配准影像的投影信息从参考影像中裁剪出目标区域代码

#include<iostream>
#include<gdal_priv.h>
#include<gdal.h>
#include<windows.h>
#include<opencv2\imgproc\types_c.h>
#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\highgui\highgui.hpp>

using namespace std;


//获取tif影像的投影信息
void getProj(double* geo, const char* srcTifPath)
{
	GDALAllRegister();

	GDALDataset* podataset = (GDALDataset*)GDALOpen(srcTifPath, GA_ReadOnly);

	//保存 .tif 文件的投影信息' x=geo[0]、y=geo[3]、像素大小=geo[1]
	//double geo[6];

	podataset->GetGeoTransform(geo);
}


//裁剪参考影像中的目标区域
void imageCut(string refpath, string senpath, string dstpath)
{
	//获取两幅影像的投影信息
	double refgeo[6], sengeo[6];

	getProj(refgeo, refpath.c_str());
	getProj(sengeo, senpath.c_str());

	/******使用投影信息在参考影像中截取目标影像******/
	cv::Mat refImage = cv::imread(refpath, -1);
	cv::Mat senImage = cv::imread(senpath, -1);

	int senRow = senImage.rows;
	int senCol = senImage.cols;

	//找到目标影像左上角和右下角坐标:(右下x-左上x)/size=像素宽度,(右下y-左上y)/size=像素宽度
	double senX = senCol * sengeo[1] + sengeo[0];
	double senY = senRow * sengeo[5] + sengeo[3];

	//计算目标影像坐标在参考影像中对应的像素坐标
	int refLeftX = (sengeo[0] - refgeo[0]) / refgeo[1];
	int refLeftY = (refgeo[3] - sengeo[3]) / refgeo[1];
	int refRightX = (senX - refgeo[0]) / refgeo[1];
	int refRightY = (refgeo[3] - senY) / refgeo[1];

	/********创建裁剪后的tif********/

	//裁剪区域的投影信息
	refgeo[0] = sengeo[0];
	refgeo[3] = sengeo[3];

	GDALDataset* poDataset1; //待创建的GDAL数据集 
	GDALDataset* poDataset2; //参考影像影像
	GDALDriver* poDriver;    //驱动,用于创建新的文件

	//gdal打开参考图像
	GDALAllRegister();
	poDataset2 = (GDALDataset*)GDALOpen(refpath.c_str(), GA_ReadOnly);

	//判断是否打开文件
	if (poDataset2 == NULL) { printf("文件打开失败"); }
	else printf("文件打开成功");

	//获取待加入坐标的图像的通道长宽
	int nBandCount = poDataset2->GetRasterCount();
	int nImgSizeX = refRightX - refLeftX;
	int nImgSizeY = refRightY - refLeftY;

	//创建新文件
	char fomat[] = "GTiff";
	poDriver = GetGDALDriverManager()->GetDriverByName(fomat);

	//获取格式类型
	char** papszMetadata = poDriver->GetMetadata();

	//根据文件路径文件名,图像宽,高,波段数,数据类型,文件类型,创建新的数据集
	poDataset1 = poDriver->Create(dstpath.c_str(), nImgSizeX, nImgSizeY, nBandCount, GDT_Byte, papszMetadata);

	//坐标赋值
	poDataset1->SetGeoTransform(refgeo);

	//将原图像数据读出,进行相应处理后,写入新文件
	BYTE* ppafScan = new BYTE[nImgSizeX * nImgSizeY * nBandCount];

	//读取参考影像中的目标区域信息
	poDataset2->RasterIO(GF_Read, refLeftX, refLeftY, nImgSizeX, nImgSizeY, ppafScan, nImgSizeX, nImgSizeY, GDT_Byte, nBandCount, 0, 0, 0, 0);

	//将图像数据写入新图像中
	poDataset1->RasterIO(GF_Write, 0, 0, nImgSizeX, nImgSizeY, ppafScan, nImgSizeX, nImgSizeY, GDT_Byte, nBandCount, 0, 0, 0, 0);

	delete poDataset1;
	delete poDataset2;
}


int main()
{
	string refpath = "..\\testImage\\ref.tif";
	string senpath = "..\\testImage\\sen.tif";
	string dstpath = ".\\imageSave\\dst.tif";

	imageCut(refpath, senpath, dstpath);

	return 0;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据库内核

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值