#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++)实现二阶线性插值的更多相关文章

  1. opencv边缘检测的入门剖析(第七天)

    ---边缘检测概念理解--- 边缘检测的理解可以结合前面的内核,说到内核在图像中的应用还真是多,到现在为止学的对图像的操作都是核的操作,下面还有更神奇的! 想把边缘检测出来,从图像像素的角度去想,那就 ...

  2. opencv算法学习

    1.改变图像的亮度和对比度: 算法介绍:对每一点像素值的r,g,b,值进行乘法和加法的运算. 代码使用: ; y < image.rows; y++ ) { ; x < image.col ...

  3. opencv的学习笔记5

    总结原博文中的一些边缘检测算子和滤波器.(Canny算子,  Sobel算子,  Laplace算子以及Scharr滤波器) 首先,一般的边缘检测包括三个步骤: 1)滤波:边缘检测的算法主要是基于图像 ...

  4. OpenCV 之 边缘检测

    上一篇 <OpenCV 之 图像平滑> 中,提到的图像平滑,从信号处理的角度来看,实际上是一种“低通滤波器”. 本篇中,数字图像的边缘,因为通常都是像素值变化剧烈的区域 (“高频”),故可 ...

  5. opencv 简单模糊和高斯模糊 cvSmooth

    cv::Mat 是C++版OpenCV的新结构. cvSmooth() 是老版 C API. 没有把C接口与C + + 结合. 建议你们也可以花一些时间看一下介绍. 同样,你如果查看opencv/mo ...

  6. 【OpenCV】边缘检测:Sobel、拉普拉斯算子

    推荐博文,博客.写得很好,给个赞. Reference Link : http://blog.csdn.net/xiaowei_cqu/article/details/7829481 一阶导数法:梯度 ...

  7. OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

    这篇已经写得很好,真心给作者点个赞.题目都是直接转过来的,直接去看吧. Reference Link : http://blog.csdn.net/poem_qianmo/article/detail ...

  8. 学习OpenCV——Surf(特征点篇)&flann

    Surf(Speed Up Robust Feature) Surf算法的原理                                                             ...

  9. [OpenCV] Feature Extraction

    特征检测 特征描述 特征匹配 特征跟踪 “不读白不读,读了还想读” 的一本基础书 低层次特征提取 阈值方法 1. 边缘检测 一阶检测算子 二阶检测算子 相位一致性(频域) 2. 角点检测(局部特征提取 ...

随机推荐

  1. generate parentheses(生成括号)

    Given n pairs of parentheses, write a function to generate all combinations of well-formed parenthes ...

  2. JTA 原理分析

    JTA 深度历险 - 原理与实现 在 J2EE 应用中,事务是一个不可或缺的组件模型,它保证了用户操作的 ACID(即原子.一致.隔离.持久)属性.对于只操作单一数据源的应用,可以通过本地资源接口实现 ...

  3. access treeview读取数据表成树并与子窗体联动

    Private Sub Form_Load()Dim i As IntegerDim rst As DAO.RecordsetSet rst = CurrentDb.OpenRecordset(&qu ...

  4. JqueryMobile学习记录一

    安装 做页面之前首先引用三个文件: <link href="/Scripts/jquery.mobile-1.4.5/jquery.mobile-1.4.5.css" rel ...

  5. windows下mongodb安装详解

    1.打开官网https://www.mongodb.com/download-center?jmp=nav#community 注:这里小伙伴们可是开启下FQ软件psiphon 3下载(不开启FQ好像 ...

  6. Jmeter 性能测试术语

    1.5 术语及缩写词 测试时间:一轮测试从开始到结束所使用的时间 并发线程数:测试时同时访问被测系统的线程数.注意,由于测试过程中,每个线程都是以尽可能快的速度发请求,与实际用户的使用有极大差别,所以 ...

  7. python单线程,多线程和协程速度对比

    在某些应用场景下,想要提高python的并发能力,可以使用多线程,或者协程.比如网络爬虫,数据库操作等一些IO密集型的操作.下面对比python单线程,多线程和协程在网络爬虫场景下的速度. 一,单线程 ...

  8. 详解k8s组件Ingress边缘路由器并落地到微服务 - kubernetes

    写在前面 Ingress 英文翻译 进入;进入权;进食,更准确的讲就是入口,即外部流量进入k8s集群必经之口.这到大门到底有什么作用?我们如何使用Ingress?k8s又是如何进行服务发现的呢?先看一 ...

  9. Day20 Django的使用_基础

    老师网址: https://www.cnblogs.com/yuanchenqi/articles/7652353.html 1,复习上级课,一对一,一对多,多对多的使用 models.py: cla ...

  10. Dubbo配置引发的一个问题--- Duplicate spring bean id

    1.原因 因项目业务需要,要调用RPC框架,项目原本已经依赖了很多RPC接口需要启动时加载,所以准备做成启动时不预加载. 就是在配置的时候加上check=false. 官方文档解释的作用,就是Dubb ...