当前位置:网站首页>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;
}
边栏推荐
- Basis of target detection (NMS)
- sqlilabs less-11~12
- QT社团管理系统
- [Jianzhi offer] 55 - ii balanced binary tree
- C语言基础知识
- User defined annotation realizes the function of verifying information
- 佩服,阿里女程序卧底 500 多个黑产群……
- sqlilabs less-11~12
- Research Report on the development trend and competitive strategy of the global CCTV robot industry
- 2022-2-15 learning the imitation Niuke project - post in Section 2
猜你喜欢

【牛客网刷题系列 之 Verilog快速入门】~ 使用函数实现数据大小端转换

逻辑是个好东西

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

2022 PMP project management examination agile knowledge points (6)

Fiori applications are shared through the enhancement of adaptation project

sqlilabs less-11~12

App automation testing Kaiyuan platform appium runner

玩转MongoDB—搭建MongoDB集群

使用 Lambda 函数URL + CloudFront 实现S3镜像回源

Introduction to distributed transactions (Seata)
随机推荐
Basis of target detection (NMS)
Use of Oracle database objects
2022-2-15 learning the imitation Niuke project - post in Section 2
开源实习经验分享:openEuler软件包加固测试
[repair version] imitating the template of I love watching movies website / template of ocean CMS film and television system
[IOT completion. Part 2] stm32+ smart cloud aiot+ laboratory security monitoring system
【IoT毕设.上】STM32+机智云AIoT+实验室安全监控系统
el-form-item 正则验证
Research Report on the development trend and competitive strategy of the global pipeline robot inspection camera industry
2022 PMP project management examination agile knowledge points (6)
Research Report on the development trend and competitive strategy of the global display filter industry
Research Report on the development trend and competitive strategy of the global traditional computer industry
[anwangbei 2021] Rev WP
C语言基础知识
SQLAchemy 常用操作
Research Report on the development trend and competitive strategy of the global axis measurement system industry
This paper introduces an implementation scheme to enhance the favorite transaction code management tool in SAP GUI
Provincial election + noi Part VIII fraction theory
Après avoir été licencié pendant trois mois, l'entrevue s'est effondrée et l'état d'esprit a commencé à s'effondrer.
被裁三個月,面試到處碰壁,心態已經開始崩了