当前位置:网站首页>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;
}
边栏推荐
- Is it reasonable and safe for securities companies to open accounts for 10000 free securities? How to say
- [repair version] imitating the template of I love watching movies website / template of ocean CMS film and television system
- MySQL log
- 8 best practices to protect your IAC security!
- 使用CMD修复和恢复病毒感染文件
- el-form-item 正则验证
- 玩转gRPC—不同编程语言间通信
- Use the right scene, get twice the result with half the effort! Full introduction to the window query function and usage scenarios of tdengine
- Research Report on the development trend and competitive strategy of the global CCTV robot industry
- Six years of technology iteration, challenges and exploration of Alibaba's globalization and compliance
猜你喜欢

Play with mongodb - build a mongodb cluster

Oracle-数据库对象的使用

Open source internship experience sharing: openeuler software package reinforcement test

That hard-working student failed the college entrance examination... Don't panic! You have another chance to counter attack!

【R语言数据科学】:机器学习常见评估指标

What "hard core innovations" does Intel have in the first half of 2022? Just look at this picture!

leetcode622.设计循环队列(C语言)

Summary of leetcode's dynamic programming 5

逻辑是个好东西

QT社团管理系统
随机推荐
C语言基础知识
Basic concepts of programming
leetcode622.设计循环队列(C语言)
sqlilabs less13
Use lambda function URL + cloudfront to realize S3 image back to source
30 Devops interview questions and answers
用栈实现队列、用队列实现栈(C语言_leetcode_232+225)
Use of Oracle database objects
That hard-working student failed the college entrance examination... Don't panic! You have another chance to counter attack!
Go整合Logrus实现日志打印
[sword finger offer] 55 - I. depth of binary tree
Research Report on the development trend and competitive strategy of the global navigation simulator industry
Go integrates logrus to realize log printing
券商万1免5证券开户是合理安全的吗,怎么讲
Research Report on the development trend and competitive strategy of the global ultrasonic scalpel system industry
Research Report on the development trend and competitive strategy of the global high temperature label industry
sqlilabs less-11~12
C language ordering management system
After being laid off for three months, the interview ran into a wall everywhere, and the mentality has begun to collapse
sqlilabs less9