当前位置:网站首页>Opencv interpolation mode
Opencv interpolation mode
2022-07-01 14:20:00 【Σίσυφος one thousand and nine hundred】
One 、 Interpolation method and resize() The relationship between
resize() Function contains several ways of interpolation :
void resize(InputArray src,// Input , Original image , The image to be changed ; OutputArray dst, // Output , Image after resizing , This image has the same content as the original image , It's just that the size is different from the original image ; Size dsize, // The size of the output image . If this parameter is not 0, So it means to zoom the original image to this Size(width,height) Specified size ; If this parameter is zero 0, Then the size of the original image after zooming should be calculated by the following formula : double fx=0, // width Scale in direction , If it is 0, Then it will follow (double)dsize.width/src.cols To calculate ; double fy=0, //height Scale in direction , If it is 0, Then it will follow (double)dsize.height/src.rows To calculate ; int interpolation=INTER_LINEAR// This is how to specify interpolation , After image zooming , Be sure to recalculate the pixels , It depends on this parameter to specify how pixels are recalculated , There are the following : INTER_NEAREST - Nearest neighbor interpolation INTER_LINEAR - Bilinear interpolation , If you don't specify the last parameter , This method is used by default INTER_AREA - Area interpolation resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method. INTER_CUBIC - 4x4 Bicubic interpolation in the neighborhood of a pixel INTER_LANCZOS4 - 8x8 Within the neighborhood of a pixel Lanczos interpolation );
Precautions for use :
dsize and fx/fy You can't do it at the same time 0,
Two 、 Nearest neighbor interpolation INTER_NEAREST
Nearest neighbor interpolation , Find the nearest neighbor ( Existing pixels , Black spot ), The assignment is the same .
Realization opencv Three interpolation algorithms commonly used in - Simple books
// Nearest neighborhood interpolation
// According to the pixel points of the target image ( Floating point coordinates ) Find... In the original image 4 Pixels , Take the original pixel value closest to the pixel point as the value of the point .
#include<opencv2/opencv.hpp>
#include<cassert>
namespace mycv {
void nearestIntertoplation(cv::Mat& src, cv::Mat& dst, const int rows, const int cols);
}//mycv
double distance(const double x1, const double y1, const double x2, const double y2);// Distance between two points , European distance is used here
int main() {
cv::Mat img = cv::imread("lena.jpg", 0);
if (img.empty()) return -1;
cv::Mat dst;
mycv::nearestIntertoplation(img, dst, 600, 600);
cv::imshow("img", img);
cv::imshow("dst", dst);
cv::waitKey(0);
return 0;
return 0;
}//main
void mycv::nearestIntertoplation(cv::Mat& src, cv::Mat& dst, const int rows, const int cols) {
// scale
const double scale_row = static_cast<double>(src.rows) / rows;
const double scale_col = static_cast<double>(src.rows) / cols;
// Expand src To dst
dst = cv::Mat(rows, cols, src.type());
assert(src.channels() == 1 && dst.channels() == 1);
for (int i = 0; i < rows; ++i)//dst The line of
for (int j = 0; j < cols; ++j)//dst The column of
{
// Find the four points of interpolation
double y = (i + 0.5) * scale_row + 0.5;
double x = (j + 0.5) * scale_col + 0.5;
int x1 = static_cast<int>(x);//col Corresponding x
if (x1 >= (src.cols - 2)) x1 = src.cols - 2;// To prevent cross-border
int x2 = x1 + 1;
int y1 = static_cast<int>(y);//row Corresponding y
if (y1 >= (src.rows - 2)) y1 = src.rows - 2;
int y2 = y1 + 1;
// According to the pixel points of the target image ( Floating point coordinates ) Find... In the original image 4 Pixels , Take the original pixel value closest to the pixel point as the value of the point .
assert(0 < x2 && x2 < src.cols && 0 < y2 && y2 < src.rows);
std::vector<double> dist(4);
dist[0] = distance(x, y, x1, y1);
dist[1] = distance(x, y, x2, y1);
dist[2] = distance(x, y, x1, y2);
dist[3] = distance(x, y, x2, y2);
int min_val = dist[0];
int min_index = 0;
for (int i = 1; i < dist.size(); ++i)
if (min_val > dist[i])
{
min_val = dist[i];
min_index = i;
}
switch (min_index)
{
case 0:
dst.at<uchar>(i, j) = src.at<uchar>(y1, x1);
break;
case 1:
dst.at<uchar>(i, j) = src.at<uchar>(y1, x2);
break;
case 2:
dst.at<uchar>(i, j) = src.at<uchar>(y2, x1);
break;
case 3:
dst.at<uchar>(i, j) = src.at<uchar>(y2, x2);
break;
default:
assert(false);
}
}
}
double distance(const double x1, const double y1, const double x2, const double y2)// Distance between two points , European distance is used here {
return (x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2);// Just compare the size , Just return the square of the distance
}3、 ... and 、 linear interpolation
Two known points ( Red ) , Giving a blue dot x coordinate , seek y.

// Linear interpolation ( Bilinear interpolation )
#include<opencv2/opencv.hpp>
#include<opencv2/core/matx.hpp>
#include<cassert>
namespace mycv {
void bilinearIntertpolatioin(cv::Mat& src, cv::Mat& dst, const int rows, const int cols);
}//mycv
int main() {
cv::Mat img = cv::imread("lena.jpg", 0);
if (img.empty()) return -1;
cv::Mat dst;
mycv::bilinearIntertpolatioin(img, dst, 600, 600);
cv::imshow("img", img);
cv::imshow("dst", dst);
cv::waitKey(0);
return 0;
}//main
void mycv::bilinearIntertpolatioin(cv::Mat& src, cv::Mat& dst, const int rows, const int cols) {
// scale
const double scale_row = static_cast<double>(src.rows) / rows;
const double scale_col = static_cast<double>(src.rows) / cols;
// Expand src To dst
dst = cv::Mat(rows, cols, src.type());
assert(src.channels() == 1 && dst.channels() == 1);
for(int i = 0; i < rows; ++i)//dst The line of
for (int j = 0; j < cols; ++j)//dst The column of
{
// Find the four points of interpolation
double y = (i + 0.5) * scale_row + 0.5;
double x = (j + 0.5) * scale_col + 0.5;
int x1 = static_cast<int>(x);//col Corresponding x
if (x1 >= (src.cols - 2)) x1 = src.cols - 2;// To prevent cross-border
int x2 = x1 + 1;
int y1 = static_cast<int>(y);//row Corresponding y
if (y1 >= (src.rows - 2)) y1 = src.rows - 2;
int y2 = y1 + 1;
assert(0 < x2 && x2 < src.cols && 0 < y2 && y2 < src.rows);
// Interpolation formula , Refer to Wikipedia matrix multiplication formula https://zh.wikipedia.org/wiki/%E5%8F%8C%E7%BA%BF%E6%80%A7%E6%8F%92%E5%80%BC
cv::Matx12d matx = { x2 - x, x - x1 };
cv::Matx22d matf = { static_cast<double>(src.at<uchar>(y1, x1)), static_cast<double>(src.at<uchar>(y2, x1)),
static_cast<double>(src.at<uchar>(y1, x2)), static_cast<double>(src.at<uchar>(y2, x2)) };
cv::Matx21d maty = {
y2 - y,
y - y1
};
auto val = (matx * matf * maty);
dst.at<uchar>(i, j) = val(0,0);
}
}Four 、 Bicubic interpolation
In the mathematical branch of numerical analysis , Bicubic interpolation ( English :Bicubic interpolation) It is the most commonly used interpolation method in two-dimensional space . In this way , function f At point (x, y) The value of can be obtained by the weighted average of the nearest 16 sampling points in the rectangular grid , Here we need to use two polynomials to interpolate cubic functions , Use one... In each direction
Bicubic interpolation calculation formula
So this a(i, j) It is the weighting coefficient mentioned in the introduction , So the key is to solve it .
The formula for solving the weighting coefficient is as follows
The code for solving the reinforcement coefficient is as follows :
std::vector<double> mycv::getW(double coor, double a)
{
std::vector<double> w(4);
int base = static_cast<int>(coor);// Take rounding as the benchmark
double e = coor - static_cast<double>(base);// More than the decimal part of the benchmark
std::vector<double> tmp(4);// Stored in formula |x| <= 1, 1 < |x| < 2 The four values
// 4 x 4 Of 16 A little bit , therefore tmp[0] and tmp[4] Far away , Values in [1, 2] Section
tmp[0] = 1.0 + e;// 1 < x < 2
tmp[1] = e;//x <= 1
tmp[2] = 1.0 - e;// x <= 1
tmp[3] = 2.0 - e;// 1 < x < 2
// according to bicubic Formula calculation coefficient w
// x <= 1
w[1] = (a + 2.0) * std::abs(std::pow(tmp[1], 3)) - (a + 3.0) * std::abs(std::pow(tmp[1], 2)) + 1;
w[2] = (a + 2.0) * std::abs(std::pow(tmp[2], 3)) - (a + 3.0) * std::abs(std::pow(tmp[2], 2)) + 1;
// 1 < x < 2
w[0] = a * std::abs(std::pow(tmp[0], 3)) - 5.0 * a * std::abs(std::pow(tmp[0], 2)) + 8.0*a*std::abs(tmp[0]) - 4.0*a;
w[3] = a * std::abs(std::pow(tmp[3], 3)) - 5.0 * a * std::abs(std::pow(tmp[3], 2)) + 8.0*a*std::abs(tmp[3]) - 4.0*a;
return w;
}
After solving it ,wx and wy Namely 4x4 Composed of 16 A coefficient of , And interpolation 4x4 Of 16 Points match . The key code of interpolation step
//4x4 Number of points (rr, cc) -> (y, x)
std::vector<std::vector<int> > src_arr = {
{ src.at<uchar>(rr - 1, cc - 1), src.at<uchar>(rr, cc - 1), src.at<uchar>(rr + 1, cc - 1), src.at<uchar>(rr + 2, cc - 1)},
{ src.at<uchar>(rr - 1, cc), src.at<uchar>(rr, cc), src.at<uchar>(rr + 1, cc), src.at<uchar>(rr + 2, cc)},
{ src.at<uchar>(rr - 1, cc + 1), src.at<uchar>(rr, cc + 1), src.at<uchar>(rr + 1, cc + 1), src.at<uchar>(rr + 2, cc + 1)},
{ src.at<uchar>(rr - 1, cc + 2), src.at<uchar>(rr, cc + 2), src.at<uchar>(rr + 1, cc + 2), src.at<uchar>(rr + 2, cc + 2)}
};
for(int p = 0; p < 3; ++p)
for (int q = 0; q < 3; ++q)
{
//val(p, q) = w(p,q) * src(p, q)
val += wr[p] * wc[q] * static_cast<double>(src_arr[p][q]);
}
assert(i < dst.rows && j < dst.cols);
dst.at<uchar>(i, j) = static_cast<int>(val);
// Bicubic interpolation
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
#include<cassert>
namespace mycv {
void bicubicInsterpolation(cv::Mat& src, cv::Mat& dst, const int rows, const int cols);
std::vector<double> getW(double coor, double a = -0.5);//a Default -0.5
}//mycv
int main(void)
{
cv::Mat img = cv::imread("lena.jpg", 0);
if (img.empty()) return -1;
cv::Mat dst;
mycv::bicubicInsterpolation(img, dst, 600, 600);
cv::imshow("img", img);
cv::imshow("dst", dst);
cv::waitKey(0);
return 0;
}//main
void mycv::bicubicInsterpolation(cv::Mat& src, cv::Mat& dst, const int rows, const int cols)
{
dst = cv::Mat(rows, cols, src.type(), cv::Scalar::all(0));// initialization dst
// scale
double row_scale = static_cast<double>(src.rows) / rows;
double col_scale = static_cast<double>(src.cols) / cols;
switch (src.channels())
{
case 1:// Grayscale
for(int i = 2; i < dst.rows - 2; ++i)
for (int j = 2; j < dst.cols - 2; ++j)
{
// Computing coefficients w
double r = static_cast<double>(i * row_scale);
double c = static_cast<double>(j * col_scale);
// To prevent cross-border
if (r < 1.0) r += 1.0;
if (c < 1.0) c += 1.0;
std::vector<double> wr = mycv::getW( r);
std::vector<double> wc = mycv::getW( c);
// Finally, calculate the gray value obtained by interpolation
double val = 0;
int cc = static_cast<int>(c);
int rr = static_cast<int>(r);
// To prevent cross-border
if (cc > src.cols - 3)
{
cc = src.cols - 3;
}
if (rr > src.rows - 3) rr = src.rows - 3;
assert(0 <= (rr - 1) && 0 <= (cc - 1) && (rr + 2) < src.rows && (cc + 2) < src.cols);
//4x4 Number of points (rr, cc) -> (y, x)
std::vector<std::vector<int> > src_arr = {
{ src.at<uchar>(rr - 1, cc - 1), src.at<uchar>(rr, cc - 1), src.at<uchar>(rr + 1, cc - 1), src.at<uchar>(rr + 2, cc - 1)},
{ src.at<uchar>(rr - 1, cc), src.at<uchar>(rr, cc), src.at<uchar>(rr + 1, cc), src.at<uchar>(rr + 2, cc)},
{ src.at<uchar>(rr - 1, cc + 1), src.at<uchar>(rr, cc + 1), src.at<uchar>(rr + 1, cc + 1), src.at<uchar>(rr + 2, cc + 1)},
{ src.at<uchar>(rr - 1, cc + 2), src.at<uchar>(rr, cc + 2), src.at<uchar>(rr + 1, cc + 2), src.at<uchar>(rr + 2, cc + 2)}
};
for(int p = 0; p < 3; ++p)
for (int q = 0; q < 3; ++q)
{
//val(p, q) = w(p,q) * src(p, q)
val += wr[p] * wc[q] * static_cast<double>(src_arr[p][q]);
}
assert(i < dst.rows && j < dst.cols);
dst.at<uchar>(i, j) = static_cast<int>(val);
}
break;
case 3:// colour ( The principle is the same, just two more channels )
break;
default:
break;
}
}
std::vector<double> mycv::getW(double coor, double a)
{
std::vector<double> w(4);
int base = static_cast<int>(coor);// Take rounding as the benchmark
double e = coor - static_cast<double>(base);// More than the decimal part of the benchmark
std::vector<double> tmp(4);// Stored in formula |x| <= 1, 1 < |x| < 2 The four values
// 4 x 4 Of 16 A little bit , therefore tmp[0] and tmp[4] Far away , Values in [1, 2] Section
tmp[0] = 1.0 + e;// 1 < x < 2
tmp[1] = e;//x <= 1
tmp[2] = 1.0 - e;// x <= 1
tmp[3] = 2.0 - e;// 1 < x < 2
// according to bicubic Formula calculation coefficient w
// x <= 1
w[1] = (a + 2.0) * std::abs(std::pow(tmp[1], 3)) - (a + 3.0) * std::abs(std::pow(tmp[1], 2)) + 1;
w[2] = (a + 2.0) * std::abs(std::pow(tmp[2], 3)) - (a + 3.0) * std::abs(std::pow(tmp[2], 2)) + 1;
// 1 < x < 2
w[0] = a * std::abs(std::pow(tmp[0], 3)) - 5.0 * a * std::abs(std::pow(tmp[0], 2)) + 8.0*a*std::abs(tmp[0]) - 4.0*a;
w[3] = a * std::abs(std::pow(tmp[3], 3)) - 5.0 * a * std::abs(std::pow(tmp[3], 2)) + 8.0*a*std::abs(tmp[3]) - 4.0*a;
return w;
}
边栏推荐
- 微服务大行其道的今天,Service Mesh是怎样一种存在?
- Is the futures company found on Baidu safe? How do futures companies determine the regularity
- 光环效应——谁说头上有光的就算英雄
- What "hard core innovations" does Intel have in the first half of 2022? Just look at this picture!
- 户外LED显示屏应该考虑哪些问题?
- When the main process architecture game, to prevent calls everywhere to reduce coupling, how to open the interface to others to call?
- Research Report on development trend and competitive strategy of global 4-aminodiphenylamine industry
- QT community management system
- 基于算力驱动、数据与功能协同的分布式动态(协同)渲染/功能运行时
- 使用CMD修复和恢复病毒感染文件
猜你喜欢

Leetcode (69) -- square root of X

sqlilabs less13

Six years of technology iteration, challenges and exploration of Alibaba's globalization and compliance

After being laid off for three months, the interview ran into a wall everywhere, and the mentality has begun to collapse

Texstudio tutorial

Use lambda function URL + cloudfront to realize S3 image back to source

Leetcode(69)——x 的平方根

In depth cooperation | Taosi data cooperates with changhongjia Huawei customers in China to provide tdengine with powerful enterprise level products and perfect service guarantee

Open source internship experience sharing: openeuler software package reinforcement test

TDengine 连接器上线 Google Data Studio 应用商店
随机推荐
sqlilabs less-11~12
How to pass array parameters in get request
QT learning management system
Research Report on the development trend and competitive strategy of the global chemical glassware industry
How can we protect our passwords?
sqlilabs less10
Using CMD to repair and recover virus infected files
Is the futures company found on Baidu safe? How do futures companies determine the regularity
玩转MongoDB—搭建MongoDB集群
WebSocket(简单体验版)
【R语言数据科学】:机器学习常见评估指标
Research Report on development trend and competitive strategy of global vibration polishing machine industry
el-form-item 正则验证
【牛客网刷题系列 之 Verilog快速入门】~ 使用函数实现数据大小端转换
程序设计的基本概念
SWT/ANR问题--当发送ANR/SWT时候如何打开binder trace(BinderTraces)
How will the surging tide of digitalization overturn the future?
【IoT毕设.上】STM32+机智云AIoT+实验室安全监控系统
【NLP】预训练模型——GPT1
QT community management system