1. 程式人生 > >Opencv(C++)實現二階線性插值

Opencv(C++)實現二階線性插值

i++ -- alt key ++ enc 新的 round idt

#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++)實現二階線性插值