OpenGL(十五) OpenCV+OpenGL实现水面倒影
有两幅原始图片,一个是景物图像,一个是水面图像,尝试生成景物在水中的倒影:
在OpenGL中,加载并显示这个景物图像可以把这个图像作为纹理载入即可,把图像直接选择180度的效果就相当于是在镜面中倒影的效果,剩下水纹的效果本来也想作为纹理叠加上去的,但是试了一下没有成功,干脆直接把水面和景物先融合一下,作为倒影的图像,一次加入到倒影平面的纹理中。融合使用了OpenCV。
OpenCV两幅图像融合代码:
#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp"
#include <iostream> using namespace cv; Mat image,image1,image2;
char* windowName="Image Fusion";
char* trackBarName="TrackBar";
int trackBarValue=0;
int trackBarMax=50; //控制条回调函数
void TrackBarFunc(int ,void(*));
int main(int argc,char *argv[])
{ image1=imread("shanghai.bmp"); image2=imread("water.bmp"); //判断读入是否成功 if(!image1.data|!image2.data) { std::cout<<"打开图片失败,请检查路径!"<<std::endl; return 0; } //调整image2的大小与image1的大小一致,融合函数addWeighted()要求输入的两个图形尺寸相同 resize(image2,image2,Size(image1.cols,image1.rows)); //建立显示窗口 namedWindow(windowName,0); //在图像窗口上创建控制条 createTrackbar(trackBarName,windowName,&trackBarValue,trackBarMax,TrackBarFunc); TrackBarFunc(0,0); waitKey(); imwrite("E:\\water.bmp",image);return 0;
}
void TrackBarFunc(int ,void(*))
{ //转换成融合比例 float rate=(float)trackBarValue/trackBarMax; addWeighted(image1,rate,image2,1-rate,0,image); // namedWindow(windowName,0);imshow(windowName,image);
}
调节水面图像和景物图像的融合比例:
最后选的这一张作为倒影纹理:
使用OpenGL把这两幅图像作为纹理载入,实现倒影效果,OpenGL代码:
#define WindowWidth 600
#define WindowHeight 600
#define WindowTitle "OpenGL水面倒影" #include <glut.h>
#include <stdio.h>
#include <stdlib.h> //定义两个纹理对象编号
GLuint shanghai;
GLuint water; #define BMP_Header_Length 54 //图像数据在内存块中的偏移量 // 函数power_of_two用于判断一个整数是不是2的整数次幂
int power_of_two(int n)
{ if( n <= 0 ) return 0; return (n & (n-1)) == 0;
} /* 函数load_texture
* 读取一个BMP文件作为纹理
* 如果失败,返回0,如果成功,返回纹理编号
*/
GLuint load_texture(const char* file_name)
{ GLint width, height, total_bytes; GLubyte* pixels = 0; GLuint last_texture_ID=0, texture_ID = 0; // 打开文件,如果失败,返回 FILE* pFile = fopen(file_name, "rb"); if( pFile == 0 ) return 0; // 读取文件中图象的宽度和高度 fseek(pFile, 0x0012, SEEK_SET); fread(&width, 4, 1, pFile); fread(&height, 4, 1, pFile); fseek(pFile, BMP_Header_Length, SEEK_SET); // 计算每行像素所占字节数,并根据此数据计算总像素字节数 { GLint line_bytes = width * 3; while( line_bytes % 4 != 0 ) ++line_bytes; total_bytes = line_bytes * height; } // 根据总像素字节数分配内存 pixels = (GLubyte*)malloc(total_bytes); if( pixels == 0 ) { fclose(pFile); return 0; } // 读取像素数据 if( fread(pixels, total_bytes, 1, pFile) <= 0 ) { free(pixels); fclose(pFile); return 0; } // 对就旧版本的兼容,如果图象的宽度和高度不是的整数次方,则需要进行缩放 // 若图像宽高超过了OpenGL规定的最大值,也缩放 { GLint max; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max); if( !power_of_two(width) || !power_of_two(height) || width > max || height > max ) { const GLint new_width = 1024; const GLint new_height = 1024; // 规定缩放后新的大小为边长的正方形 GLint new_line_bytes, new_total_bytes; GLubyte* new_pixels = 0; // 计算每行需要的字节数和总字节数 new_line_bytes = new_width * 3; while( new_line_bytes % 4 != 0 ) ++new_line_bytes; new_total_bytes = new_line_bytes * new_height; // 分配内存 new_pixels = (GLubyte*)malloc(new_total_bytes); if( new_pixels == 0 ) { free(pixels); fclose(pFile); return 0; } // 进行像素缩放 gluScaleImage(GL_RGB, width, height, GL_UNSIGNED_BYTE, pixels, new_width, new_height, GL_UNSIGNED_BYTE, new_pixels); // 释放原来的像素数据,把pixels指向新的像素数据,并重新设置width和height free(pixels); pixels = new_pixels; width = new_width; height = new_height; } } // 分配一个新的纹理编号 glGenTextures(1, &texture_ID); if( texture_ID == 0 ) { free(pixels); fclose(pFile); return 0; } // 绑定新的纹理,载入纹理并设置纹理参数 // 在绑定前,先获得原来绑定的纹理编号,以便在最后进行恢复 GLint lastTextureID=last_texture_ID; glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastTextureID); glBindTexture(GL_TEXTURE_2D, texture_ID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels); glBindTexture(GL_TEXTURE_2D, lastTextureID); //恢复之前的纹理绑定 free(pixels); return texture_ID;
} void display(void)
{ // 清除屏幕 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 设置视角 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(70, 1, 1, 21); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 7,-1.5, 0, 0, 0, 0, 0, -1); // 绘制倒影glBindTexture(GL_TEXTURE_2D, water); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-6.0f, -3.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-6.0f, -3.0f, 5.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(6.0f, -3.0f, 5.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(6.0f, -3.0f, 0.0f); glEnd(); //绘制真实场景glBindTexture(GL_TEXTURE_2D, shanghai); glTranslatef(0,-6,0);glRotatef(180,1,0,0);glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-6.0f, -3.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-6.0f, -3.0f, 5.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(6.0f, -3.0f, 5.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(6.0f, -3.0f, 0.0f); glEnd(); glutSwapBuffers();
} int main(int argc, char* argv[])
{ // GLUT初始化 glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100, 100); glutInitWindowSize(WindowWidth, WindowHeight); glutCreateWindow(WindowTitle); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); // 启用纹理 shanghai = load_texture("shanghai.bmp"); //加载纹理 water= load_texture("water.bmp"); glutDisplayFunc(&display); //注册函数 glutMainLoop(); //循环调用 return 0;
}
这个是没有使用倒影的效果:
倒影效果:
OpenGL(十五) OpenCV+OpenGL实现水面倒影相关推荐
- 【OpenGL】十五、OpenGL 绘制三角形 ( 绘制 GL_TRIANGLE_FAN 三角形扇 )
文章目录 一.绘制 GL_TRIANGLE_FAN 三角形 1.绘制 3 个点的情况 2.绘制 4 个点的情况 3.绘制 5 个点的情况 4.绘制 6 个点的情况 二.相关资源 一.绘制 GL_TRI ...
- [Python图像处理] 三十五.OpenCV图像处理入门、算数逻辑运算与图像融合(推荐)
该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...
- 《OpenCv视觉之眼》Python图像处理十六:Opencv图像处理实战一之图像中的硬币检测
本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...
- 《OpenCv视觉之眼》Python图像处理十九:Opencv图像处理实战四之通过OpenCV进行人脸口罩模型训练并进行口罩检测
本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...
- NeHe OpenGL第三十五课:播放AVI
NeHe OpenGL第三十五课:播放AVI 在OpenGL中播放AVI: 在OpenGL中如何播放AVI呢?利用Windows的API把每一帧作为纹理绑定到OpenGL中,虽然很慢,但它的效果不错. ...
- NeHe OpenGL教程 第四十五课:顶点缓存
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL第二十五课:变形
NeHe OpenGL第二十五课:变形 变形和从文件中加载3D物体: 在这一课中,你将学会如何从文件加载3D模型,并且平滑的从一个模型变换为另一个模型. 欢迎来到这激动人心的一课,在这一课里,我们 ...
- OpenGL 图形库的使用(二十五)—— 高级OpenGL之帧缓冲Framebuffers
https://www.jianshu.com/p/d7066d6a02cc OpenGL 图形库的使用(二十五)-- 高级OpenGL之帧缓冲Framebuffers 刀客传奇 关注 0.2 20 ...
- OpenGL教程翻译 第二十五课 天空盒
第二十五课 天空盒 背景 天空盒是用于增强场景表现力的一个常用技术,它一般通过在相机周围包裹一个纹理来实现.这个纹理通常是一些天空.山川或者摩天大楼等等,下面是游戏 Half-Life 中使用天空盒的 ...
- 用OpenInventor实现的NeHe OpenGL教程-第二十五课
用OpenInventor实现的NeHe OpenGL教程-第二十五课 NeHe教程在这节课中向我们介绍了如何从文件加载3D模型,并且平滑的从一个模型变换为另一个模型.两个模型之间 ...
最新文章
- ACMNO.19 C语言-对角求和 求一个3×3矩阵对角线元素之和。 输入 矩阵 输出 主对角线 副对角线 元素和 样例输入 1 2 3 1 1 1 3 2 1 样例输出 3 7
- v3 微信api 请求微信_企业微信API使用基本教程
- 排序算法(还需补充)
- python各个解释器的用途-常见的Python五大解释器!
- 中文与Unicode码互转(utf-8)
- 问题合集 ------- 用 Eclipse 平台进行 C/C++ 开发
- 径向基函数RBF三维网格变形
- 在哪能找到陌生人聊骚_如何说服陌生人帮助您找到工作
- 【LeetCode】剑指 Offer 28. 对称的二叉树
- 浮点数不能全等比较吗php,php的一些易错知识点整理 | 木凡博客
- ERP+WMS信息一体化案例:汽车钢板弹簧企业【神风弹簧】
- 用组织分析框架分析阿里巴巴集团
- linux otl mysql_Linux下使用OTL操作mysql数据库
- 怎么修改html的空格大小,css设置空格宽度间距样式
- html获取页面点击事件吗,jquery 获取页面点击事件 $(body).click()
- 记录开发内容demo-java华为云发送短信验证码
- 帝国危机,线程要罢工了!
- 浅谈HEVC中的CTU CU PU TU
- 货币等精确计算使用BigDecimal
- vue3源码分析--真的有必要掌握框架的细枝末节吗?
热门文章
- uniapp微信小程序服务器与行内img src图片路径拼接
- git查看分支、创建分支、合并分支
- 开发者工具的简单使用
- GitKraken V8.4.0快速管理整个工作区中的 PR
- dofilter在java中_FilterChain doFilter中的java.lang.NullPointerException方法
- oracle 获取最大id
- 基于JAVA二手儿童闲置物品交易平台计算机毕业设计源码+系统+lw文档+部署
- 信息系统的生命周期 与 ITSS(信息技术服务标准)定义的IT服务生命周期
- 深度学习的原理是什么?
- 电商项目测试实战(四)