OpenCV中resize函数插值算法的实现过程(五种)


Posted in Python onJune 05, 2021

最新版OpenCV2.4.7中,cv::resize函数有五种插值算法:最近邻、双线性、双三次、基于像素区域关系、兰索斯插值。下面用for循环代替cv::resize函数来说明其详细的插值实现过程,其中部分代码摘自于cv::resize函数中的源代码。

每种插值算法的前部分代码是相同的,如下:

cv::Mat matSrc, matDst1, matDst2;
 
	matSrc = cv::imread("lena.jpg", 2 | 4);
	matDst1 = cv::Mat(cv::Size(800, 1000), matSrc.type(), cv::Scalar::all(0));
	matDst2 = cv::Mat(matDst1.size(), matSrc.type(), cv::Scalar::all(0));
 
	double scale_x = (double)matSrc.cols / matDst1.cols;
	double scale_y = (double)matSrc.rows / matDst1.rows;

1、最近邻:公式,

OpenCV中resize函数插值算法的实现过程(五种)

for (int i = 0; i < matDst1.cols; ++i)
	{
		int sx = cvFloor(i * scale_x);
		sx = std::min(sx, matSrc.cols - 1);
		for (int j = 0; j < matDst1.rows; ++j)
		{
			int sy = cvFloor(j * scale_y);
			sy = std::min(sy, matSrc.rows - 1);
			matDst1.at<cv::Vec3b>(j, i) = matSrc.at<cv::Vec3b>(sy, sx);
		}
	}
	cv::imwrite("nearest_1.jpg", matDst1);
 
	cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 0);
	cv::imwrite("nearest_2.jpg", matDst2);

2、双线性:由相邻的四像素(2*2)计算得出,公式,

OpenCV中resize函数插值算法的实现过程(五种)

uchar* dataDst = matDst1.data;
	int stepDst = matDst1.step;
	uchar* dataSrc = matSrc.data;
	int stepSrc = matSrc.step;
	int iWidthSrc = matSrc.cols;
	int iHiehgtSrc = matSrc.rows;
 
	for (int j = 0; j < matDst1.rows; ++j)
	{
		float fy = (float)((j + 0.5) * scale_y - 0.5);
		int sy = cvFloor(fy);
		fy -= sy;
		sy = std::min(sy, iHiehgtSrc - 2);
		sy = std::max(0, sy);
 
		short cbufy[2];
		cbufy[0] = cv::saturate_cast<short>((1.f - fy) * 2048);
		cbufy[1] = 2048 - cbufy[0];
 
		for (int i = 0; i < matDst1.cols; ++i)
		{
			float fx = (float)((i + 0.5) * scale_x - 0.5);
			int sx = cvFloor(fx);
			fx -= sx;
 
			if (sx < 0) {
				fx = 0, sx = 0;
			}
			if (sx >= iWidthSrc - 1) {
				fx = 0, sx = iWidthSrc - 2;
			}
 
			short cbufx[2];
			cbufx[0] = cv::saturate_cast<short>((1.f - fx) * 2048);
			cbufx[1] = 2048 - cbufx[0];
 
			for (int k = 0; k < matSrc.channels(); ++k)
			{
				*(dataDst+ j*stepDst + 3*i + k) = (*(dataSrc + sy*stepSrc + 3*sx + k) * cbufx[0] * cbufy[0] + 
					*(dataSrc + (sy+1)*stepSrc + 3*sx + k) * cbufx[0] * cbufy[1] + 
					*(dataSrc + sy*stepSrc + 3*(sx+1) + k) * cbufx[1] * cbufy[0] + 
					*(dataSrc + (sy+1)*stepSrc + 3*(sx+1) + k) * cbufx[1] * cbufy[1]) >> 22;
			}
		}
	}
	cv::imwrite("linear_1.jpg", matDst1);
 
	cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 1);
	cv::imwrite("linear_2.jpg", matDst2);

3、双三次:由相邻的4*4像素计算得出,公式类似于双线性

int iscale_x = cv::saturate_cast<int>(scale_x);
	int iscale_y = cv::saturate_cast<int>(scale_y);
 
	for (int j = 0; j < matDst1.rows; ++j)
	{
		float fy = (float)((j + 0.5) * scale_y - 0.5);
		int sy = cvFloor(fy);
		fy -= sy;
		sy = std::min(sy, matSrc.rows - 3);
		sy = std::max(1, sy);
 
		const float A = -0.75f;
 
		float coeffsY[4];
		coeffsY[0] = ((A*(fy + 1) - 5*A)*(fy + 1) + 8*A)*(fy + 1) - 4*A;
		coeffsY[1] = ((A + 2)*fy - (A + 3))*fy*fy + 1;
		coeffsY[2] = ((A + 2)*(1 - fy) - (A + 3))*(1 - fy)*(1 - fy) + 1;
		coeffsY[3] = 1.f - coeffsY[0] - coeffsY[1] - coeffsY[2];
 
		short cbufY[4];
		cbufY[0] = cv::saturate_cast<short>(coeffsY[0] * 2048);
		cbufY[1] = cv::saturate_cast<short>(coeffsY[1] * 2048);
		cbufY[2] = cv::saturate_cast<short>(coeffsY[2] * 2048);
		cbufY[3] = cv::saturate_cast<short>(coeffsY[3] * 2048);
 
		for (int i = 0; i < matDst1.cols; ++i)
		{
			float fx = (float)((i + 0.5) * scale_x - 0.5);
			int sx = cvFloor(fx);
			fx -= sx;
 
			if (sx < 1) {
				fx = 0, sx = 1;
			}
			if (sx >= matSrc.cols - 3) {
				fx = 0, sx = matSrc.cols - 3;
			}
 
			float coeffsX[4];
			coeffsX[0] = ((A*(fx + 1) - 5*A)*(fx + 1) + 8*A)*(fx + 1) - 4*A;
			coeffsX[1] = ((A + 2)*fx - (A + 3))*fx*fx + 1;
			coeffsX[2] = ((A + 2)*(1 - fx) - (A + 3))*(1 - fx)*(1 - fx) + 1;
			coeffsX[3] = 1.f - coeffsX[0] - coeffsX[1] - coeffsX[2];
 
			short cbufX[4];
			cbufX[0] = cv::saturate_cast<short>(coeffsX[0] * 2048);
			cbufX[1] = cv::saturate_cast<short>(coeffsX[1] * 2048);
			cbufX[2] = cv::saturate_cast<short>(coeffsX[2] * 2048);
			cbufX[3] = cv::saturate_cast<short>(coeffsX[3] * 2048);
 
			for (int k = 0; k < matSrc.channels(); ++k)
			{
				matDst1.at<cv::Vec3b>(j, i)[k] = abs((matSrc.at<cv::Vec3b>(sy-1, sx-1)[k] * cbufX[0] * cbufY[0] + matSrc.at<cv::Vec3b>(sy, sx-1)[k] * cbufX[0] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy+1, sx-1)[k] * cbufX[0] * cbufY[2] + matSrc.at<cv::Vec3b>(sy+2, sx-1)[k] * cbufX[0] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy-1, sx)[k] * cbufX[1] * cbufY[0] + matSrc.at<cv::Vec3b>(sy, sx)[k] * cbufX[1] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy+1, sx)[k] * cbufX[1] * cbufY[2] + matSrc.at<cv::Vec3b>(sy+2, sx)[k] * cbufX[1] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy-1, sx+1)[k] * cbufX[2] * cbufY[0] + matSrc.at<cv::Vec3b>(sy, sx+1)[k] * cbufX[2] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy+1, sx+1)[k] * cbufX[2] * cbufY[2] + matSrc.at<cv::Vec3b>(sy+2, sx+1)[k] * cbufX[2] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy-1, sx+2)[k] * cbufX[3] * cbufY[0] + matSrc.at<cv::Vec3b>(sy, sx+2)[k] * cbufX[3] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy+1, sx+2)[k] * cbufX[3] * cbufY[2] + matSrc.at<cv::Vec3b>(sy+2, sx+2)[k] * cbufX[3] * cbufY[3] ) >> 22);
			}
		}
	}
	cv::imwrite("cubic_1.jpg", matDst1);
 
	cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 2);
	cv::imwrite("cubic_2.jpg", matDst2);

4、基于像素区域关系:共分三种情况,图像放大时类似于双线性插值,图像缩小(x轴、y轴同时缩小)又分两种情况,此情况下可以避免波纹出现。

#ifdef _MSC_VER
	cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 3);
	cv::imwrite("E:/GitCode/OpenCV_Test/test_images/area_2.jpg", matDst2);
#else
	cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 3);
	cv::imwrite("area_2.jpg", matDst2);
#endif
 
	fprintf(stdout, "==== start area ====\n");
	double inv_scale_x = 1. / scale_x;
	double inv_scale_y = 1. / scale_y;
	int iscale_x = cv::saturate_cast<int>(scale_x);
	int iscale_y = cv::saturate_cast<int>(scale_y);
	bool is_area_fast = std::abs(scale_x - iscale_x) < DBL_EPSILON && std::abs(scale_y - iscale_y) < DBL_EPSILON;
 
	if (scale_x >= 1 && scale_y >= 1)  { // zoom out
		if (is_area_fast)  { // integer multiples
			for (int j = 0; j < matDst1.rows; ++j) {
				int sy = std::min(cvFloor(j * scale_y), matSrc.rows - 1);
 
				for (int i = 0; i < matDst1.cols; ++i) {
					int sx = std::min(cvFloor(i * scale_x), matSrc.cols -1);
 
					matDst1.at<cv::Vec3b>(j, i) = matSrc.at<cv::Vec3b>(sy, sx);
				}
			}
#ifdef _MSC_VER
			cv::imwrite("E:/GitCode/OpenCV_Test/test_images/area_1.jpg", matDst1);
#else
			cv::imwrite("area_1.jpg", matDst1);
#endif
			return 0;
		}
 
		for (int j = 0; j < matDst1.rows; ++j) {
			double fsy1 = j * scale_y;
			double fsy2 = fsy1 + scale_y;
			double cellHeight = cv::min(scale_y, matSrc.rows - fsy1);
 
			int sy1 = cvCeil(fsy1), sy2 = cvFloor(fsy2);
 
			sy2 = std::min(sy2, matSrc.rows - 2);
			sy1 = std::min(sy1, sy2);
 
			float cbufy[2];
			cbufy[0] = (float)((sy1 - fsy1) / cellHeight);
			cbufy[1] = (float)(std::min(std::min(fsy2 - sy2, 1.), cellHeight) / cellHeight);
 
			for (int i = 0; i < matDst1.cols; ++i) {
				double fsx1 = i * scale_x;
				double fsx2 = fsx1 + scale_x;
				double cellWidth = std::min(scale_x, matSrc.cols - fsx1);
 
				int sx1 = cvCeil(fsx1), sx2 = cvFloor(fsx2);
 
				sx2 = std::min(sx2, matSrc.cols - 2);
				sx1 = std::min(sx1, sx2);
 
				float cbufx[2];
				cbufx[0] = (float)((sx1 - fsx1) / cellWidth);
				cbufx[1] = (float)(std::min(std::min(fsx2 - sx2, 1.), cellWidth) / cellWidth);
 
				for (int k = 0; k < matSrc.channels(); ++k) {
					matDst1.at<cv::Vec3b>(j, i)[k] = (uchar)(matSrc.at<cv::Vec3b>(sy1, sx1)[k] * cbufx[0] * cbufy[0] +
						matSrc.at<cv::Vec3b>(sy1 + 1, sx1)[k] * cbufx[0] * cbufy[1] +
						matSrc.at<cv::Vec3b>(sy1, sx1 + 1)[k] * cbufx[1] * cbufy[0] +
						matSrc.at<cv::Vec3b>(sy1 + 1, sx1 + 1)[k] * cbufx[1] * cbufy[1]);
				}
			}
		}
#ifdef _MSC_VER
		cv::imwrite("E:/GitCode/OpenCV_Test/test_images/area_1.jpg", matDst1);
#else
		cv::imwrite("area_1.jpg", matDst1);
#endif
 
		return 0;
	}
 
	//zoom in,it is emulated using some variant of bilinear interpolation
	for (int j = 0; j < matDst1.rows; ++j) {
		int  sy = cvFloor(j * scale_y);
		float fy = (float)((j + 1) - (sy + 1) * inv_scale_y);
		fy = fy <= 0 ? 0.f : fy - cvFloor(fy);
		sy = std::min(sy, matSrc.rows - 2);
 
		short cbufy[2];
		cbufy[0] = cv::saturate_cast<short>((1.f - fy) * 2048);
		cbufy[1] = 2048 - cbufy[0];
 
		for (int i = 0; i < matDst1.cols; ++i) {
			int sx = cvFloor(i * scale_x);
			float fx = (float)((i + 1) - (sx + 1) * inv_scale_x);
			fx = fx < 0 ? 0.f : fx - cvFloor(fx);
 
			if (sx < 0) {
				fx = 0, sx = 0;
			}
 
			if (sx >= matSrc.cols - 1) {
				fx = 0, sx = matSrc.cols - 2;
			}
 
			short cbufx[2];
			cbufx[0] = cv::saturate_cast<short>((1.f - fx) * 2048);
			cbufx[1] = 2048 - cbufx[0];
 
			for (int k = 0; k < matSrc.channels(); ++k) {
				matDst1.at<cv::Vec3b>(j, i)[k] = (matSrc.at<cv::Vec3b>(sy, sx)[k] * cbufx[0] * cbufy[0] +
					matSrc.at<cv::Vec3b>(sy + 1, sx)[k] * cbufx[0] * cbufy[1] +
					matSrc.at<cv::Vec3b>(sy, sx + 1)[k] * cbufx[1] * cbufy[0] +
					matSrc.at<cv::Vec3b>(sy + 1, sx + 1)[k] * cbufx[1] * cbufy[1]) >> 22;
			}
		}
	}
	fprintf(stdout, "==== end area ====\n");
 
#ifdef _MSC_VER
	cv::imwrite("E:/GitCode/OpenCV_Test/test_images/area_1.jpg", matDst1);
#else
	cv::imwrite("area_1.jpg", matDst1);
#endif

注:以上基于area进行图像缩小的代码有问题,具体实现代码可以参考https://github.com/fengbingchun/OpenCV_Test/blob/master/src/fbc_cv/include/resize.hpp,用法如下:

fbc::Mat3BGR src(matSrc.rows, matSrc.cols, matSrc.data);
fbc::Mat3BGR dst(matDst1.rows, matDst1.cols, matDst1.data);
fbc::resize(src, dst, 3);

5、兰索斯插值:由相邻的8*8像素计算得出,公式类似于双线性

int iscale_x = cv::saturate_cast<int>(scale_x);
	int iscale_y = cv::saturate_cast<int>(scale_y);
 
	for (int j = 0; j < matDst1.rows; ++j)
	{
		float fy = (float)((j + 0.5) * scale_y - 0.5);
		int sy = cvFloor(fy);
		fy -= sy;
		sy = std::min(sy, matSrc.rows - 5);
		sy = std::max(3, sy);
 
		const double s45 = 0.70710678118654752440084436210485;
		const double cs[][2] = {{1, 0}, {-s45, -s45}, {0, 1}, {s45, -s45}, {-1, 0}, {s45, s45}, {0, -1}, {-s45, s45}};
		float coeffsY[8];
 
		if (fy < FLT_EPSILON) {
			for (int t = 0; t < 8; t++)
				coeffsY[t] = 0;
			coeffsY[3] = 1;
		} else {
			float sum = 0;
			double y0 = -(fy + 3) * CV_PI * 0.25, s0 = sin(y0), c0 = cos(y0);
 
			for (int t = 0; t < 8; ++t)
			{
				double dy = -(fy + 3 -t) * CV_PI * 0.25;
				coeffsY[t] = (float)((cs[t][0] * s0 + cs[t][1] * c0) / (dy * dy));
				sum += coeffsY[t];
			}
 
			sum = 1.f / sum;
			for (int t = 0; t < 8; ++t)
				coeffsY[t] *= sum;
		}
 
		short cbufY[8];
		cbufY[0] = cv::saturate_cast<short>(coeffsY[0] * 2048);
		cbufY[1] = cv::saturate_cast<short>(coeffsY[1] * 2048);
		cbufY[2] = cv::saturate_cast<short>(coeffsY[2] * 2048);
		cbufY[3] = cv::saturate_cast<short>(coeffsY[3] * 2048);
		cbufY[4] = cv::saturate_cast<short>(coeffsY[4] * 2048);
		cbufY[5] = cv::saturate_cast<short>(coeffsY[5] * 2048);
		cbufY[6] = cv::saturate_cast<short>(coeffsY[6] * 2048);
		cbufY[7] = cv::saturate_cast<short>(coeffsY[7] * 2048);
 
		for (int i = 0; i < matDst1.cols; ++i)
		{
			float fx = (float)((i + 0.5) * scale_x - 0.5);
			int sx = cvFloor(fx);
			fx -= sx;
 
			if (sx < 3) {
				fx = 0, sx = 3;
			}
			if (sx >= matSrc.cols - 5) {
				fx = 0, sx = matSrc.cols - 5;
			}
 
			float coeffsX[8];
 
			if (fx < FLT_EPSILON) {
				for ( int t = 0; t < 8; t++ )
					coeffsX[t] = 0;
				coeffsX[3] = 1;
			} else {
				float sum = 0;
				double x0 = -(fx + 3) * CV_PI * 0.25, s0 = sin(x0), c0 = cos(x0);
 
				for (int t = 0; t < 8; ++t)
				{
					double dx = -(fx + 3 -t) * CV_PI * 0.25;
					coeffsX[t] = (float)((cs[t][0] * s0 + cs[t][1] * c0) / (dx * dx));
					sum += coeffsX[t];
				}
 
				sum = 1.f / sum;
				for (int t = 0; t < 8; ++t)
					coeffsX[t] *= sum;
			}
 
			short cbufX[8];
			cbufX[0] = cv::saturate_cast<short>(coeffsX[0] * 2048);
			cbufX[1] = cv::saturate_cast<short>(coeffsX[1] * 2048);
			cbufX[2] = cv::saturate_cast<short>(coeffsX[2] * 2048);
			cbufX[3] = cv::saturate_cast<short>(coeffsX[3] * 2048);
			cbufX[4] = cv::saturate_cast<short>(coeffsX[4] * 2048);
			cbufX[5] = cv::saturate_cast<short>(coeffsX[5] * 2048);
			cbufX[6] = cv::saturate_cast<short>(coeffsX[6] * 2048);
			cbufX[7] = cv::saturate_cast<short>(coeffsX[7] * 2048);
 
			for (int k = 0; k < matSrc.channels(); ++k)
			{
				matDst1.at<cv::Vec3b>(j, i)[k] = abs((matSrc.at<cv::Vec3b>(sy-3, sx-3)[k] * cbufX[0] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx-3)[k] * cbufX[0] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy-1, sx-3)[k] * cbufX[0] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx-3)[k] * cbufX[0] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy+1, sx-3)[k] * cbufX[0] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx-3)[k] * cbufX[0] * cbufY[5] +
					matSrc.at<cv::Vec3b>(sy+3, sx-3)[k] * cbufX[0] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx-3)[k] * cbufX[0] * cbufY[7] +
 
					matSrc.at<cv::Vec3b>(sy-3, sx-2)[k] * cbufX[1] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx-2)[k] * cbufX[1] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy-1, sx-2)[k] * cbufX[1] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx-2)[k] * cbufX[1] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy+1, sx-2)[k] * cbufX[1] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx-2)[k] * cbufX[1] * cbufY[5] +
					matSrc.at<cv::Vec3b>(sy+3, sx-2)[k] * cbufX[1] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx-2)[k] * cbufX[1] * cbufY[7] +
 
					matSrc.at<cv::Vec3b>(sy-3, sx-1)[k] * cbufX[2] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx-1)[k] * cbufX[2] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy-1, sx-1)[k] * cbufX[2] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx-1)[k] * cbufX[2] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy+1, sx-1)[k] * cbufX[2] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx-1)[k] * cbufX[2] * cbufY[5] +
					matSrc.at<cv::Vec3b>(sy+3, sx-1)[k] * cbufX[2] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx-1)[k] * cbufX[2] * cbufY[7] +
 
					matSrc.at<cv::Vec3b>(sy-3, sx)[k] * cbufX[3] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx)[k] * cbufX[3] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy-1, sx)[k] * cbufX[3] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx)[k] * cbufX[3] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy+1, sx)[k] * cbufX[3] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx)[k] * cbufX[3] * cbufY[5] +
					matSrc.at<cv::Vec3b>(sy+3, sx)[k] * cbufX[3] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx)[k] * cbufX[3] * cbufY[7] +
 
					matSrc.at<cv::Vec3b>(sy-3, sx+1)[k] * cbufX[4] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx+1)[k] * cbufX[4] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy-1, sx+1)[k] * cbufX[4] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx+1)[k] * cbufX[4] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy+1, sx+1)[k] * cbufX[4] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx+1)[k] * cbufX[4] * cbufY[5] +
					matSrc.at<cv::Vec3b>(sy+3, sx+1)[k] * cbufX[4] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx+1)[k] * cbufX[4] * cbufY[7] +
 
					matSrc.at<cv::Vec3b>(sy-3, sx+2)[k] * cbufX[5] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx+2)[k] * cbufX[5] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy-1, sx+2)[k] * cbufX[5] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx+2)[k] * cbufX[5] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy+1, sx+2)[k] * cbufX[5] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx+2)[k] * cbufX[5] * cbufY[5] +
					matSrc.at<cv::Vec3b>(sy+3, sx+2)[k] * cbufX[5] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx+2)[k] * cbufX[5] * cbufY[7] +
 
					matSrc.at<cv::Vec3b>(sy-3, sx+3)[k] * cbufX[6] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx+3)[k] * cbufX[6] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy-1, sx+3)[k] * cbufX[6] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx+3)[k] * cbufX[6] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy+1, sx+3)[k] * cbufX[6] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx+3)[k] * cbufX[6] * cbufY[5] +
					matSrc.at<cv::Vec3b>(sy+3, sx+3)[k] * cbufX[6] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx+3)[k] * cbufX[6] * cbufY[7] +
 
					matSrc.at<cv::Vec3b>(sy-3, sx+4)[k] * cbufX[7] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx+4)[k] * cbufX[7] * cbufY[1] +
					matSrc.at<cv::Vec3b>(sy-1, sx+4)[k] * cbufX[7] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx+4)[k] * cbufX[7] * cbufY[3] +
					matSrc.at<cv::Vec3b>(sy+1, sx+4)[k] * cbufX[7] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx+4)[k] * cbufX[7] * cbufY[5] +
					matSrc.at<cv::Vec3b>(sy+3, sx+4)[k] * cbufX[7] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx+4)[k] * cbufX[7] * cbufY[7] ) >> 22);// 4194304
			}
		}
	}
	cv::imwrite("Lanczos_1.jpg", matDst1);
 
	cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 4);
	cv::imwrite("Lanczos_2.jpg", matDst2);

以上代码的实现结果与cv::resize函数相同,但是执行效率非常低,只是为了详细说明插值过程。OpenCV中默认采用C++ Concurrency进行优化加速,你也可以采用TBB、OpenMP等进行优化加速。

GitHubhttps://github.com/fengbingchun/OpenCV_Test/blob/master/demo/OpenCV_Test/test_opencv_funset.cpp

到此这篇关于OpenCV中resize函数插值算法的实现过程(五种)的文章就介绍到这了,更多相关OpenCV resize插值内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
使用python调用浏览器并打开一个网址的例子
Jun 05 Python
简单介绍Python中的round()方法
May 15 Python
Python NumPy库安装使用笔记
May 18 Python
python subprocess 杀掉全部派生的子进程方法
Jan 16 Python
深入学习Python中的上下文管理器与else块
Aug 27 Python
Python hashlib模块用法实例分析
Jun 12 Python
详解python中Numpy的属性与创建矩阵
Sep 10 Python
python命令行工具Click快速掌握
Jul 04 Python
Pycharm中出现ImportError:DLL load failed:找不到指定模块的解决方法
Sep 17 Python
pytorch实现MNIST手写体识别
Feb 14 Python
python实现canny边缘检测
Sep 14 Python
python爬虫爬取淘宝商品比价(附淘宝反爬虫机制解决小办法)
Dec 03 Python
OpenCV全景图像拼接的实现示例
opencv 分类白天与夜景视频的方法
python如何利用traceback获取详细的异常信息
Jun 05 #Python
Python异常类型以及处理方法汇总
Jun 05 #Python
Python OpenCV 彩色与灰度图像的转换实现
Python深度学习之实现卷积神经网络
python opencv通过4坐标剪裁图片
Jun 05 #Python
You might like
PHP 获取目录下的图片并随机显示的代码
2009/12/28 PHP
windows服务器中检测PHP SSL是否开启以及开启SSL的方法
2014/04/25 PHP
php模拟服务器实现autoindex效果的方法
2015/03/10 PHP
PHP查看当前变量类型的方法
2015/07/31 PHP
Zend Framework教程之响应对象的封装Zend_Controller_Response实例详解
2016/03/07 PHP
Ajax+PHP实现的分类列表框功能示例
2019/02/11 PHP
jQuery为iframe的body添加click事件的实现代码
2011/04/07 Javascript
jQuery插件jQuery-JSONP开发ajax调用使用注意事项
2013/11/22 Javascript
JavaScript中一个奇葩的IE浏览器判断方法
2014/04/16 Javascript
js中回调函数的学习笔记
2014/07/31 Javascript
我用的一些Node.js开发工具、开发包、框架等总结
2014/09/25 Javascript
jquery队列函数用法实例
2014/12/16 Javascript
AngularJS使用angular-formly进行表单验证
2015/12/27 Javascript
Jquery和angularjs获取check框选中的值的方法汇总
2016/01/17 Javascript
javascript cookie用法基础教程(概念,设置,读取及删除)
2016/09/20 Javascript
javascript中Number的方法小结
2016/11/21 Javascript
bootstrap配合Masonry插件实现瀑布式布局
2017/01/18 Javascript
详解探索 vuex 2.0 以及使用 vuejs 2.0 + vuex 2.0 构建记事本应用
2017/06/16 Javascript
jQuery实现checkbox全选功能完整实例
2018/07/12 jQuery
微信小程序实现手势滑动卡片效果
2019/08/26 Javascript
layui 解决富文本框form表单提交为空的问题
2019/10/26 Javascript
vue中使用vue-print.js实现多页打印
2020/03/05 Javascript
[02:19]DOTA2女子战队FOX视频专访:希望更多美眉一起加入
2013/10/15 DOTA
Python多进程同步Lock、Semaphore、Event实例
2014/11/21 Python
Python制作爬虫采集小说
2015/10/25 Python
python读取txt文件中特定位置字符的方法
2018/12/24 Python
Python字节单位转换实例
2019/12/05 Python
CSS3实现DIV圆角效果完整代码
2012/10/10 HTML / CSS
css3 矩阵的使用详解
2018/03/20 HTML / CSS
丝芙兰美国官网:SEPHORA美国
2016/08/03 全球购物
美国庭院家具购物网站:AlphaMarts
2019/04/10 全球购物
高级护理实习生自荐信
2013/09/28 职场文书
计算机学生求职信范文
2014/01/30 职场文书
2015国庆节66周年标语
2015/07/30 职场文书
Python中json.load()和json.loads()有哪些区别
2021/06/07 Python
QT连接MYSQL数据库的详细步骤
2021/07/07 MySQL