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实现水面倒影的更多相关文章
- NeHe OpenGL教程 第四十五课:顶点缓存
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十五课:播放AVI
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十五课:变形
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第十五课:纹理图形字
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- OpenCV开发笔记(六十五):红胖子8分钟带你深入了解ORB特征点(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- OpenCV+OpenGL 双目立体视觉三维重建
0.绪论 这篇文章主要为了研究双目立体视觉的最终目标--三维重建,系统的介绍了三维重建的整体步骤.双目立体视觉的整体流程包括:图像获取,摄像机标定,特征提取(稠密匹配中这一步可以省略),立体匹配,三维 ...
- 【OpenCV新手教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/28261997 作者:毛星云( ...
- Android平台OpenGL ES/Assimp/OpenCV/GLM集成说明
Android平台OpenGL ES/Assimp/OpenCV/GLM集成说明 本文代码见: https://github.com/jiangxincode/OpenGLDemo 集成Assimp ...
- 深入理解OpenGL拾取模式(OpenGL Picking)
深入理解OpenGL拾取模式(OpenGL Picking) 本文转自:http://blog.csdn.net/zhangci226/article/details/4749526 在用OpenGL ...
- Coding and Paper Letter(十五)
资源整理. 1.Nature Climate Change论文"Higher temperatures increase suicide rates in the United States ...
随机推荐
- 神经网络 vs 大脑
海马区域(负责记忆的关键区域) 0. 常见概念 神经递质:neurotransmitter 在突触传递中是担当"信使"的特定化学物质.简称递质. 重要的神经递质有:乙酰胆碱: 1. ...
- angular自定义指令相关知识及代码
原文地址 https://www.jianshu.com/p/0c015862156d 大纲 1.自定义指令之——属性指令 2.自定义属性指令的运行原理 3.自定义属性指令代码实践 4.自定义结构指令 ...
- IOS开发核心动画六:动画组
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutl ...
- iOS开发之Quarz2D:九:图形上下文矩阵操作
#import "VCView.h" @implementation VCView - (void)drawRect:(CGRect)rect { // Drawing code ...
- ios开发之级联菜单(两个tableView实现)
一:在ios项目实际开发中经常会看到级联菜单的效果:如图:点击左侧菜单,右侧菜单刷新数据.此篇用两个tableView来实现如图效果: 二:代码: 1:构造数据模型:利用kvc快速构建数据模型 #im ...
- 【codeforces 754D】Fedor and coupons
time limit per test4 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- spring mvc redirect 重定向 跳转并传递参数
在项目中做form表单功能提交时,防止用户客户端后退或者刷新时重复提交问题,需要在服务端进行重定向跳转,具体跳转方式有以下几种方式: 公用代码: @RequestMapping(value=" ...
- 树莓派——root用户和sudo
Linux操作系统是一个多用户操作系统,它同意多个用户登录和使用一台计算机. 为了保护计算机(和其它用户的隐私).用户都被限制了能做的事情. 大多数用户都同意执行计算机上大部分程序,而且编辑和保存存放 ...
- 小强的HTML5移动开发之路(30)—— JavaScript回顾5
一.查找 第一种方式:依据id查找 var obj = document.getElementById(id); //document是HTMLDocument的实例 <html> & ...
- Javascript中eval解析的json的几种用法
eval解析json字符串可用的三种方式都可以实现... <!DOCTYPE html> <html> <head> <meta charset=" ...