基于OpenCV的全景图剪切程序
来源:互联网 发布:神州专车价格算法 编辑:程序博客网 时间:2024/05/16 10:54
去年实习的时候,接到一个任务将公司软件生成的一张全景图扭曲切割成六个正常的面,然后动态生成一个3D网页。忙活了2天后完成代码。但最终因为某些原因未被采用。
首先配置OpenCV。
找寻了众多资料,找了一个算是我觉得最靠谱的:http://tieba.baidu.com/p/3931605400
安装好OpenCV以后我们来看原始图片
全景图的剪切原理我也不一一叙述了,贴出详细的原理解释:
http://paulbourke.net/geometry/transformationprojection/
接下来我们就po出源码:
#include <opencv2/imgproc/imgproc.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include<math.h>#include <iostream>using namespace cv;using namespace std;float M_PI = 3.14159265358979323846f;float faceTransform[6][2] ={ {0, 0}, {M_PI /2,0}, {M_PI,0}, {-M_PI /2,0}, {0,-M_PI/2}, {0,M_PI/2} };inline void createCubeMapFace(const Mat &in, Mat &face, int faceId = 0, const int width = -1,const int height = -1){ float inWidth = in.cols; float inHeight = in.rows; // 获取图片的行列数量// cout << in.cols;// cout << in.rows;// system("pause"); // Allocate map Mat mapx(height, width, CV_32F); Mat mapy(height, width, CV_32F); //分配图的x,y轴 // Calculate adjacent (ak) and opposite (an) of the // triangle that is spanned from the sphere center //to our cube face. const float an = sin(M_PI / 4); const float ak = cos(M_PI / 4); //计算相邻ak和相反an的三角形张成球体中心// cout << ak;// cout << an;// system("pause"); const float ftu = faceTransform[faceId][0]; const float ftv = faceTransform[faceId][1]; // For each point in the target image, // calculate the corresponding source coordinates. 对于每个图像计算相应的源坐标 for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Map face pixel coordinates to [-1, 1] on plane 将坐标映射在平面上 float nx = (float)y / (float)height - 0.5f; float ny = (float)x / (float)width - 0.5f; nx *= 2; ny *= 2; // Map [-1, 1] plane coord to [-an, an] // thats the coordinates in respect to a unit sphere // that contains our box. nx *= an; ny *= an; float u, v; // Project from plane to sphere surface. if (ftv == 0) { // Center faces u = atan2(nx, ak); v = atan2(ny * cos(u), ak); u += ftu; } else if (ftv > 0) { // Bottom face float d = sqrt(nx * nx + ny * ny); v = M_PI / 2 - atan2(d, ak); u = atan2(ny, nx); } else { // Top face //cout << "aaa"; float d = sqrt(nx * nx + ny * ny); v = -M_PI / 2 + atan2(d, ak); u = atan2(-ny, nx); } // Map from angular coordinates to [-1, 1], respectively. u = u / (M_PI); v = v / (M_PI / 2); // Warp around, if our coordinates are out of bounds. while (v < -1) { v += 2; u += 1; } while (v > 1) { v -= 2; u += 1; } while (u < -1) { u += 2; } while (u > 1) { u -= 2; } // Map from [-1, 1] to in texture space u = u / 2.0f + 0.5f; v = v / 2.0f + 0.5f; u = u*(inWidth-1); v = v*(inHeight-1); mapx.at<float>(x, y) = u; mapy.at<float>(x, y) = v; } } // Recreate output image if it has wrong size or type. if (face.cols != width || face.rows != height || face.type() != in.type()) { face = Mat(width, height, in.type()); /* system("pause");*/ } // Do actual using OpenCV's remap remap(in, face, mapx, mapy, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); // imshow("123", in); // imshow("456", face); if (faceId == 0) { imwrite("F:\\cube0000.png", face); } else if (faceId == 1) { imwrite("F:\\cube0001.png", face); } else if (faceId == 2) { imwrite("F:\\cube0002.png", face); } else if (faceId == 3) { imwrite("F:\\cube0003.png", face); } else if (faceId == 4) { imwrite("F:\\cube0004.png", face); } else if (faceId == 5) { imwrite("F:\\cube0005.png", face); }/* waitKey(10000);*/}int main(){ int faceId = 0; int width = 1296 ; int height = 1296; cv::Mat srcimage = cv::imread("F:\\wmz9(1).hdr");// namedWindow("游戏原画");// imshow("游戏原画", srcimage);// waitKey(6000); cv::Mat resultImage; //resultImage= srcimage(Rect(800, 350, srcimage.cols, srcimage.rows)); for (int i = 0; i < 6; i++) { createCubeMapFace(srcimage, resultImage, i, width, height); }}
该代码在国内应该找不到实际可用的,至少楼主在找的时候没找到。太多骗积分和过于驳杂的代码,以上代码都是我经过自己的理解,精简到可以利用的最佳形式,希望对大家有所帮助。
然后我们就可以看到六张图:
接下来要做的就是把它变成一个3D网页
哦,对,我在程序中生成的是png格式的图片,但我最后网页中显示的jpg,其实只用在程序中的后缀改成.jpg即可,但我太懒了,干脆写了一个.bat文件
ren *.png *.jpg
这是一个改后缀的代码。前面是要改的后缀名(可以为空),后面是最后的后缀名。
由于只用做一个简单的展示效果,我就在这里给大家Po一个最简单的Web网页源码
<!DOCTYPE html><html lang="en"> <head> <title>css transform 3d cube panorama demo</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <style> @-webkit-keyframes spin { from { -webkit-transform: rotateY(0); } to { -webkit-transform: rotateY(-360deg); } } @keyframes spin { from { transform: rotateY(0); } to { transform: rotateY(-360deg); } } html, body { background-color: #000000; margin: 0px; overflow: hidden; width: 100%; height: 100%; } #container, #viewer { width: 100%; height: 100%; } #container { } #viewer { position: absolute; left: 50%; top: 100px; margin-left: -320px; width: 640px; height: 360px; overflow: hidden; -webkit-transition: -webkit-transform 3s; transition: transform 3s; -webkit-perspective: 600px; perspective: 600px; -webkit-transform-style: preserve-3d; transform-style: preserve-3d; } #cube { width: 100%; height: 100%; position: relative; -webkit-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-transform-origin: 50% 50% 750px; //-webkit-animation: spin 12s infinite linear; //animation: spin 12s infinite linear; -webkit-transform: translateZ(-150px); transform: translateZ(-150px); } #cube img { position: absolute; width: 1500px; height: 1500px; top: 50%; left: 50%; margin-top: -750px; margin-left: -750px; opacity: 0.8; -webkit-transition: -webkit-transform 3s; transition: transform 3s; -webkit-transform-style: preserve-3d; transform-style: preserve-3d; -webkit-backface-visibility: hidden; backface-visibility: hidden; } .front { -webkit-transform: translateZ(750px) translateZ(-750px); transform: translateZ(750px) translateZ(-750px); } .right { -webkit-transform: translateZ(750px) rotateY(-90deg) translateZ(-750px); transform: translateZ(750px) rotateY(-90deg) translateZ(-750px); } .left { -webkit-transform: translateZ(750px) rotateY(90deg) translateZ(-750px); transform: translateZ(750px) rotateY(90deg) translateZ(-750px); } .rear { -webkit-transform: translateZ(750px) translateZ(750px) rotateY( 180deg ); transform: translateZ(750px) translateZ(750px) rotateY( 180deg ); } .roof { -webkit-transform: translateZ(750px) rotateX(-90deg) translateZ(-750px); transform: translateZ(750px) rotateX(-90deg) translateZ(-750px); } .floor { -webkit-transform: translateZ(750px) rotateX(90deg) translateZ(-750px); transform: translateZ(750px) rotateX(90deg) translateZ(-750px); } </style> </head> <body> <div id="container"> <div id="viewer"> <div id="cube"> <img class="front" src="texture/cube0000.jpg" alt="" /> <img class="right" src="texture/cube0001.jpg" alt="" /> <img class="rear" src="texture/cube0002.jpg" alt="" /> <img class="left" src="texture/cube0003.jpg" alt="" /> <img class="roof" src="texture/cube0004.jpg" alt="" /> <img class="floor" src="texture/cube0005.jpg" alt="" /> </div> </div> </div> <script src="jquery-2.0.2.min.js"></script> <script>(function() { var x1, y1, moving = false, $viewer = $('#viewer'), $cube = $('#cube'), w_v = $viewer.width(), // width of viewer h_v = $viewer.height(), // height of viewer c_yaw = 0, // current x c_pitch = 0, perspective = 525; // current y $(document).on('mousedown', function(e) { x1 = e.pageX; y1 = e.pageY; moving = true; e.preventDefault(); }); $(document).on('mousemove', function(e) { if( moving === true ) { x2 = e.pageX; y2 = e.pageY; var dist_x = x2 - x1, dist_y = y2 - y1, perc_x = dist_x / w_v, perc_y = dist_y / h_v, yaw = Math.atan2(dist_y, perspective) / Math.PI * 180, pitch = -Math.atan2(dist_x, perspective) / Math.PI * 180, i, vendors = ['-webkit-', '-moz-', '']; c_yaw += yaw; c_pitch += pitch; c_yaw = Math.min(90, c_yaw); c_yaw = Math.max(-90, c_yaw); c_pitch %= 360; yaw = c_yaw; pitch = c_pitch; for(i in vendors) { $cube.css(vendors[i] + 'transform', 'translateZ(-150px) rotateX(' + yaw + 'deg) rotateY(' + pitch + 'deg)'); } x1 = x2; y1 = y2; } e.preventDefault(); }).on('mouseup', function(e) { moving = false; e.preventDefault(); });})(); </script> </body></html>
附上JS的链接:http://pan.baidu.com/s/1bpNwWeb
至于你网页的相对位置:
最后打开html就成功了,用鼠标就可以上下左右的看~~~。
3 0
- 基于OpenCV的全景图剪切程序
- opencv 基于sift的多张图片全景图拼接
- 基于OpenCV全景图像拼接
- 全景图的种类及opencv实现
- opencv全景图拼接
- 基于Threejs的360全景图预览
- 基于OpenCV的抠图程序
- openCV中图像的剪切
- opencv实现全景图_1
- 基于过程的软件测试全景图 (2)
- 基于过程的软件测试全景图 (2)
- 基于过程的软件测试全景图 (2)
- 基于过程的软件测试全景图 (2)
- 基于过程的软件测试全景图 (2)
- 基于过程的软件测试全景图 (2)
- 基于过程的软件测试全景图 (2)
- 基于过程的软件测试全景图 (2)
- 基于过程的软件测试全景图 (2)
- C语言标准库函数getenv的实现
- UI09-UITableViewCell
- CentOS---网络配置详解
- OpenStack——keystone安装
- 将数组中的元素排列成一个最小的数
- 基于OpenCV的全景图剪切程序
- 1122
- 自己抽空写的一个epoll事件处理框架
- sql 对表的操作
- nginx负载均衡
- eclipse自动补全
- MP3的解码模块(VS1003B芯片)的原理和参数设置
- python 3.3 下载带有防盗链的文件
- mySQL解压版配置