Opencv(C++)实现二阶线性插值

#include<opencv2\opencv.hpp>
#include<iostream> using namespace cv;
using namespace std; bool enlargedImage(Mat &src, float k1, float k2);//k1,k2表示放大的倍数 void main()
{
Mat srcImage = imread("flower.png");
float k1 = 1.2, k2 = 2.5;
enlargedImage(srcImage, k1, k2);
} bool enlargedImage(Mat &src, float k1, float k2)
{
int height, width, theight, twidth;
int ia, ja;//新的坐标
height = src.rows;//图像的高
width = src.cols;//图像的宽
theight = round(height*k1);//扩大后图像的高
cout << theight << endl;
twidth = round(width*k2);//扩大后图像的宽
cout << twidth << endl;
Mat dstImage(theight, twidth, src.type(), Scalar(0));
//对得到的新图片进行填充 for (int i = 0; i < height; i++)
{
for (int j = 0; j < width - 1; j++)
{ ia = round(i*k1);
ja = round(j*k2);
//如果位于四个顶角
if (ia == 0 && ja == 0)//左顶角
{
dstImage.at<Vec3b>(ia, ja)[0] = src.at<Vec3b>(i, j)[0];
dstImage.at<Vec3b>(ia, ja)[1] = src.at<Vec3b>(i, j)[1];
dstImage.at<Vec3b>(ia, ja)[2] = src.at<Vec3b>(i, j)[2];
}
else if (ia == theight - 1 && ja == twidth - 1)//左下角
{
dstImage.at<Vec3b>(ia, ja)[0] = src.at<Vec3b>(i, j)[0];
dstImage.at<Vec3b>(ia, ja)[1] = src.at<Vec3b>(i, j)[1];
dstImage.at<Vec3b>(ia, ja)[2] = src.at<Vec3b>(i, j)[2];
}
else if (ia == 0 && ja == twidth - 1)//右顶角
{
dstImage.at<Vec3b>(ia, ja)[0] = src.at<Vec3b>(i, j)[0];
dstImage.at<Vec3b>(ia, ja)[1] = src.at<Vec3b>(i, j)[1];
dstImage.at<Vec3b>(ia, ja)[2] = src.at<Vec3b>(i, j)[2];
}
else if (ia == theight - 1 && ja == twidth - 1)//右下角
{
dstImage.at<Vec3b>(ia, ja)[0] = src.at<Vec3b>(i, j)[0];
dstImage.at<Vec3b>(ia, ja)[1] = src.at<Vec3b>(i, j)[1];
dstImage.at<Vec3b>(ia, ja)[2] = src.at<Vec3b>(i, j)[2];
}
else if (ja == twidth - 1)//第三种情况,最右边
{
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[0] = src.at<Vec3b>(i, j)[0];
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[1] = src.at<Vec3b>(i, j)[1];
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[2] = src.at<Vec3b>(i, j)[2];
}
else if (ia == 0)//第一种情况,最上面
{
dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[0] = src.at<Vec3b>(i, j)[0];
dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[1] = src.at<Vec3b>(i, j)[1];
dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[2] = src.at<Vec3b>(i, j)[2];
}
else if (ja == 0)//第二种情况,最左边
{
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[0] = src.at<Vec3b>(i, j)[0];
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[1] = src.at<Vec3b>(i, j)[1];
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[2] = src.at<Vec3b>(i, j)[2];
} else if (ia == theight - 1)//第四种情况,最下面
{
dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[0] = src.at<Vec3b>(i, j)[0];
dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[1] = src.at<Vec3b>(i, j)[1];
dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[2] = src.at<Vec3b>(i, j)[2];
}
//最后一种情况,位于中间的,将值赋给左上角的值
else
{
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, round((j - 1)*k2) + 1)[0] = src.at<Vec3b>(i, j)[0];
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, round((j - 1)*k2) + 1)[1] = src.at<Vec3b>(i, j)[1];
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, round((j - 1)*k2) + 1)[2] = src.at<Vec3b>(i, j)[2];
}
}
}
for (int i = 0; i < height; i++)
{
//单独考虑最右边
int j = width - 1;
ia = round(i*k1);
ja = round(j*k2);
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja + 1)[0] = src.at<Vec3b>(i, j)[0];
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja + 1)[1] = src.at<Vec3b>(i, j)[1];
dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja + 1)[2] = src.at<Vec3b>(i, j)[2]; } int a1, a2, b1, b2;//用来表示单线性插值中的上下左右中不为0的坐标
//利用单线性进行了行插值
for (int i = 0; i < theight; i++)
{
for (int j = 0; j < twidth; j++)
{
//首先考虑的满足单线性插值的 if (dstImage.at<Vec3b>(i, 0)[0] == 0 && dstImage.at<Vec3b>(i, 0)[1] == 0 && dstImage.at<Vec3b>(i, 0)[2] == 0)
{
continue;
} if (dstImage.at<Vec3b>(i, j)[0] == 0 && dstImage.at<Vec3b>(i, j)[1] == 0 && dstImage.at<Vec3b>(i, j)[2] == 0&& j>0 && j < twidth)
{
b1 = j - 1;
b2 = j + 1; while (dstImage.at<Vec3b>(i, b1)[0] == 0 && dstImage.at<Vec3b>(i, b1)[1] == 0 && dstImage.at<Vec3b>(i, b1)[2] == 0 && b1 >= 0)
{
b1--;
} while (dstImage.at<Vec3b>(i, b2)[0] == 0 && dstImage.at<Vec3b>(i, b2)[1] == 0 && dstImage.at<Vec3b>(i, b2)[2] == 0 && b2 <twidth)
{
b2++;
}
int sfrg0 = floor(((j - b1)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b2)[0] + ((b2 - j)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b1)[0]);
int sfrg1 = floor(((j - b1)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b2)[1] + ((b2 - j)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b1)[1]);
int sfrg2 = floor(((j - b1)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b2)[2] + ((b2 - j)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b1)[2]);
dstImage.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(sfrg0);
dstImage.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(sfrg1);
dstImage.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(sfrg2); }
}
}
//利用单线性对列进行插值 for (int j = 0; j < twidth; j++)
{
for (int i = 0; i < theight; i++)
{ if (dstImage.at<Vec3b>(i, j)[0] == 0 && dstImage.at<Vec3b>(i, j)[1] == 0 && dstImage.at<Vec3b>(i, j)[2] == 0 && i>0 && i < theight)
{
a1 = i - 1;
a2 = i + 1; while (dstImage.at<Vec3b>(a1, j)[0] == 0 && dstImage.at<Vec3b>(a1, j)[1] == 0 && dstImage.at<Vec3b>(a1, j)[2] == 0 && a1 >= 0)
{
a1--;
} while (dstImage.at<Vec3b>(a2, j)[0] == 0 && dstImage.at<Vec3b>(a2, j)[1] == 0 && dstImage.at<Vec3b>(a2, j)[2] == 0 && a2 < twidth)
{
a2++;
}
int s0 = floor(((i - a1)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a2, j)[0] + ((a2 - i)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a1, j)[0]);
int s1 = floor(((i - a1)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a2, j)[1] + ((a2 - i)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a1, j)[1]);
int s2 = floor(((i - a1)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a2, j)[2] + ((a2 - i)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a1, j)[2]);
dstImage.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(s0);
dstImage.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(s1);
dstImage.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(s2); }
}
} imshow("原图", src);
//namedWindow("扩大后的图像", CV_WINDOW_NORMAL);
imshow("扩大后的图像", dstImage); waitKey(0);
return true;
}

  效果图:

Opencv(C++)实现二阶线性插值

上一篇:EBS中查看其他用户或所有用户的请求和输出文件


下一篇:mac终端命令及pycharm常用快捷键记录