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. 角点检测(局部特征提取 ...
随机推荐
- Centos7 时区的设置
Linux 系统(我特指发行版, 没说内核) 下大部分软件的风格就是不会仔细去考虑向后 的兼容性, 比如你上个版本能用这种程序配置, 没准到了下一个版本, 该程序已经不见了. 比如 sysvinit ...
- Android的颜色值转换
Android的颜色int值比较变态,是个负值,用计算机术语讲叫补码,手工转换比较麻烦,首先看看文档 https://developer.android.com/reference/android/g ...
- CentOs 6 或 7 yum安装JDK1.8 (内含报 PYCURL ERROR 6 - "Couldn't resolve host 'mirrors.163.com'"错误解决方案)并分析为什么不能yum安装
查看JDK的安装路径 # java -version============================查看Linux系统版本信息# cat /etc/redhat-releaseCentOS r ...
- 详解Java的Spring框架中的注解的用法
转载:http://www.jb51.net/article/75460.htm 1. 使用Spring注解来注入属性 1.1. 使用注解以前我们是怎样注入属性的 类的实现: class UserMa ...
- JS跨域:1.解决方案之-SpringMVC拦截器
一 拦截器代码 package com.wiimedia.controller; import java.util.List; import javax.servlet.http.HttpServle ...
- python笔记:#011#循环
循环 目标 程序的三大流程 while 循环基本使用 break 和 continue while 循环嵌套 01. 程序的三大流程 在程序开发中,一共有三种流程方式: 顺序 -- 从上向下,顺序执行 ...
- Hibernate二级缓存简述及基于Spring4,Hibernate5,Ehcache3的二级缓存配置
Hibernate L2缓存 缓存的分类 L2缓存工作原理 放入二级缓存的数据 Ehcache 依赖 ehcache.xml 常用的memoryStoreEvictionPolicy(缓存算法) eh ...
- STM32f030f4p6 内部flash 打包读写
最近做到的项目在运行需要把一组uint8_t(unsigned char)的数据进行掉电储存,想到单片机STM32f030f4p6内部flash可以直接由程序操作,写了以下代码用于uint8_t数据打 ...
- kvm常见故障及解决
一.启动虚拟机Connection reset by peer # virsh start vmhost1error: Failed to start domain vmhost1error: Una ...
- PAT1086:Tree Traversals Again
1086. Tree Traversals Again (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...