当前位置:   article > 正文

C++| 一维线性插值、imadjust函数

C++| 一维线性插值、imadjust函数

前言:最近要从Matlab代码改C++代码,不能直接用Matlab生成的C代码,因为需要嵌入到已有项目中。Matlab本身有很多很方便的数学公式,但是在C++里没有相关的库的话,需要自己实现。

一维线性插值

原理

Matlab中的interp1函数插值类型有很多:

  • nearest(最邻近插值法)
  • linear(线性插值)
  • spline(三次样条插值)
  • cubic(三次立方插值)
  • pchip(三次Hermite插值)

本文编写的是linear线性插值,其实是分段线性插值,分段线性插值就是线性插值的原理。

在这里插入图片描述

从分段线性插值图像结果来看,其实就是分别对相邻两个点进行线性插值。新的x点如果落在了相邻两个点之间就用对应的线性插值计算,但是如果新的x点落在了最大和最小以外,这个可以用离得最近的两个相邻点作为线性插值的斜率计算。

C++代码

x和y是分段插值的点坐标,然后new_x是需要插值获得x坐标,new_y是插值对应的y坐标。

double* linear(double* x, double* y, int n, double* new_x, int new_n) {
	double* new_y;
	new_y = new double[new_n];
	double last_x = 0, last_y = 0, next_x = 0, next_y = 0;
	int p = 0;
	for (int i = 0; i < new_n; i++) {
		while (p < n&& new_x[i] < x[p]) {
			p++;
			if (p == n)
				break;
		}
		// 考虑落在最小和最大范围外的点,做特殊处理,取最近相邻的点作为线性插值的计算
		if (p == 0) {
			last_x = x[0];
			last_y = y[0];
			next_x = x[1];
			next_y = y[1];
		}
		else if (p == n) {
			last_x = x[n-2];
			last_y = y[n-2];
			next_x = x[n-1];
			next_y = y[n-1];
		}
		else {
			last_x = x[p-1];
			last_y = y[p-1];
			next_x = x[p];
			next_y = y[p];
		}
		new_y[i] = (new_x[i]-last_x)*((next_y - last_y) / (next_x - last_x))+last_x;
	}
	return new_y;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

imadjust函数图像灰度调整

原理

Matlab中的imadjust函数可以对图像进行灰度调整,调用格式如下:

J=imadjust( I,[low_in;high_in],[low_out;high_out],gamma);
  • 1

该函数的功能,输入图像数据I:

  • 灰度小于low_in:low_out。
  • 灰度大于low_in且小于high_in:灰度线性变换后,进行gamma变换。
  • 灰度大于high_in:high_out。

结合图像来理解更为直观:
在这里插入图片描述
其中gamma变换,是一个固定的公式 s = c r γ s=cr^γ s=crγ,在gamma为1的时候是线性变换,函数图像如下图:
在这里插入图片描述

C++代码

void imadjust2(unsigned char**Image,int rows,int cols, int low_in, int high_in, int low_out, int high_out, double gamma) {
	// gamma变换公式
	unsigned char gammaLut[256];
	double c = 1.0;
	for (int i = 0; i < 256; i++)
		gammaLut[i] = (unsigned char)(c * pow((double)i / 255.0, gamma) * 255.0);
	// 灰度调整
	double k = ((double)high_out - low_out) / (high_in - low_in);
	double result = 0.0;
	for (int i = 0; i < rows;i++) {
		for (int j = 0; j < cols;j++) {
			if (Image[i][j] <= low_in) {
				Image[i][j] = low_out % 255;
			}
			else if (Image[i][j] >= high_in) {
				Image[i][j] = high_out % 255;
			}
			else {
				result = k * ((double)Image[i][j] - low_in) + low_in;
				Image[i][j] = gammaLut[(unsigned char)result]%255;
			}
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

思路:Matlab代码转C++

  1. 搜C++有没有现成的库,例如Matlab中傅里叶变换,在C++中就有fftw3.h(CPU)或者cufft.h(GPU)能够实现。
  2. 上网搜有没有别人已经写好的相同功能的,直接搬砖改写。
  3. 在Matlab中右键函数“打开xxx函数”,就会出现该函数使用帮助、原理和源码(有些有 有些没有),这些辅助转写C++代码。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/691467
推荐阅读
相关标签
  

闽ICP备14008679号