OpenCV的resize函数优化

article/2025/9/24 17:53:01

背景

在使用OpenCV做图像处理的时候,最常见的问题是c++版本性能不足,以resize函数为例来说明,将size为[864,1323,3]的函数缩小一半:

Mat img0;gettimeofday(&t4, NULL);cv::resize(source, img0, cv::Size(cols_out,rows_out));gettimeofday(&t5, NULL);time = 1000*(t5.tv_sec - t4.tv_sec) + (double)(t5.tv_usec - t4.tv_usec)/1000;printf("frank cv::resize = %lf\n", time);output:
frank cv::resize = 13.569000(ms) on Macmini(2.6 GHz Intel Core i5)

需要13ms才能完成这个操作,对于一半应用的实时性要求,要再33ms内处理一帧,超过1/3的时间花在resize上,是非常不合理的。

优化1

针对上面这种1/2大小的resize,可以这样来思考,既然我已经知道输出mat的长宽是输入mat的一半,那么输出mat的每个像素值都是从原图的4个像素得到的一个映射,事实上OpenCV也是用类似的技巧,从原图的点映射到输出图像的像素点,这个映射可以是Nearest Neiborhood,也可以是双线性插值、平均、取左上角等等。对于一般自然图像,我们可以直接使用NN映射来获得输出图像的点。

使用上面的方法:

    double time = 0.0;gettimeofday(&t1, NULL);Mat half_img = resizeByHalf(source, &leftTopInt4);int wh = half_img.cols;int hh = half_img.rows;printf("half_img = %d, %d\n", hh, wh);gettimeofday(&t2, NULL);time = 1000*(t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec)/1000;printf("frank resizeByHalf = %lf\n", time);output:frank resizeByHalf = 10.539000 

时间相比OpenCV的版本,缩小了3ms

优化2 进一步借鉴最邻近算法

如果我们不是resize到1/2等特定的长宽,而且任意尺寸呢?上面的方法就不能直接使用,但是这个思想是可以借鉴的,我们可以进一步将最临近算法发挥的更好,对outuput的每个点,先根据长宽比计算其在原图中最邻近的像素点,然后直接根据最邻近的思想,直接拷贝Channel个字节作为输出图像:

Mat new_img = Mat(rows_out, cols_out, CV_8UC3);resizeByNN(source.data, new_img.data, source.rows, source.cols, source.channels(), new_img.rows, new_img.cols);gettimeofday(&t4, NULL);time = 1000*(t4.tv_sec - t3.tv_sec) + (double)(t4.tv_usec - t3.tv_usec)/1000;printf("frank resizeByNN = %lf\n", time);output: frank resizeByNN = 6.738000

时间已经缩小到原先的一半!

优化3

还有一个杀招,待日后更新。。。。

原图:
在这里插入图片描述

resizeByNN的结果:
在这里插入图片描述

上面两个函数的源码

resizeByHalf

uchar maxInt4(uchar x0, uchar x1, uchar x2, uchar x3){uchar t0 = (x0 >= x1) ? x0 : x1;uchar t1 = (x2 >= x3) ? x2 : x3;return (t0 >= t1) ? t0 : t1;
}uchar meanInt4(uchar x0, uchar x1, uchar x2, uchar x3){float t = (x0 + x1 + x2 + x3)/4.0;return uchar(round(t));  //四舍五入
}uchar leftTopInt4(uchar x0, uchar x1, uchar x2, uchar x3){return x0;
}Mat resizeByHalf(Mat input, uchar (*pfun)(uchar x0, uchar x1, uchar x2, uchar x3)){Mat output;int h_in = input.rows;int w_in = input.cols;int c = input.channels();int h_out = h_in/2;int w_out = w_in/2;output.create(h_out, w_out, CV_8UC(c));uchar *data_source = input.data;uchar *data_half = output.data;int bpl_source = w_in*3;int bpl_half = w_out*3;for (int i = 0; i < h_out; i++) {for (int j = 0; j < w_out; j++) {uchar *sr = data_source + i*2*bpl_source + j*2*c;uchar *hr = data_half + i*bpl_half + j*c;for (int k = 0; k < c; k++) {*(hr+k) = pfun(*(sr+k), *(sr+k+c), *(sr+k+bpl_source), *(sr+k+c+bpl_source));}}}return output;
}

resizeByNN

void resizeByNN(uchar *input, uchar *output, int height_in, int width_in, int channels, int height_out, int width_out){uchar *data_source = input;uchar *data_half = output;int bpl_source = width_in*3;int bpl_dst = width_out*3;int pos = 0;int sep = 0;uchar *sr = nullptr;uchar *hr = nullptr;float step = 0.0;float step_x = float(width_in)/float(width_out);float step_y = float(height_in)/float(height_out);for (int i = 0; i < height_out; i++) {for (int j = 0; j < width_out; j++) {sep = int(step_y*i);step = int(j*step_x);sr = data_source + sep*bpl_source;hr = data_half + i*bpl_dst +j*channels;pos = step*channels;memcpy(hr, sr+pos, channels);}}return;
}

多谢阅读!


http://chatgpt.dhexx.cn/article/wvojcJmk.shtml

相关文章

C++ | resize函数的用法

最近在leetcode用C刷题&#xff0c;刚遇到一题需要给重新弄一个容器&#xff0c;并给容器初始化。新建容器要在private类中声明resize函数用来初始化preSum容器。 resize函数是C中序列式容器的一个共性函数&#xff0c;vv.resize(int n,element)表示调整容器vv的大小为n&#x…

opencv的resize函数

一、Opencv官方文档中resize的描述&#xff1a; resize Resizes an image. C: void resize(InputArray src, OutputArray dst, Size dsize, double fx0, double fy0, int interpolationINTER_LINEAR ) Python: cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) …

resize()函数

resize()&#xff0c;设置大小&#xff08;size&#xff09;; reserve()&#xff0c;设置容量&#xff08;capacity&#xff09;; size()是分配容器的内存大小&#xff0c;而capacity()只是设置容器容量大小&#xff0c;但并没有真正分配内存。 打个比方&#xff1a;正在建造…

OpenCV 图像缩放:cv.resize() 函数详解

目录 系列前言API函数详解参数列表缩放方式其一缩放方式其二两种方式的优先级关于插值方式 扩展 —— 相关函数 系列前言 这个系列是我第一个想要更下去的系列。每篇会全面介绍一个 OpenCV 函数&#xff0c;会给出 API 和示例。示例主要是用 Python 去写&#xff0c;但是 Open…

安卓中的几种线程间通信方式

一&#xff1a;Handler实现线程间的通信 andriod提供了 Handler 和 Looper 来满足线程间的通信。例如一个子线程从网络上下载了一副图片&#xff0c;当它下载完成后会发送消息给主线程&#xff0c;这个消息是通过绑定在主线程的Handler来传递的。 在Android&#xff0c;这里的…

Java中的线程通信的几种方式

Java中的线程间通信是指不同线程之间相互协作&#xff0c;以完成一些复杂的任务或实现某些功能的过程。线程间通信主要包括两个方面&#xff1a;线程之间的互斥和同步&#xff0c;以及线程之间的数据共享和通信。Java提供了多种方式来实现线程间通信&#xff0c;本文将介绍Java…

创建线程的四种方式 线程通信

文章目录 1.1 创建线程1.1.1 创建线程的四种方式1.1.2 Thread类与Runnable接口的比较1.1.3 Callable、Future与FutureTask 1.2 线程组和线程优先级1.3 Java线程的状态及主要转化方法1.4 Java线程间的通信1.4.1 等待/通知机制1.4.2 信号量1.4.3 管道 1.1 创建线程 1.1.1 创建线…

【多线程间几种通信方式】

一、使用 volatile 关键字 基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想。大致意思就是多个线程同时监听一个变量&#xff0c;当这个变量发生变化的时候 &#xff0c;线程能够感知并执行相应的业务。这也是最简单的一种实现方式 代码案例 package com.han…

线程之间的通信方式

前言 我只是个搬运工&#xff0c;尊重原作者的劳动成果&#xff0c;本文来源下列文章链接&#xff1a; https://zhuanlan.zhihu.com/p/129374075 https://blog.csdn.net/jisuanji12306/article/details/86363390 线程之间为什么要通信&#xff1f; 通信的目的是为了更好的协…

Java线程间的通信方式

文章目录 线程间通信的定义一、等待—通知&#xff08;1&#xff09;等待—通知机制的相关方法&#xff1a;&#xff08;2&#xff09;注意事项&#xff1a;&#xff08;4&#xff09;notify()方法的核心原理&#xff08;5&#xff09;等待—通知机制的经典范式&#xff08;6&a…

线程间实现通信的几种方式

目录 线程通信相关概述提出问题方式一&#xff1a;使用Object类的wait() 和 notify() 方法方式二&#xff1a;Lock 接口中的 newContition() 方法返回 Condition 对象&#xff0c;Condition 类也可以实现等待/通知模式方法三&#xff1a;使用 volatile 关键字方法四&#xff1a…

线程间的通信方式

对共享数据进行更改的时候&#xff0c;先到主内存中拷贝一份到本地内存中&#xff0c;然后进行数据的更改&#xff0c;再重新将数据刷到主内存&#xff0c;这中间的过程&#xff0c;其他线程是看不到的。 1、为什么需要线程通信 线程是操作系统调度的最小单位&#xff0c;有自…

进程和线程的几种通信方式

进程之间通信的几种方式 1. 管道&#xff1a;是内核里面的一串缓存 管道传输的数据是单向的&#xff0c;若相互进行通信的话&#xff0c;需要进行创建两个管道才行的。 2. 消息队列&#xff1a; 例如&#xff0c;A进程给B进程发送消息&#xff0c;A进程把数据放在对应的消息队…

线程的几种通信方式

目录 一、Object的wait()、notify()、notifyAll()方法 二、Condition的await()、signal()、signalAll()方法 三、CountDownLatch 四、CyclicBarrier 五、Semaphore 线程间的通信方式常用的有如下几种&#xff1a; Object的wait()、notify()、notifyAll()方法&#xff1b; …

线程间的通信方法

线程间的通信方法 1. 线程通信简介 一般而言&#xff0c;在一个应用程序&#xff08;即进程&#xff09;中&#xff0c;一个线程往往不是孤立存在的&#xff0c;常常需要和其它线程通信&#xff0c;以执行特定的任务。如主线程和次线程&#xff0c;次线程与次线程&#xff0c…

Matlab基本操作函数 abs函数

分享一下我老师大神的人工智能教程&#xff01;零基础&#xff0c;通俗易懂&#xff01;http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章。分享知识&#xff0c;造福人民&#xff0c;实现我们中华民族伟大复兴&#xff01; 1、abs函数&#xff1a;数值的绝对值和复数…

MATLAB中FFT的整理

作为一个资深的健忘症患者&#xff0c;需要把每次用都忘记的FFT问题进行整理。 FFT可将信号从时域转换到频域。 首先是一些简单常识&#xff1a; 采样周期&#xff1a;两次采样之间的时间间隔。 采样频率&#xff1a;1/采样周期。每秒采样的点数。&#xff08;注意&#xff1a…

matlab中abs函数,matlababs是什么意思 是是是什么意思

matlababs是什么意思 是是是什么意思以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! matlab 中的abs函数什么意思 编程知识 matlab中的abs(x)是去绝对值的函数 例如:x=-1.23 abs(x) ans 1.23 以上即是取了-1.23…

Matlab 用法

MATLAB基础&#xff1a; 清除命令 clc 清空命令行的命令 clf 清除当前figure中的内容 clear 清除工作区变量 close all 关闭所有图形窗口 清除命令通常放在代码最前方&#xff0c;避免其他变量或代码的干扰 变量命名规则 ①以英文字母开头&#xff0c;可包含英文字母、…

abs 三种功能及代码详解 matlab函数

1.abs函数功能 求实数的绝对值、复数的模、字符串的ASCII值 2.基本用法 abs(x)函数是对数组元素进行绝对值处理的函数。 函数的定义域包括复数。 对于复数xab*i&#xff0c;有abs(x)sqrt(a2b2)。 3.代码 clc; clear all;a -7; b 12i; abs(a…