Opencv 插值方法 总结

一、概括

面试的时候问到了一个图,就是如何将一个算子放缩??我第一反应是resize(),但是后来我转念一想,人家问的是插值方式,今天来总结一下

最邻近插值法原理分析及c++实现_最临近插值法-CSDN博客

我们总常用的插值方式,临近插值 、双线性插值、三次样条插值、拉格朗日插值、多项式、区域插值等

下面我们就一步一步的将其概括出来

二、临近插值

最邻近插值法 : 其核心思想是选取离目标点最近的点作为待插入的新值点

如图:其他的Q12 Q22 Q11  Q21都是已知的像素点,要求插入一个点P

从上图可以看出P到 Q12 最近,那么我就直接将P=Q12

计算两份方向上的缩放后的图像

	int dst_cols = round(src.cols * sx);  // 列  ==xint dst_rows = round(src.rows * sy);  // 行==y

有3*3 --》5*5 ,那么我们可以计算P(3,3)

 sx=5/3

那么 new_i=3/sx=round(9/5)=2;

        new_j=3/sy=round(9/5)=2

P(3,3)=src(2,2)=83

 

void NearestInterpolation(cv::Mat& src, cv::Mat& dst, float sx, float sy)
{//放大的因子 x,y 方向可能会不一样的// 放缩之后的图像的大小int dst_cols = round(src.cols * sx);  // 列  ==xint dst_rows = round(src.rows * sy);  // 行==ydst = cv::Mat(dst_rows, dst_cols, src.type());//灰度图像处理if (src.channels() == 1){for (int i = 0; i < dst.rows; i++){for (int j = 0; j < dst.cols; j++){//插值计算,取最近值插入到新的图像中int i_new = round(i / sy);int j_new = round(j / sx);if (i_new > src.rows - 1){i_new = src.rows - 1;}if (j_new > src.cols - 1){j_new = src.cols - 1;}dst.at<uchar>(i, j) = src.at<uchar>(i_new, j_new);}}}//彩色图像处理else {for (int i = 0; i < dst.rows; i++){for (int j = 0; j < dst.cols; j++){int i_new = round(i / sy);int j_new = round(j / sx);if (i_new > src.rows - 1){i_new = src.rows - 1;}if (j_new > src.cols - 1){j_new = src.cols - 1;}//Bdst.at<cv::Vec3b>(i, j)[0] = src.at<cv::Vec3b>(i_new, j_new)[0];//Gdst.at<cv::Vec3b>(i, j)[1] = src.at<cv::Vec3b>(i_new, j_new)[1];//Rdst.at<cv::Vec3b>(i, j)[2] = src.at<cv::Vec3b>(i_new, j_new)[2];}}}
}

优点:简单、计算量小。
缺点:效果不好,图像放大后失真现象严重。

 

三、线性插值 

resize() 函数默认的就是双线性插值,

我们先看线性插值:

线性插值:


然后我们将上面的做个变性,就写成了如下:

 双线性插值原理

顾名思义就是做两次线性插值,但是其实是3次

c++ opencv图像双线性插值的应用方法 - 知乎

案例:

 算法流程:

1、先通过每个方向的缩放因子,计算出我们缩放后的图像的大小

2、计算通过新图像的row_new 和col_new 推算出原图像中的四个点 的位置并获得四个点的灰度值

3、通过上面拿到的公式来计算新插入的值

4、计算边界的特殊值


/// <summary>
/// 双线性插值处理
/// </summary>
/// <param name="src"></param>
/// <param name="scale_x"></param>
/// <param name="scale_y"></param>
/// <param name="dst"></param>
void DoubleLineInterpolate(Mat src, double scale_x,double scale_y, Mat& dst)
{int result_H = static_cast<int>(src.rows * scale_y);int result_W = static_cast<int>(src.cols * scale_x);dst = Mat::zeros(cv::Size(result_W, result_H), src.type());for (int i = 0; i < dst.rows; i++){for (int j = 0; j < dst.cols; j++){// 非常重要的一步就是用新的图像来推算出原来图像的四个像素的位置和灰度值double before_x = double(j + 0.5) / scale_x - 0.5f;double before_y = double(i + 0.5) / scale_y - 0.5;int top_y = static_cast<int>(before_y);int bottom_y = top_y + 1;int left_x = static_cast<int>(before_x);int right_x = left_x + 1;//计算变换前坐标的小数部分double u = before_x - left_x;double v = before_y - top_y;// 如果计算的原始图像的像素大于真实原始图像尺寸if ((top_y >= src.rows - 1) && (left_x >= src.cols - 1)){//右下角dst.at<uchar>(i, j) = (1. - u) * (1. - v) * src.at<uchar>(top_y, left_x);}else if (top_y >= src.rows - 1){//最后一行dst.at<uchar>(i, j)= (1. - u) * (1. - v) * src.at<uchar>(top_y, left_x)+ (1. - v) * u * src.at<uchar>(top_y, right_x);}else if (left_x >= src.cols - 1){dst.at<uchar>(i, j)= (1. - u) * (1. - v) * src.at<uchar>(top_y, left_x)+ (v) * (1. - u) * src.at<uchar>(bottom_y, left_x);}else{dst.at<uchar>(i, j)= (1. - u) * (1. - v) * src.at<uchar>(top_y, left_x)+ (1. - v) * (u)*src.at<uchar>(top_y, right_x)+ (v) * (1. - u) * src.at<uchar>(bottom_y, left_x)+ (u) * (v)*src.at<uchar>(bottom_y, right_x);}}}  
}

 

 

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

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

相关文章

Python与C++的对比——跟老吕学Python编程

Python与C的对比——跟老吕学Python编程 Python与C的对比1.C编译型 vs Python解释型2.执行效率3.开发效率4.跨平台5.可移植性6.内存管理机制7.易学性8.静态类型 vs 动态类型9.面向对象编程概念10.垃圾回收11.应用领域 Python与C的对比表 Python与C的对比 Python和C都是最受欢迎…

数据结构小记【Python/C++版】——散列表篇

一&#xff0c;基础概念 散列表&#xff0c;英文名是hash table&#xff0c;又叫哈希表。 散列表通常使用顺序表来存储集合元素&#xff0c;集合元素以一种很分散的分布方式存储在顺序表中。 散列表是一个键值对(key-item)的组合&#xff0c;由键(key)和元素值(item)组成。键…

解密阿里巴巴面试题:如何设计一个微博?

亲爱的小米科技粉丝们,大家好呀!今天小米带来了一则热门话题——阿里巴巴面试题:如何设计一个微博?别着急,跟着小米一起来揭秘吧! 实现哪些功能? 在设计微博系统时,需要考虑实现哪些功能才能满足用户的需求。除了基本的发布推文、时间线、新闻推送、关注/不允许用户以…

【JavaScript 漫游】【034】AJAX

文章简介 本篇文章为【JavaScript 漫游】专栏的第 034 篇文章&#xff0c;对浏览器模型的 XMLHttpRequest 对象&#xff08;AJAX&#xff09;的知识点进行了总结。 XMLHttpRequest 对象概述 浏览器与服务器之间&#xff0c;采用 HTTP 协议通信。用户在浏览器地址栏键入一个网…

Java项目源码基于springboot的家政服务平台的设计与实现

大家好我是程序员阿存&#xff0c;在java圈的辛苦码农。辛辛苦苦板砖&#xff0c;今天要和大家聊的是一款Java项目源码基于springboot的家政服务平台的设计与实现&#xff0c;项目源码以及部署相关请联系存哥&#xff0c;文末附上联系信息 。 项目源码&#xff1a;Java基于spr…

虚拟机镜像iso下载

MSDN, 我告诉你 - 做一个安静的工具站 (itellyou.cn)

CANalyzer使用_00 概述

计划写一个专题&#xff0c;该专题主要介绍CANalyzer的使用&#xff0c;每次文档计划写一个点&#xff0c;自己不累&#xff0c;别人看着也不累&#xff0c;并且方便拓展。本文作为专题的开篇主要介绍下CANalyzer软件的背景&#xff0c;软件界面等信息。 1 软件介绍 CANalyze…

FastAPI 学习笔记

FastAPI 学习笔记 0. 引言1. 快速开始2. 升级示例代码 0. 引言 在 Python 这个充满活力的生态系统中&#xff0c;FastAPI 应运而生&#xff0c;它是一个现代的、快速的 Web 框架&#xff0c;专注于构建 RESTful API。 无论你是一名有经验的 Python 开发人员&#xff0c;还是一…

HTTP/2、HTTP/3对HTTP/1.1的性能改进和优化

HTTP/1.1 相比 HTTP/1.0 提高了什么性能&#xff1f; 性能上的改进&#xff1a; 使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。 支持管道&#xff08;pipeline&#xff09;网络传输&#xff0c;只要第一个请求发出去了&#xff0c;不必等其回来&#xff0c;就可以…

Purple Pi OH鸿蒙开发板7天入门OpenHarmony开源鸿蒙教程【五】

在完成了Purple Pi OH大部分的接口测试之后&#xff0c;紧接着就是一个充满挑战的任务——利用SDK来编译生成我们自己的镜像文件。通过这一过程&#xff0c;不仅能够让你获得一个可在真实硬件上运行的系统镜像&#xff0c;更重要的是&#xff0c;它让你对OpenHarmony系统的构建…

Qt - 信号和槽

目录 一、信号 二、槽 三、信号和槽的使用 (一) 连接信号和槽 (二) 自定义槽 (三) 通过 Qt Creator生成信号槽代码 (四) 自定义信号 四、带参数的信号和槽 五、信号与槽的断开 六、Qt4版本信号与槽的连接 (一) Qt4版本信号与槽连接的优缺点 一、信号 在 Qt 中&…

CubeMX使用教程(5)——定时器PWM输出

本篇我们将利用CubeMX产生频率固定、占空比可调的两路PWM信号输出 例如PA6引脚输出100Hz的PWM&#xff1b;PA7引脚输出500Hz的PWM&#xff0c;双路同时输出 我们还是利用上一章定时器中断的工程进行学习&#xff0c;这样比较方便 首先打开CubeMX对PA6、PA7进行GPIO配置 注&a…

Mixamo动画素材导入UE5的最简单方法

一、Mixamo素材 官网&#xff1a;https://www.mixamo.com/ Mixamo是Adobe公司出品的免费动画库&#xff0c;可商用。软件分为characters(角色&#xff09;、Animations&#xff08;动画)两个部分。 二、辅助工具MIXAMO CONVERTER 官网&#xff1a;https://terribilisstudio…

C#与WPF通用类库

个人集成封装&#xff0c;仓库已公开 NetHelper 集成了一些常用的方法&#xff1b; 如通用的缓存静态操作类、常用的Wpf的ValueConverters、内置的委托类型、通用的反射加载dll操作类、Wpf的ViewModel、Command、Navigation、Messenger、部分常用UserControls(可绑定的Passwo…

通信总线协议之CAN-FD协议详解

文章目录 通信总线之CAN-FD总线协议详解1. CAN-FD 简介1.1 什么是CAN FD1.2 CAN FD的特点 2. CAN-FD总线协议2.1 帧起始2.2 仲裁段2.3 控制段2.4 数据段2.5 CRC段2.6 ACK段2.7 帧结束 3. 如何从传统的CAN升级到CAN FD 通信总线之CAN-FD总线协议详解 1. CAN-FD 简介 1.1 什么是…

selenium高级应用

常见控件应用 复杂的控件操作1.操作Ajax选项2.滑动滑块操作 WebDriver的特殊操作元素class值包含空格property、attribute、text的区别定位动态id 截图功能页面截图页面截图&#xff0c;返回截图的二进制数据页面截图&#xff0c;返回base64的字符串截取指定元素。先定位元素&a…

Redis常见数据类型下

目录 Hash 哈希 常用指令 HSET HGET HEXISTS HDEL HKEYS HVALS HGETALL HMGET 内部编码 Hash类型和关系型数据库 缓存方式对比 List 列表 特点 常用命令 LPUSH LPUSHX RPUSH RPUSHX LRANGE LPOP / RPOP LINDEX LINSERT 阻塞(BLOCK)版…

【Linux】文件缓冲区|理解文件系统

目录 预备知识 观察现象 第一&#xff1a;携带\n&#xff0c;不使用fork()&#xff0c;打印到显示器 第二&#xff1a;携带\n&#xff0c;使用fork()&#xff0c;打印到显示器 第三&#xff1a;携带\n&#xff0c;使用fork()&#xff0c;打印到文件里 第四&#xff1a;不携…

如何选择适合的G口大流量服务器?

G口大流量服务器是指接入互联网的带宽达到1Gbps及以上&#xff0c;并且能够提供大量数据传输服务的服务器。那么如何选择适合的G口大流量服务器&#xff0c;RAK部落小编为您整理发布选择适合的G口大流量服务器需要考虑哪些关键点。 选择适合的G口大流量服务器时&#xff0c;应该…

JavaSec 基础之 CC1 链

文章目录 背景环境以及配置分析0x1 终点(利用点分析)0x20x30x310x320x33 0x040x05 背景 Apache Commons Collections是Apache提供的一个Java库&#xff0c;它扩展了Java自带的集合框架。通过这个库&#xff0c;咱们可以使用更多种类的集合类型&#xff0c;以及各种实用的集合操…