ITK-重采样

news2024/9/20 12:16:21

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

什么是重采样

       重采样(Resampling) 是一种用于图像处理的技术,主要应用于对图像进行尺寸调整、旋转、平移、变形等几何变换时重构像素数据。在图像处理中的重采样,是通过插值计算在新图像坐标系下的像素值,以保证图像在几何变换后的视觉效果和数据准确性。

       重采样的主要目的:

  •  尺寸缩放:改变图像的分辨率,使其变大或变小。例如,缩小图像可用于节省存储空间或加速处理,而放大图像用于查看细节。
  • 旋转、平移、仿射变换:对图像进行各种几何变换,保持图像特征不失真。
  • 图像配准:将一幅图像对齐到另一幅图像中,通常用于医学图像处理、多视角影像合成等领域。 

       重采样的过程:

  •  几何变换:根据目标图像的需求(缩放、旋转、平移等),使用相应的几何变换(如仿射变换、刚体变换)将原图像的坐标映射到新图像的坐标系。
  • 插值计算:由于原始图像中的像素点坐标通常不能直接映射到新图像中的整数坐标,需要通过插值算法(如线性插值、双三次插值等)来估算新位置像素值。
  • 输出图像生成:根据插值计算得到的像素值生成新的图像。 

       重采样的核心之一是插值方法,用于计算新图像中每个像素点的值。常见的插值方法有:

  •  最近邻插值

    • 最简单的插值方法,新像素值取与之最近的旧像素点的值。
    • 优点:计算量小,速度快。
    • 缺点:图像缩放后容易产生锯齿效应,图像不够平滑。
  • 双线性插值

    • 通过周围 2x2 个像素点的加权平均,计算出新像素值。
    • 优点:生成的图像较平滑,效果好于最近邻插值。
    • 缺点:相比最近邻插值,计算复杂度稍高。
  • 双三次插值

    • 通过周围 4x4 个像素点进行插值计算,考虑更多像素的信息。
    • 优点:图像质量较好,适合大规模缩放。
    • 缺点:计算量较大。
  • 样条插值(Spline Interpolation)

    • 通过样条曲线对图像进行插值,能保证图像边缘的平滑性。
    • 优点:插值精度高,能保留较多细节。
    • 缺点:计算较复杂。 

       重采样的应用:

  •  医学图像处理:重采样用于将多模态(如 CT、MRI)或多时间点图像进行配准,以便医生进行精确分析。
  • 计算机视觉:对图像进行缩放或旋转以适应不同的应用需求,如目标识别、特征提取。
  • 遥感影像处理:遥感影像需要在不同分辨率下进行分析和配准,重采样是关键步骤之一。 

       重采样的挑战:

  • 图像失真:在缩放和旋转等操作中,重采样可能会引入失真,尤其是最近邻插值容易导致锯齿或模糊效果。
  • 计算量:复杂的插值方法(如双三次插值、样条插值)会增加计算时间,在实时处理应用中可能会带来性能问题。

       总结来说,重采样是图像处理中的一种基础技术,能够对图像进行精确的几何变换,适用于图像配准、缩放、旋转等多种应用场景,且插值方法的选择直接影响到处理后的图像质量。

环境准备

参见:Windows下用CMake编译ITK及配置测试_itk配置-CSDN博客

功能解析

       下面以图像扩展2倍为例,展示重采样的使用方法。

1.引入必要的头文件:

#include <itkImage.h>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <itkResampleImageFilter.h>
#include <itkAffineTransform.h>
#include <itkLinearInterpolateImageFunction.h>
#include <itkRescaleIntensityImageFilter.h>
#include <itkJPEGImageIOFactory.h>

2.初始化图像类型和读写器:

// 定义图像类型
typedef itk::Image<unsigned char, 2> ImageType;
typedef itk::ImageFileReader<ImageType> ReaderType;
typedef itk::ImageFileWriter<ImageType> WriterType;
// 注册JPEG格式支持
itk::JPEGImageIOFactory::RegisterOneFactory();
// 创建读取器和写入器
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();

3.设置文件名:

// 设置要读取和写入的文件
reader->SetFileName("test.jpg");
writer->SetFileName("output_2x_resized.jpg");

4.读取图像信息:

// 读取图像
reader->Update();
// 获取原始图像的大小和空间信息
ImageType::Pointer inputImage = reader->GetOutput();
ImageType::SpacingType inputSpacing = inputImage->GetSpacing();
ImageType::SizeType inputSize = inputImage->GetLargestPossibleRegion().GetSize();
// 计算输出图像的空间信息(将图像扩展为原来的2倍)
ImageType::SpacingType outputSpacing;
outputSpacing[0] = inputSpacing[0] / 2.0;  // 水平方向的间距缩小一半(像素数变成两倍)
outputSpacing[1] = inputSpacing[1] / 2.0;  // 垂直方向的间距缩小一半
ImageType::SizeType outputSize;
outputSize[0] = inputSize[0] * 2;  // 水平方向的像素数扩展为两倍
outputSize[1] = inputSize[1] * 2;  // 垂直方向的像素数扩展为两倍

5.创建仿射变换、插值器、重采样滤波器:

// 创建一个仿射变换,用于调整图像空间
typedef itk::AffineTransform<double, 2> TransformType;
TransformType::Pointer transform = TransformType::New();
transform->SetIdentity();
// 创建插值器(线性插值)
typedef itk::LinearInterpolateImageFunction<ImageType, double> InterpolatorType;
InterpolatorType::Pointer interpolator = InterpolatorType::New();
// 创建重采样滤波器
typedef itk::ResampleImageFilter<ImageType, ImageType> ResampleFilterType;
ResampleFilterType::Pointer resampleFilter = ResampleFilterType::New();
resampleFilter->SetInput(inputImage);
resampleFilter->SetTransform(transform);
resampleFilter->SetInterpolator(interpolator);
resampleFilter->SetOutputSpacing(outputSpacing);
resampleFilter->SetSize(outputSize);
resampleFilter->SetOutputOrigin(inputImage->GetOrigin());
resampleFilter->SetOutputDirection(inputImage->GetDirection());
// 执行重采样
try
{
	resampleFilter->Update();
}
catch (itk::ExceptionObject &error)
{
	std::cerr << "Error: " << error << std::endl;
	return EXIT_FAILURE;
}

6.连接过滤器输出到写入器并执行写入操作:

// 保存输出图像
writer->SetInput(resampleFilter->GetOutput());
try
{
	writer->Update();
}
catch (itk::ExceptionObject &error)
{
	std::cerr << "Error: " << error << std::endl;
	return EXIT_FAILURE;
}

完整代码

#include <itkImage.h>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <itkResampleImageFilter.h>
#include <itkAffineTransform.h>
#include <itkLinearInterpolateImageFunction.h>
#include <itkRescaleIntensityImageFilter.h>
#include <itkJPEGImageIOFactory.h>

int main()
{
	// 定义图像类型
	typedef itk::Image<unsigned char, 2> ImageType;
	typedef itk::ImageFileReader<ImageType> ReaderType;
	typedef itk::ImageFileWriter<ImageType> WriterType;

	// 注册JPEG格式支持
	itk::JPEGImageIOFactory::RegisterOneFactory();

	// 创建读取器和写入器
	ReaderType::Pointer reader = ReaderType::New();
	WriterType::Pointer writer = WriterType::New();

	// 设置要读取和写入的文件
	reader->SetFileName("test.jpg");
	writer->SetFileName("output_2x_resized.jpg");

	// 读取图像
	reader->Update();

	// 获取原始图像的大小和空间信息
	ImageType::Pointer inputImage = reader->GetOutput();
	ImageType::SpacingType inputSpacing = inputImage->GetSpacing();
	ImageType::SizeType inputSize = inputImage->GetLargestPossibleRegion().GetSize();

	// 计算输出图像的空间信息(将图像扩展为原来的2倍)
	ImageType::SpacingType outputSpacing;
	outputSpacing[0] = inputSpacing[0] / 2.0;  // 水平方向的间距缩小一半(像素数变成两倍)
	outputSpacing[1] = inputSpacing[1] / 2.0;  // 垂直方向的间距缩小一半

	ImageType::SizeType outputSize;
	outputSize[0] = inputSize[0] * 2;  // 水平方向的像素数扩展为两倍
	outputSize[1] = inputSize[1] * 2;  // 垂直方向的像素数扩展为两倍

	// 创建一个仿射变换,用于调整图像空间
	typedef itk::AffineTransform<double, 2> TransformType;
	TransformType::Pointer transform = TransformType::New();
	transform->SetIdentity();

	// 创建插值器(线性插值)
	typedef itk::LinearInterpolateImageFunction<ImageType, double> InterpolatorType;
	InterpolatorType::Pointer interpolator = InterpolatorType::New();

	// 创建重采样滤波器
	typedef itk::ResampleImageFilter<ImageType, ImageType> ResampleFilterType;
	ResampleFilterType::Pointer resampleFilter = ResampleFilterType::New();
	resampleFilter->SetInput(inputImage);
	resampleFilter->SetTransform(transform);
	resampleFilter->SetInterpolator(interpolator);
	resampleFilter->SetOutputSpacing(outputSpacing);
	resampleFilter->SetSize(outputSize);
	resampleFilter->SetOutputOrigin(inputImage->GetOrigin());
	resampleFilter->SetOutputDirection(inputImage->GetDirection());

	// 执行重采样
	try
	{
		resampleFilter->Update();
	}
	catch (itk::ExceptionObject &error)
	{
		std::cerr << "Error: " << error << std::endl;
		return EXIT_FAILURE;
	}

	// 保存输出图像
	writer->SetInput(resampleFilter->GetOutput());
	try
	{
		writer->Update();
	}
	catch (itk::ExceptionObject &error)
	{
		std::cerr << "Error: " << error << std::endl;
		return EXIT_FAILURE;
	}

	std::cout << "Image resized to 2x original size successfully!" << std::endl;
	return EXIT_SUCCESS;
}

测试效果 

       如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2108711.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【专项刷题】— 栈

1、删除字符串中的所有相邻重复项 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 使用栈进行操作&#xff0c;每次入栈的时候和栈顶元素进行比对&#xff0c;如果相同的话就弹出栈顶元素也可以用数组来模拟栈进行操作代码&#xff1a; public String removeDuplica…

基于人工智能的交通标志识别系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 交通标志识别系统是自动驾驶和智能交通的重要组成部分&#xff0c;能够帮助车辆自动识别路边的交通标志并作出相应的决策。通过使用深…

C语言-数据结构 无向图普里姆Prim算法(邻接矩阵存储)

Prim算法使用了贪心的思想&#xff0c;在算法中使用了两个数组&#xff0c;这两个数组会非常巧妙的操作整个算法的灵魂过程 lowcost的功能&#xff1a; 1.帮助算法寻找到当前距离已完成的最小生成树集合的最小的边长&#xff08;找到新边&#xff09; 2.在整个过程中记录新结…

分拣机介绍及解决方案细节

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 完整版文件和更多学习资料&#xff0c;请球友到知识星球【智能仓储物流技术研习社】自行下载。 这份文件是关于交叉带式分拣机的介绍及解…

openSSL 如何降版本

文章目录 前言openSSL 如何降版本1. 卸载2. 安装新的openssl版本3. 验证 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&…

RT-Thread 使用HTTP固件下载方式进行OTA远程升级

参考资料:RT-T官网资料如下链接所示 STM32通用Bootloader (rt-thread.org) 1.app程序env配置过程 参考上述资料中"制作 app 固件"章节&#xff0c;分区大小根据自己设备而定&#xff0c;以下是我以407VET6为例设置的fal分区 notes:上述分区是由片内flash(on-chip)…

机械革命imini Pro820迷你主机评测和拆解,8845H小主机使用政府补贴仅需两千三

机械革命imini Pro820迷你主机评测和拆解&#xff0c;8845H小主机使用政府补贴仅需两千三。 最近上线了家电补贴相关的活动&#xff0c;最高可以补贴20%&#xff0c;然后就看到了这款mini主机感觉很划算就下单了&#xff0c;用来替换我旧的N5095小主机&#xff0c;当服务器用。…

电子技术基础

目录 二极管 二极管的概念二极管的整流 二极管的防反接 二极管的钳位稳压二极管 三极管 NPN型三极管PNP型三极管三极管的三种状态三极管三个极之间电流的关系 放大电路 三极管共射极放大电路分压式偏置电路静态工作点多级放大功率放大电路 运算放大器 同相比例放大器反相…

旅行商问题 | Matlab基于混合粒子群算法GA-PSO的旅行商问题TSP

目录 效果一览基本介绍建模步骤程序设计参考资料 效果一览 基本介绍 混合粒子群算法GA-PSO是一种结合了遗传算法&#xff08;Genetic Algorithm, GA&#xff09;和粒子群优化算法&#xff08;Particle Swarm Optimization, PSO&#xff09;的优化算法。在解决旅行商问题&#…

「Python数据分析」Pandas进阶,使用groupby分组聚合数据(三)

​在实际数据分析和处理过程中&#xff0c;我们可能需要灵活对分组数据进行聚合操作。这个时候&#xff0c;我们就需要用到用户自定义函数&#xff08;User-Defined Functions&#xff0c;UDFs&#xff09;。 使用用户自定义函数进行聚合 使用用户自定义函数聚合时的性能&…

联想泄露显示本月推出更便宜的Copilot Plus电脑

联想似乎准备推出新的更实惠的 Copilot Plus 电脑。可靠的爆料者Evan Blass发布了一份来自联想的新闻稿&#xff0c;详细介绍了将在本周晚些时候的IFA展会上宣布的各种Copilot Plus电脑&#xff0c;其中包括两款采用尚未公布的8核高通骁龙X Plus芯片的电脑。 这些新的高通芯片…

Qt 创建一个json数组对象写入文档并从文档读出q

void createJsonArray() { // 创建一个JSON数组 QJsonArray jsonArray; // 创建一些JSON对象并添加到数组中 for (int i 0; i < 3; i) { QJsonObject jsonObject; jsonObject["key" QString::number(i)] "value" QStri…

原点安全荣获“AutoSec Awards 安全之星”优秀汽车数据安全合规方案奖

9月3日&#xff0c;「AutoSec 2024第八届中国汽车网络安全周暨第五届智能汽车数据安全展」在上海盛大开幕。本届大会由谈思实验室和谈思汽车主办、上海市车联网协会联合主办&#xff0c;以汽车“网络数据安全、软件安全、功能安全”为主题&#xff0c;汇聚了国内外的技术专家、…

Meta关闭Spark AR平台:未来规划与影响分析

Meta宣布将关闭其移动AR创作平台Spark AR&#xff0c;这一消息在业界引起了广泛关注。尽管Snap和TikTok在AR滤镜领域取得了巨大成功&#xff0c;但Meta却选择了另一条发展道路。本文将探讨这一决策背后的可能原因及其对未来的影响。 关闭Spark AR平台的背后 硬件为主&#xff…

PyTorch 创建数据集

图片数据和标签数据准备 1.本文所用图片数据在同级文件夹中 ,文件路径为train/’ 2.标签数据在同级文件&#xff0c;文件路径为train.csv 3。将标签数据提取 train_csvpd.read_csv(train.csv)创建继承类 第一步&#xff0c;首先创建数据类对象 此时可以想象为单个数据单元的…

【PyTorch】基础环境如何打开

前期安装可以基于这个视频&#xff0c;本文是为了给自己存档如何打开pycharm和jupyter notebookPyTorch深度学习快速入门教程&#xff08;绝对通俗易懂&#xff01;&#xff09;【小土堆】_哔哩哔哩_bilibili Pycharm 配置 新建项目的时候选择解释器pytorch-gpu即可。 Jupyte…

【C++ 第二十二章】C++的类型转换

1.C语言中的类型转换 在C语言中&#xff0c;如果赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类型不匹配&#xff0c;或者返回值类型与接收返回值类型不一致时&#xff0c;就需要发生类型转化&#xff0c;C语言中总共有两种形式的类型转换&#xff1a;隐式类型转换和…

CDA数据分析一级考试备考攻略

一、了解考试内容和结构 CDA一级考试主要涉及的内容包括&#xff1a;数据分析概述与职业操守、数据结构、数据库基础与数据模型、数据可视化分析与报表制作、Power BI应用、业务数据分析与报告编写等。 CDA Level Ⅰ 认证考试大纲:https://www.cdaglobal.com/certification.h…

一文还原时序数据库 IoTDB 在 TPCx-IoT 的测试全流程!

在云服务硬件环境下&#xff0c;IoTDB 写入、查询、利用资源能力均表现出色&#xff01; 之前&#xff0c;我们为大家介绍了基于 IoTDB 的企业级产品 TimechoDB&#xff0c;在 TPCx-IoT 基准测试中打破世界纪录&#xff0c;取得的双指标第一成绩&#xff0c;和选择 TPCx-IoT 的…

【Python机器学习】核心数、进程、线程、超线程、L1、L2、L3级缓存

如何知道自己电脑的CPU是几核的,打开任务管理器(同时按下:Esc键、SHIFT键、CTRL键) 然后,点击任务管理器左上角的性能选项,观察右下角中的内核:后面的数字,就是你CPU的核心数,下图中我的是16个核心的。 需要注意的是,下面的逻辑处理器:32 表示支持 32 线程(即超线…