opengl显示位图 显示图像问题

2932人阅读
前段时间给员工做培训,做了不少OpenGL下面的Demo,不过onSurfaceChanged 获取的width 和height和屏幕尺寸适中不符合终于找到了&&supports-screens android:anyDensity=&true&/& &设置,获取的尺寸和屏幕相符了但是,贴图却不能显示了,全部变白实机截图模拟器运行效果调查思考了一下原因,我觉得应该是样:Android平台中,当程序在manifest中设置android:anyDensity=&true&后,系统会对创建的bitmap进行缩放,缩放的根据就是Density。而在设备上,opengl的贴图大小必须是2的N次方,模拟器因为是软件模拟,对贴图尺寸没有严格要求。我的图片本来是512*512的,但是被自动缩放后,尺寸就不标准了,所以造成贴图没有成功通过调试确认了这一想法
& &bitmap = BitmapFactory.decodeResource(mContext.getResources(), id + i);
& &int w = bitmap.getWidth();
& &int h = bitmap.getHeight();不设置 android:anyDensity=&true&, w h 为512, 设置后 变为了768然后,我将所有的图片资源,都放到了drawable-hdpi目录下,再运行程序,这次尺寸没有改变,贴图正常了。基于这个问题,这里深入探讨一下android的多分辨率支持机制。android SDK文档中&&android-sdk-windows/docs/guide/practices/screens_support.html,说的其实比较清楚,不过由于是英文的,大家估计通读理解的人并不多,网上说到多分辨率支持,也就是
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:19519次
排名:千里之外
评论:13条
(2)(4)(1)(5)19769人阅读
五、三维重建与
在获取到视差数据后,利用
reProjectImageTo3D
校正方法得到的
矩阵就可以得到环境的三维坐标数据,然后利用
来实现三维重构。
的编程范例,我在
中有详细的讨论,这里就不重复了,下面补充一些细节问题:
reProjectImageTo3D
是怎样计算出三维坐标数据的?
章的朋友对上图中的
矩阵不会陌生,根据以上变换公式,按理说
应该也是通过矩阵运算的方式来计算出三维坐标数据的,但实际上仔细查看源代码,会发现
cvReprojectImageTo3D
用了比较奇怪的方法来实现,主要代码如下:
for( y = 0; y & y++ )
const float* sptr = (const float*)(src-&data.ptr + src-&step*y);
// 视差矩阵指针
float* dptr0 = (float*)(dst-&data.ptr + dst-&step*y), *dptr = dptr0;
// 三维坐标矩阵指针
// 每一行运算开始时,用 当前行号y 乘以Q阵第2列、再加上Q阵第4列,作为初始值
// 记 qq=[qx, qy, qz, qw]&
double qx = q[0][1]*y + q[0][3], qy = q[1][1]*y + q[1][3];
double qz = q[2][1]*y + q[2][3], qw = q[3][1]*y + q[3][3];
// 每算完一个像素的三维坐标,向量qq 累加一次q阵第1列
// 即:qq = qq + q(:,1)
for( x = 0; x & x++, qx += q[0][0], qy += q[1][0], qz += q[2][0], qw += q[3][0] )
double d = sptr[x];
// 计算当前像素三维坐标
// 将向量qq 加上 Q阵第3列与当前像素视差d的乘积,用所得结果的第4元素除前三位元素即可
// [X,Y,Z,W]& = qq + q(:,3) *
iW = 1/W; X=X*iW; Y=Y*iW; Z=Z*iW;
double iW = 1./(qw + q[3][2]*d);
double X = (qx + q[0][2]*d)*iW;
double Y = (qy + q[1][2]*d)*iW;
double Z = (qz + q[2][2]*d)*iW;
if( fabs(d-minDisparity) &= FLT_EPSILON )
const double bigZ = 10000.;
dptr[x*3] = (float)X;
dptr[x*3+1] = (float)Y;
dptr[x*3+2] = (float)Z;
的这种计算方式比较令人费解,我的理解是可能这种方式的计算速度比较快。理论上,直接通过矩阵
[x,y,d,1]&
的乘积就可以得到相同的结果,下面用
来验证一下两种方式是异曲同工的,用
计算方式得到的结果称为&
OpenCV method
&,直接按公式计算得到的结果称为&
Equation method
本身算出的三维坐标作为参考,程序代码如下
im = imread('C:/Stereo IO Data/lfFrame_01.jpg');
data = importdata('C:/Stereo IO Data/disparity_01.txt');
r = data(1);
c = data(2);
disp = data(3:end); % 视差
vmin = min(disp);
vmax = max(disp);
disp = reshape(disp, [c,r])'; % 将列向量形式的 disp 重构为 矩阵形式
OpenCV 是行扫描存储图像,Matlab 是列扫描存储图像
故对 disp 的重新排列是首先变成 c 行 r 列的矩阵,然后再转置回 r 行 c 列
img = uint8( 255 * ( disp - vmin ) / ( vmax - vmin ) );
q = [1. 0. 0. -1.;...
0. 1. 0. -1.;...
0. 0. 0. 5.;...
0. 0. 1..]; % q(4,3) 原为负值,现修正为正值
big_z = 1e5;
pos1 = zeros(r,c,3);
pos2 = zeros(r,c,3);
for i = 1:r
qq = q*[0 i 0 1]';
for j = 1:c
if disp(i,j)&0
% OpenCV method
vec = qq + q(:,3)*disp(i,j);
vec = vec/vec(4);
pos1(i,j,:) = vec(1:3);
% Textbook method
tmp = q*[j,i,disp(i,j),1]'; % j 是列数,i 是行数,分别对应公式中的 x 和 y
pos2(i,j,:) = tmp(1:3)/tmp(4);
pos1(i,j,3) = big_z;
pos2(i,j,3) = big_z;
qq = qq + q(:,1);
subplot(221);
imshow(im); title('Left Frame');
subplot(222);
imshow(img); title('Disparity map');
% Matlab按OpenCV计算方式得到的三维坐标
x = pos1(:,:,1);
y = -pos1(:,:,2);
% 图像坐标系Y轴是向下为正方向,因此需添加负号来修正
z = pos1(:,:,3);
ind = find(z&10000);
% 以毫米为量纲
x(ind)=NaN; y(ind)=NaN; z(ind)=NaN;
subplot(234);
mesh(x,z,y,double(im),'FaceColor','texturemap');
% Matlab 的 mesh、surf 函数支持纹理映射
colormap(gray);
axis([- 00]);
xlabel('Horizonal');ylabel('Depth');zlabel('Vertical'); title('OpenCV method');
view([0 0]);
% view([0 90]);
% view([90 0]);
% Matlab 按公式直接计算得到的三维坐标
x = pos2(:,:,1);
y = -pos2(:,:,2);
z = pos2(:,:,3);
ind = find(z&10000);
% 以毫米为量纲
x(ind)=NaN; y(ind)=NaN; z(ind)=NaN;
subplot(235);
mesh(x,z,y,double(im),'FaceColor','texturemap');
colormap(gray);
axis([- 00]);
xlabel('Horizonal');ylabel('Depth');zlabel('Vertical'); title('Equation method');
view([0 0]);
% 读入OpenCV计算保存到本地的三维坐标作为参考
data=importdata('C:/Stereo IO Data/xyz.txt');
x=data(:,1); y=data(:,2); z=data(:,3);
ind=find(z&1000);
% 以厘米为量纲
x(ind)=NaN; y(ind)=NaN; z(ind)=NaN;
x=reshape(x,[352 288])'; % 数据写入时是逐行进行的,而Matlab是逐列读取
y=-reshape(y,[352 288])';
z=reshape(z,[352 288])';
subplot(236)
mesh(x,z, y,double(im),'FaceColor','texturemap');
colormap(gray);
axis([-100 100 0 900 -50 200]);
xlabel('Horizonal');ylabel('Depth');zlabel('Vertical'); title('OpenCV result');
view([0 0]);
为什么利用修正了的
矩阵所计算得到的三维数据中,
坐标数据是正负颠倒的?
这个问题我觉得可以从图像坐标系与摄像机坐标系的关系这一角度来解释。如上图所示,一般图像坐标系和摄像机坐标系都是以从左至右为
轴正方向,从上至下为
,摄像机坐标系的
轴正方向则是从光心到成像平面的垂线方向。因此,我们得到的三维坐标数据中
轴数据的正负与实际是相反的,在应用时要添加负号来修正。
如何画出三维重建图像和景深图像?
cvReprojectImageTo3D
计算出的三维坐标数据矩阵一般是三通道浮点型的,需要注意的是这个矩阵存储的是三维坐标数据,而不是
颜色值,所以是不能调用
cvShowImage()
等函数来显示这个矩阵,否则就会看到这种图像:
这里出现的明显的四个色块,其实应该是由三维坐标数据中的
轴数据造成,不同象限的数据形成相应的色块。
要画出正确的三维重建图像,可以结合
(可参考我的
(例如保存三维数据到本地然后用
函数画出,例程见本文问题
;也可以考虑在
混合编程)来实现。
深度图像的显示相对比较简单,只要从三维坐标数据中分离出来(可用
函数),经过适当的格式转换(例如转换为
格式),就可用
cvShowImage()
等函数来显示了,伪彩色的深度图
也可以参考我的
给出的例程
稍作修改即可实现。
窗口的图像复制到
格式显示和保存?
中详细给出了将
图像和三维坐标数据复制到
中显示的例程,而在应用中,我们有时候也需要把
实时显示的三维图像复制到
格式保存,以便和其它图像组合起来显示或保存为视频文件。这里给出相应的例程以供参考:
首先在创建
窗口时,显示模式要如下设置:
//***OpenGL Window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition(10,420);
glutInitWindowSize(glWinWidth, glWinHeight);
glutCreateWindow(&3D disparity image&);
在循环中的调用:
//////////////////////////////////////////////////////////////////////////
// OpenGL显示
img3dIpl = img3d;
load3dDataToGL(&img3dIpl);
// 载入需要显示的图像(视差数据)
loadTextureToGL(&img1roi);
// 显示纹理
glutReshapeFunc (reshape);
// 窗口变化时重绘图像
glutDisplayFunc(renderScene);
// 显示三维图像
glutPostRedisplay();
// 刷新画面(不用此语句则不能动态更新图像)
loadPixel2IplImage(imgGL);
// 将 OpenGL 生成的像素值存储到 IplImage 中
loadGLPixelToIplImage
函数定义:
//////////////////////////////////////////////////////////////////////////
// 将OpenGL窗口像素存储到 IplImage 中
loadGLPixelToIplImage(IplImage* img)
const int n = 3*glWinWidth*glWinH
float *pixels = (float *)malloc(n * sizeof(GL_FLOAT));
IplImage *tmp = cvCreateImage(cvSize(glWinWidth, glWinHeight), 8, 3);
tmp-&origin = CV_ORIGIN_BL;
/* 后台缓存的图像数据才是我们需要复制的,若复制前台缓存会把可能的叠加在OpenGL窗口上的对象(其它窗口或者鼠标指针)也复制进去*/
glReadBuffer(GL_BACK);
glReadPixels(0, 0, glWinWidth, glWinHeight, GL_RGB, GL_FLOAT, pixels);
int k = 0;
for(int i = 0 ; i & glWinH i++)
for(int j = 0 ; j & glWinW j++,k+=3)
CvPoint pt = {j, glWinHeight - i - 1};
uchar* temp_ptr = &((uchar*)(tmp-&imageData + tmp-&widthStep*pt.y))[pt.x*3];
//OpenGL采用的是BGR格式,所以,读出来以后,还要换一下R&-&B,才能得到RGB
temp_ptr[0] = pixels[k+2] * 255; //blue
temp_ptr[1] = pixels[k+1] * 255; //green
temp_ptr[2] = pixels[k] * 255;
cvResize(tmp, img);
// 释放内存
free(pixels);
cvReleaseImage(&tmp);
显示效果如下:
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1458999次
积分:14705
积分:14705
排名:第212名
原创:186篇
转载:66篇
评论:1766条
(1)(1)(1)(7)(1)(2)(1)(2)(2)(13)(2)(2)(2)(6)(1)(2)(3)(1)(2)(4)(6)(4)(4)(1)(1)(2)(1)(6)(2)(3)(6)(1)(16)(12)(6)(8)(11)(3)(12)(28)(65)解矿体在地下空间的贮存情况,从而可以更好地为采矿工程设. 计和工程施工服务,..
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
基于OpenGL的真实感图形绘制技术及应用3
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口当前位置: &
OpenGL-2D-Drawing-GD
资源说明:使用OpenGL实现一个2D二维图形绘制控件(解决GDI过慢问题)源代码:此前作者正忙于一个项目,需要绘制很多的二维图形。开始想着使用GDI,不过GDI对于绘制很多的图像来说实在是太慢了,所以,一个解决办法是:使用OpenGL实现一个能够绘制二维图形的用户控件。-
部分文件列表(点击文件名可查看文件内容)
最新本分类资源
这本是关于vc与opengl开发的书籍,内容丰富全面,特别适合初学者- ...
在delphi下开发OpenGL程序的最好控件包,可以方便地实现纹理、灯光、粒子等复杂的特效 ...
用OpenGL编写的水的场景,对于学习OpenGL的人来说很有用,大家看看。- ...
用VC编写的爆炸场景,很逼真。可以让你看到真实的爆炸效果哦。- ...
用OpenGL制作的三维动画,很好看的,很逼真,可以让你更好的了解OpenGL。- ...
一个利用OpenGL制作的三维动画,很具有逼真感。-
基于OpenGL的高级图形编程技术,对OpenGL的初学者很有帮助!
资源共享,大家一起进步! ...
VC中OpenGL编程实现虚拟现实的源代码-
下雪模拟程序,采用opengle,有详细的注释。-
用OPENGL实现的,可以用来实现定点的Bezier曲线曲面的绘制.用VC环境加上OPENG ...
本类热门下载
一个利用OpenGL制作的三维动画,很具有逼真感。-
这本是关于vc与opengl开发的书籍,内容丰富全面,特别适合初学者- ...
基于OpenGL的高级图形编程技术,对OpenGL的初学者很有帮助!
资源共享,大家一起进步! ...
这是在OPENGL下开发的一款游戏源代码,效果很好。-
用OpenGL编写的水的场景,对于学习OpenGL的人来说很有用,大家看看。- ...
边学边编的基于opengl的搜索雷达显示界面-
用VC编写的爆炸场景,很逼真。可以让你看到真实的爆炸效果哦。- ...
图象拼接代码,必须使用OpenGL的glut.h header file,压缩档内含有glut.h使用说明- ...
用OpenGL制作的三维动画,很好看的,很逼真,可以让你更好的了解OpenGL。- ...
在delphi下开发OpenGL程序的最好控件包,可以方便地实现纹理、灯光、粒子等复杂的特效 ...
友情链接:
CopyRight & 2008- All Rights reserved. 苏ICP备
号 京公网安备:95

我要回帖

更多关于 opengl显示位图 的文章

 

随机推荐