【C++】双线性差值算法实现RGB图像缩放
双线性差值算法
双线性插值(Bilinear Interpolation)并不是“双线性差值”,它是一种在二维平面上估计未知数据点的方法,通常用于图像处理中的图像缩放。
双线性插值的基本思想是:对于一个未知的数据点,我们找到其最近的4个已知数据点,然后根据这4个已知数据点的值以及它们与未知数据点的距离,来估计未知数据点的值。
具体到图像处理中,如果我们想要将一个图像从一个尺寸放大或缩小到另一个尺寸,我们可以使用双线性插值来估计新尺寸下每个像素点的颜色值。
以下是双线性插值的数学公式:
设我们要估计的点为P(x,y),其最近的4个已知点为A(x0,y0),B(x1,y0),C(x0,y1),D(x1,y1),则P点的值I_P可以表示为:
I_P = I_A * (x1-x)(y1-y) + I_B * (x-x0)(y1-y) + I_C * (x1-x)(y-y0) + I_D * (x-x0)(y-y0)
其中,I_A,I_B,I_C,I_D分别为A,B,C,D点的值。
在实际应用中,我们通常会使用浮点数来表示x和y,这样可以得到更精确的结果。但是,由于x和y可能是小数,所以我们需要使用floor和ceil函数来找到最近的4个整数坐标点。
C++双线性差值算法RGB图像缩放
/**@func Imresize
* @brief 双线性差值算法缩放RGB图片
* @param[out] pfDst 目的图像地址
* @param[in] nW 目的图像宽度
* @param[in] nH 目的图像高度
* @param[in] pfSrc 源图像地址
* @param[in] nOriW 源图像宽度
* @param[in] nOriH 源图像高度
*/
void Imresize(unsigned char *pfDst, int nH, int nW, unsigned char *pfSrc, int nOriH, int nOriW)
{for (int i = 0; i < nH * nW; i++){int row = i / nW;int col = i % nW;float x = (row + 0.5) * nOriH / nH - 0.5;if (x < 0) x = 0;if (x >= nOriH - 1) x = nOriH - 2;int fx = (int)x;x = x - fx;float x1 = 1.0 - x;float y = (col + 0.5) * nOriW / nW - 0.5;if (y < 0) y = 0;if (y >= nOriW - 1) y = nOriW - 2;int fy = (int)y;y = y - fy;float y1 = 1.0 - y;float val_R = (pfSrc[fx * nOriW * 3 + 3 * fy] * x1 * y1 + pfSrc[(fx + 1) * nOriW * 3 + 3 * fy] * x * y1+ pfSrc[fx * nOriW * 3 + (fy + 1) * 3] * x1 * y + pfSrc[(fx + 1) * nOriW * 3 + (fy + 1) * 3] * x * y);float val_G = (pfSrc[fx * nOriW * 3 + 1 + 3 * fy] * x1 * y1 + pfSrc[(fx + 1) * nOriW * 3 + 1 + 3 * fy] * x * y1+ pfSrc[fx * nOriW * 3 + 1 + (fy + 1) * 3] * x1 * y + pfSrc[(fx + 1) * nOriW * 3 + 1 + (fy + 1) * 3] * x * y);float val_B = (pfSrc[fx * nOriW * 3 + 2 + 3 * fy] * x1 * y1 + pfSrc[(fx + 1) * nOriW * 3 + 2 + 3 * fy] * x * y1+ pfSrc[fx * nOriW * 3 + 2 + (fy + 1) * 3] * x1 * y + pfSrc[(fx + 1) * nOriW * 3 + 2 + (fy + 1) * 3] * x * y);pfDst[i * 3] = unsigned char(val_B);pfDst[i * 3 + 1] = unsigned char(val_G);pfDst[i * 3 + 2] = unsigned char(val_R);}
}
使用OpenCV库实现双线性差值算法RGB图像缩放
#include <opencv2/opencv.hpp>cv::Mat bilinearInterpolation(const cv::Mat& src, int newWidth, int newHeight) {cv::Mat dst(newHeight, newWidth, CV_8UC3);float x_ratio = src.cols / (float)newWidth;float y_ratio = src.rows / (float)newHeight;for(int dst_y = 0; dst_y < newHeight; dst_y++) {for(int dst_x = 0; dst_x < newWidth; dst_x++) {// 计算源图像中的位置float src_x = (dst_x + 0.5f) * x_ratio - 0.5f;float src_y = (dst_y + 0.5f) * y_ratio - 0.5f;// 找到最邻近的四个像素点int x0 = floor(src_x);int y0 = floor(src_y);int x1 = ceil(src_x);int y1 = ceil(src_y);// 确保坐标在图像范围内x0 = std::min(std::max(0, x0), src.cols - 2);y0 = std::min(std::max(0, y0), src.rows - 2);x1 = std::min(std::max(0, x1), src.cols - 2);y1 = std::min(std::max(0, y1), src.rows - 2);// 双线性插值计算float dx = src_x - x0;float dy = src_y - y0;cv::Vec3b top = src.at<cv::Vec3b>(y0, x0) * (1 - dx) + src.at<cv::Vec3b>(y0, x1) * dx;cv::Vec3b bottom = src.at<cv::Vec3b>(y1, x0) * (1 - dx) + src.at<cv::Vec3b>(y1, x1) * dx;dst.at<cv::Vec3b>(dst_y, dst_x) = top * (1 - dy) + bottom * dy;}}return dst;
}
使用双线性差值算法需要注意的点
使用双线性插值算法时,需要注意以下几点:
-
边界处理:在计算目标像素对应的源图像坐标时,可能会出现超出边界的情况。例如,如果目标像素对应的位置在源图像的边界之外,那么你就找不到四个邻近的像素。这时,你可能需要做一些特殊的处理,比如将坐标限制在图像的边界内,或者使用边界上的像素值进行插值。
-
精度问题:双线性插值涉及到浮点数运算,可能会有精度损失。此外,如果你的目标图像的尺寸远大于源图像,那么可能会出现“模糊”的效果,这是因为插值算法无法创造出新的信息。
-
颜色空间:如果你处理的是彩色图像,那么你需要对每个颜色通道分别进行插值。在某些情况下,可能需要考虑颜色空间的影响,例如在HSV颜色空间中,色相(H)通道的插值可能需要特殊处理,因为它是一个循环的量。
-
性能问题:双线性插值需要对每个像素进行四次访问和一次乘法操作,这可能会导致性能问题。如果你需要处理大尺寸的图像,或者需要实时处理图像,那么你可能需要考虑使用更高效的算法,或者使用硬件加速。
-
其他插值方法:双线性插值只是众多插值方法中的一种,还有最近邻插值、双三次插值等方法。不同的插值方法有不同的优缺点,你需要根据你的具体需求选择最适合的插值方法。
相关文章:
【C++】双线性差值算法实现RGB图像缩放
双线性差值算法 双线性插值(Bilinear Interpolation)并不是“双线性差值”,它是一种在二维平面上估计未知数据点的方法,通常用于图像处理中的图像缩放。 双线性插值的基本思想是:对于一个未知的数据点,我…...
计算机网络知识普及之四元组
在涉及到TCP/UDP等IP类通信协议时,存在四元组概念 这里只是普及使用 先来一些前置知识,什么是IP协议? IP协议全称为互联网协议,处于网络层中,主要作用是标识网络中的设备,每个设备的IP地址是唯一的。 在网…...
深度探讨网络安全:挑战、防御策略与实战案例
目录 编辑 一、引言 二、网络安全的主要挑战 恶意软件与病毒 数据泄露 分布式拒绝服务攻击(DDoS) 内部威胁 三、防御策略与实战案例 恶意软件防护 网络钓鱼防护 数据泄露防护 总结 一、引言 随着信息技术的迅猛发展,网络安全问…...
“穿越时空的机械奇观:记里鼓车的历史与科技探秘“
在人类文明的发展历程中,科技的创新与进步不仅仅推动了社会的进步,也为我们留下了丰富的文化遗产。记里鼓车,作为一种古老的里程计量工具,其历史地位和技术成就在科技史上具有重要的意义。本文将详细介绍记里鼓车的起源、结构原理…...
DevOps CMDB平台整合Jira工单
背景 在DevOps CMDB平台建设的过程中,我们可以很容易的将业务应用所涉及的云资源(WAF、K8S、虚拟机等)、CICD工具链(Jenkins、ArgoCD)、监控、日志等一次性的维护到CMDB平台,但随着时间的推移,…...
Vue-路由
路由简介 SPA单页面应用。导航区和展示区 单页Web应用整个应用只有一个完整的页面点击页面中的导航连接不会刷新页面,只会做页面的局部更新数据需要通过ajax请求获取 路由:路由就是一组映射关系,服务器接收到请求时,根据请求路…...
【Rust入门教程】安装Rust
文章目录 前言Rust简介Rust的安装更新与卸载rust更新卸载 总结 前言 在当今的编程世界中,Rust语言以其独特的安全性和高效性吸引了大量开发者的关注。Rust是一种系统编程语言,专注于速度、内存安全和并行性。它具有现代化的特性,同时提供了低…...
Character.ai因内容审查流失大量用户、马斯克:Grok-3用了10万块英伟达H100芯片
ChatGPT狂飙160天,世界已经不是之前的样子。 更多资源欢迎关注 1、爆火AI惨遭阉割,1600万美国年轻人失恋?Character.ai被爆资金断裂 美国流行的社交软件Character.ai近期对模型进行大幅度内容审查,导致用户感到失望并开始流失。…...
Spring源码九:BeanFactoryPostProcessor
上一篇Spring源码八:容器扩展一,我们看到ApplicationContext容器通过refresh方法中的prepareBeanFactory方法对BeanFactory扩展的一些功能点,包括对SPEL语句的支持、添加属性编辑器的注册器扩展解决Bean属性只能定义基础变量的问题、以及一些…...
大模型笔记1: Longformer环境配置
论文: https://arxiv.org/abs/2004.05150 目录 库安装 LongformerForQuestionAnswering 库安装 首先保证电脑上配置了git. git环境配置: https://blog.csdn.net/Andone_hsx/article/details/87937329 3.1、找到git安装路径中bin的位置,如:D:\Prog…...
类和对象(提高)
类和对象(提高) 1、定义一个类 关键字class 6 class Data1 7 { 8 //类中 默认为私有 9 private: 10 int a;//不要给类中成员 初始化 11 protected://保护 12 int b; 13 public://公共 14 int c; 15 //在类的内部 不存在权限之分 16 void showData(void)…...
免费最好用的证件照制作软件,一键换底+老照片修复+图片动漫化,吊打付费!
这款软件真的是阿星用过的,最好用的证件照制作软件,没有之一! 我是阿星,今天要给大家安利一款超实用的证件照工具,一键换底,自动排版,免费无广告,让你在家就能轻松搞定证件照&#…...
antfu/ni 在 Windows 下的安装
问题 全局安装 ni 之后,第一次使用会有这个问题 解决 在 powershell 中输入 Remove-Item Alias:ni -Force -ErrorAction Ignore之后再次运行 ni Windows 11 下的 Powershell 环境配置 可以参考 https://github.com/antfu-collective/ni?tabreadme-ov-file#how …...
Linux 生产消费者模型
💓博主CSDN主页:麻辣韭菜💓 ⏩专栏分类:Linux初窥门径⏪ 🚚代码仓库:Linux代码练习🚚 🌹关注我🫵带你学习更多Linux知识 🔝 前言 1. 生产消费者模型 1.1 什么是生产消…...
深入浅出:MongoDB中的背景创建索引
深入浅出:MongoDB中的背景创建索引 想象一下,你正忙于将成千上万的数据塞入你的MongoDB数据库中,你的用户期待着实时的响应速度。此时,你突然想到:“嘿,我应该给这些查询加个索引!” 没错&…...
Spring事务十种失效场景
首先我们要明白什么是事务?它的作用是什么?它在什么场景下在Spring框架下会失效? 事务:本质上是由数据库和程序之间交互的过程中的衍生物,它是一种控制数据的行为规则。有几个特性 1、原子性:执行单元内,要…...
JELR-630HS漏电继电器 30-500mA 导轨安装 约瑟JOSEF
JELR-HS系列 漏电继电器型号: JELR-15HS漏电继电器;JELR-25HS漏电继电器; JELR-32HS漏电继电器;JELR-63HS漏电继电器; JELR-100HS漏电继电器;JELR-120HS漏电继电器; JELR-160HS漏电继电器&a…...
如何实现一个简单的链表或栈结构
实现一个简单的链表或栈结构是面向对象编程中的基础任务。下面我将分别给出链表和栈的简单实现。 链表(单链表)的实现 链表是由一系列节点组成的集合,每个节点都包含数据部分和指向列表中下一个节点的链接(指针或引用࿰…...
抖音外卖服务商入驻流程及费用分别是什么?入驻官方平台的难度大吗?
随着抖音关于新增《【到家外卖】内容服务商开放准入公告》的意见征集通知(以下简称“通知”)的发布,抖音外卖服务商入驻流程及费用逐渐成为众多创业者所关注和热议的话题。不过,就当前的讨论情况来看,这个话题似乎没有…...
“小红书、B站崩了”,背后的阿里云怎么了?
导语:阿里云不能承受之重 文 | 魏强 7月2日,“小红书崩了”、“B站崩了”等话题登上了热搜。 据第一财经、财联社等报道,7月2日,用户在B站App无法使用浏览历史关注等内容,消息界面、更新界面、客服界面均不可用&…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
2.3 物理层设备
在这个视频中,我们要学习工作在物理层的两种网络设备,分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间,需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质,假设A节点要给…...
