zoukankan      html  css  js  c++  java
  • Opencv(C++)实现二阶线性插值

    #include<opencv2opencv.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;
    }
    

      效果图:

  • 相关阅读:
    Java面向对象(02)--封装
    Java面向对象(01)--初识
    Java基础(10)--数组
    Java基础(09)--方法
    python中format输出常用的3种格式
    python 查找列表中重复元素以及重复元素的次数
    HttpRunner六:创建run.py文件,执行套件并生成测试报告
    HttpRunner五:关联参数的应用,获取上一个接口的返回值,用于当前接口的请求值
    HttpRunner四:testcases、testsuites以及参数化的使用
    HttpRunner中在case2中,使用作为请求参数和预期结果,预期结果中值显示是:LazyString($变量key)
  • 原文地址:https://www.cnblogs.com/Qsir/p/8687000.html
Copyright © 2011-2022 走看看