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++)实现二阶线性插值的更多相关文章
- opencv边缘检测的入门剖析(第七天)
---边缘检测概念理解--- 边缘检测的理解可以结合前面的内核,说到内核在图像中的应用还真是多,到现在为止学的对图像的操作都是核的操作,下面还有更神奇的! 想把边缘检测出来,从图像像素的角度去想,那就 ...
- opencv算法学习
1.改变图像的亮度和对比度: 算法介绍:对每一点像素值的r,g,b,值进行乘法和加法的运算. 代码使用: ; y < image.rows; y++ ) { ; x < image.col ...
- opencv的学习笔记5
总结原博文中的一些边缘检测算子和滤波器.(Canny算子, Sobel算子, Laplace算子以及Scharr滤波器) 首先,一般的边缘检测包括三个步骤: 1)滤波:边缘检测的算法主要是基于图像 ...
- OpenCV 之 边缘检测
上一篇 <OpenCV 之 图像平滑> 中,提到的图像平滑,从信号处理的角度来看,实际上是一种“低通滤波器”. 本篇中,数字图像的边缘,因为通常都是像素值变化剧烈的区域 (“高频”),故可 ...
- opencv 简单模糊和高斯模糊 cvSmooth
cv::Mat 是C++版OpenCV的新结构. cvSmooth() 是老版 C API. 没有把C接口与C + + 结合. 建议你们也可以花一些时间看一下介绍. 同样,你如果查看opencv/mo ...
- 【OpenCV】边缘检测:Sobel、拉普拉斯算子
推荐博文,博客.写得很好,给个赞. Reference Link : http://blog.csdn.net/xiaowei_cqu/article/details/7829481 一阶导数法:梯度 ...
- OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放
这篇已经写得很好,真心给作者点个赞.题目都是直接转过来的,直接去看吧. Reference Link : http://blog.csdn.net/poem_qianmo/article/detail ...
- 学习OpenCV——Surf(特征点篇)&flann
Surf(Speed Up Robust Feature) Surf算法的原理 ...
- [OpenCV] Feature Extraction
特征检测 特征描述 特征匹配 特征跟踪 “不读白不读,读了还想读” 的一本基础书 低层次特征提取 阈值方法 1. 边缘检测 一阶检测算子 二阶检测算子 相位一致性(频域) 2. 角点检测(局部特征提取 ...
随机推荐
- sql server对并发的处理-乐观锁和悲观锁
https://www.cnblogs.com/dengshaojun/p/3955826.html sql server对并发的处理-乐观锁和悲观锁 假如两个线程同时修改数据库同一条记录,就会导致后 ...
- JAVA学习总结-面向对象
前言:java面向对象中的知识可以说是整个java基础最核心的部分,不知不觉已经学完快2个月了,是时候复习一波了,刚开始学习的时候被绕的很懵逼,这次总结完毕之后有了很多新的感悟,这就是所谓的每有会意, ...
- flash 视频 死机(转贴)
http://zhidao.baidu.com/question/120464366 打开有关flash的网站就定屏死机 打开flash的网站经常定屏死机,打开酷狗,看土豆网遇到旁边那些广告也一样死机 ...
- MariaDB/MySQL备份和恢复(一):mysqldump工具用法详述
本文目录:1.备份分类2.备份内容和备份工具3.mysqldump用法详述 3.1 语法选项 3.1.1 连接选项 3.1.2 筛选选项 3.1.3 DDL选项 3.1.4 字符集选项 3.1.5 复 ...
- 判断某个方法是否存在,解析php函数function_exists (),method_exists()与is_callable()的区别
php函数function_exists (),method_exists() 与is_callable()的区别在哪? 先来讲下后两个:method_exists() 与is_callable(): ...
- 二叉树,AVL树和红黑树
为了接下来能更好的学习TreeMap和TreeSet,讲解一下二叉树,AVL树和红黑树. 1. 二叉查找树 2. AVL树 2.1. 树旋转 2.1.1. 左旋和右旋 2.1.2. 左左,右右,左右, ...
- Python 装饰器(Decorator)
装饰器的语法为 @dec_name ,置于函数定义之前.如: import atexit @atexit.register def goodbye(): print('Goodbye!') print ...
- 软件及博客的markdown支持度的评测
软件 vscode vscode原生支持markdown,但对数学公式的支持不太好,用 $$包含的数学公式不支持换行,而且在数学公式里面不能输入中文 Typora 非常简洁优美的软件,只有预览页,没有 ...
- 关于C#中程序功能实现,对代码选择的思考
body { background-color: rgb(60,60,60) } 接触C#语言只有短短几天时间,想要写出什么高大上的深入性研究文章,估计也是满篇的猜想和一些没有逻辑的推断.截至目前而言 ...
- 读《图解HTTP》有感-(与HTTP协作的WEB服务器)
写在前面 Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以向浏览器等Web客户端提供文档: 一台web服务器可以搭建多个独立域名的web网站,也可以作为通信路径(路由)上的中 ...