SpringBoot整合openCV实现360全景相机拍摄的全景图切割,话不多说,直接上代码
1、获取opencv-452.jar
首先,切割全景图需要使用到openCV的依赖jar,这个jar可以通过安装openCV,在openCV的安装目录获取,安装教程请看这里,安装好openCV后,依赖jar在openCV的安装目录下opencv\build\java\opencv-452.jar。
2、代码
引入依赖

 <!-- OpenCV --><dependency><groupId>org</groupId><artifactId>opencv</artifactId><version>4.5.2</version><scope>system</scope><systemPath>${pom.basedir}\src\main\resources\lib\opencv-452.jar</systemPath></dependency><configuration><includeSystemScope>true</includeSystemScope></configuration>

实现全景图切割的工具类

import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.*;
import java.net.URL;public class ConverUtil {/*** 读取本地图片文件** @param filePath* @return Mat*/public static final Mat matRead(String filePath) {//return Highgui.imread("/home/night/webvr/vr.jpg");
//      return Imgcodecs.imread("/home/night/webvr/vr.jpg");return Imgcodecs.imread(filePath);}/*** 读取网络图片** @param urlStr* @return*/public static final BufferedImage bufferReadUrl(String urlStr) {BufferedImage image = null;try {URL url = new URL(urlStr);image = ImageIO.read(url);} catch (Exception e) {e.printStackTrace();}return image;}/*** 图片文件保存** @param fileName* @param mat*/public static final void matSave(String fileName, Mat mat) {//Highgui.imwrite(fileName, mat);//Imgcodecs.imwrite(fileName, mat);BufferedImage buff = matToBuffer(".jpg", mat);bufferSave(fileName, buff);}/*** 读取图片文件** @param filePath* @return*/public static final BufferedImage bufferRead(String filePath) {try {return ImageIO.read(new File(filePath));} catch (IOException e) {e.printStackTrace();}return null;}/*** 图片文件保存** @param fileName* @param buff*/public static final void bufferSave(String fileName, BufferedImage buff) {try {ImageIO.write(buff, "JPEG", new File(fileName));} catch (IOException e) {e.printStackTrace();}}public static final Mat matResize(Mat mat, int width, int height) {Mat target = new Mat(width, height, mat.type());//Imgproc.resize(src, dst, dsize);Imgproc.resize(mat, target, new Size(width, height), 0, 0, Imgproc.INTER_LINEAR);return target;}/*** Mat转换为BufferedImage,已测,可用** @param fileExt* @param mat* @return*/public static final BufferedImage matToBuffer(String fileExt, Mat mat) {MatOfByte mob = new MatOfByte();Imgcodecs.imencode(fileExt, mat, mob);// convert the "matrix of bytes" into a byte arraybyte[] byteArray = mob.toArray();BufferedImage bufImage = null;try {InputStream in = new ByteArrayInputStream(byteArray);bufImage = ImageIO.read(in);} catch (Exception e) {e.printStackTrace();}return bufImage;}/*** BufferedImage转换为Mat,已测,可用** @param bufferedImage* @param imgType* @return*/public static Mat bufferToMat(BufferedImage bufferedImage, int imgType) {final int matType = CvType.CV_8UC3;if (bufferedImage == null) {throw new IllegalArgumentException("bufferToMat-> BufferedImage == null");}if (bufferedImage.getType() != imgType) {BufferedImage image = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), imgType);Graphics2D g = image.createGraphics();try {g.setComposite(AlphaComposite.Src);g.drawImage(bufferedImage, 0, 0, null);} finally {g.dispose();}}byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();Mat mat = Mat.eye(bufferedImage.getHeight(), bufferedImage.getWidth(), matType);mat.put(0, 0, pixels);return mat;}/*** 将Mat图片进行Base64编码* base64编码后的字符串中经常包含“+”号,在C#环境中发送给服务器后,服务器把“+”存成了“ ”空格,而在Java环境下,“+”号依然是加号* 所以在java环境中,解码之前,需要先把编码后的字符串中的“ ”替换成“+”号* <code>String des = des.replaceAll("\\+", "%2B");</code>** @param mat* @return*/
/*public static final String matEncoder(Mat mat) {BufferedImage buff = matToBuffer(".jpg", mat);ByteArrayOutputStream byteout = new ByteArrayOutputStream();try {ImageIO.write(buff, "JPEG", byteout);} catch (IOException e) {e.printStackTrace();}BASE64Encoder encoder = new BASE64Encoder();return encoder.encode(byteout.toByteArray());}
*//*** 图像整体向左旋转90度** @param src Mat* @return 旋转后的Mat*/public static Mat rotateRight(Mat src, int flipCode) {Mat tmp = new Mat();// 此函数是转置、(即将图像逆时针旋转90度,然后再关于x轴对称)Core.transpose(src, tmp);Mat result = new Mat();// flipCode = 0 绕x轴旋转180, 也就是关于x轴对称// flipCode = 1 绕y轴旋转180, 也就是关于y轴对称// flipCode = -1 此函数关于原点对称Core.flip(tmp, result, flipCode);return result;}}

调用方法,企切割

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;import java.awt.image.BufferedImage;
import java.io.File;public class OpenCVUtil {static {String opencvDllName = "E:/Dowin_workspace/tjcloud-designer/tjcloud-designer-web/src/main/resources/lib/opencv_java452.dll";               //Linux 环境//String opencvSoName = "/usr/local/share/java/opencv4/libopencv_java452.so";               //Linux中so文件地址System.load(opencvDllName);}double[][] imageTransform ={{0, 0},{Math.PI / 2, 0},{Math.PI, 0},{-Math.PI / 2, 0},{0, -Math.PI / 2},{0, Math.PI / 2}};public static void main(String[] args) {OpenCVUtil util = new OpenCVUtil();BufferedImage buff = ConverUtil.bufferRead("C:\\Users\\XQD\\Desktop\\kt.jpg");//全景图切割Mat[] cube = util.shear(buff, 1024, 1024);//预览图合成Mat preview = util.mergeImage(cube, 512);}/*** 全景图切割,返回6张图* ossPanoPath  oss存储地址* panoImgPath  本地存储地址*/public Mat[] shear(BufferedImage buff, int targetWidth, int targetHeight) {Mat mat = ConverUtil.bufferToMat(buff, buff.getType());Mat[] cube = new Mat[6];for (int i = 0; i < 6; i++) {cube[i] = sideCubeMapImage(mat, i, targetWidth, targetHeight);}return cube;}/*** @Description: 全景图切割,单面处理* @Param: [source, sideId, sideWidth, sideHeight]* @return: org.opencv.core.Mat* @Author: XQD* @Date:2021/10/22 13:51*/private Mat sideCubeMapImage(Mat source, final int sideId, final int sideWidth, final int sideHeight) {Mat result = new Mat(sideWidth, sideHeight, source.type());System.out.println("==========handle " + sideId + " start ===========");// 获取图片的行列数量float sourceWidth = source.cols();float sourceHeight = source.rows();//分配图的x,y轴Mat mapx = new Mat(sideHeight, sideWidth, CvType.CV_32F);Mat mapy = new Mat(sideHeight, sideWidth, CvType.CV_32F);//计算相邻ak和相反an的三角形张成球体中心final double an = Math.sin(Math.PI / 4);final double ak = Math.cos(Math.PI / 4);double ftu = imageTransform[sideId][0];double ftv = imageTransform[sideId][1];//对于每个图像计算相应的源坐标for (int y = 0; y < sideHeight; y++) {for (int x = 0; x < sideWidth; x++) {//将坐标映射在平面上float nx = (float) y / (float) sideHeight - 0.5f;float ny = (float) x / (float) sideWidth - 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;double u, v;// Project from plane to sphere surface.if (ftv == 0) {// Center faces 中心面u = Math.atan2(nx, ak);v = Math.atan2(ny * Math.cos(u), ak);u += ftu;} else if (ftv > 0) {// Bottom face 低面double d = Math.sqrt(nx * nx + ny * ny);v = Math.PI / 2 - Math.atan2(d, ak);u = Math.atan2(ny, nx);} else {// Top face 顶面//cout << "aaa";double d = Math.sqrt(nx * nx + ny * ny);v = -Math.PI / 2 + Math.atan2(d, ak);u = Math.atan2(-ny, nx);}// Map from angular coordinates to [-1, 1], respectively.u = u / (Math.PI);v = v / (Math.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 spaceu = u / 2.0f + 0.5f;v = v / 2.0f + 0.5f;u = u * (sourceWidth - 1);v = v * (sourceHeight - 1);mapx.put(x, y, u);mapy.put(x, y, v);}}// Do actual  using OpenCV's remapImgproc.remap(source, result, mapx, mapy, Imgproc.INTER_LINEAR, Core.BORDER_CONSTANT, new Scalar(0, 0, 0));// 均值模糊(降噪)Mat image = source.clone();Imgproc.blur(source, image, new Size(3,3),new Point(-1,-1));if (sideId == 0) {ConverUtil.matSave("E:\\data\\kct.tiles\\a.jpg", result);} else if (sideId == 1) {ConverUtil.matSave("E:\\data\\kct.tiles\\b.jpg", result);} else if (sideId == 2) {ConverUtil.matSave("E:\\data\\kct.tiles\\c.jpg", result);} else if (sideId == 3) {ConverUtil.matSave("E:\\data\\kct.tiles\\d.jpg", result);} else if (sideId == 4) {//旋转角度result = ConverUtil.rotateRight(result, 1);ConverUtil.matSave("E:\\data\\kct.tiles\\e.jpg", result);} else if (sideId == 5) {//旋转角度result = ConverUtil.rotateRight(result, 0);ConverUtil.matSave("E:\\data\\kct.tiles\\f.jpg", result);}System.out.println("==========handle " + sideId + " over ===========");return result;}/*** 全景预览图合成*/public Mat mergeImage(Mat[] cube, int width) {Mat mat = new Mat(width * cube.length, width, cube[0].type());for (int i = 0; i < cube.length; i++) {Mat side = ConverUtil.matResize(cube[i], 512, 512);mat.put(i * 512, 0, getByte(side));}ConverUtil.matSave("E:\\data\\kct.tiles\\preview.jpg", mat);return mat;}public byte[] getByte(Mat mat) {int width = mat.cols();int height = mat.rows();int dims = mat.channels();byte[] rgbdata = new byte[width * height * dims];mat.get(0, 0, rgbdata);return rgbdata;}
}

openCV需要依赖的源文件,区分为windows环境和linux环境,windows环境依赖 .dll 文件,linux环境依赖 .so文件。我放在百度网盘,需要的朋友自取,点击这里添加链接描述,提取码:ihj6

SpringBoot整合opencv实现全景图切割相关推荐

  1. opencv用java完成的例子_SpringBoot整合OpenCV的实现示例

    简介 接下来会讲解怎么用SpringBoot整合OpenCV 初始化SpringBoot项目 这里正常初始一个SpringBoot项目 依赖文件 在安装目录下找到以下两个文件,如果不知道怎么安装Ope ...

  2. opencv第三方库JAVA接口,SpringBoot使用OpenCV示例总结

    前言 最近有个项目需要对图片图像进行处理,使用到了开源框架OpenCV全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库:而现在的项目都是基于Sp ...

  3. 五、Springboot 整合Shiro---03认证---第三方QQ登陆

    本章节基于:四.Springboot 整合Shiro---02认证---记住我 在开始之前,先要理解一下oauth2: 推荐去看一下(六.授权码模式):阮一峰讲解的oauth2 下面附上一张阮一峰博客 ...

  4. 很详细的SpringBoot整合UEditor教程

    很详细的SpringBoot整合UEditor教程 2017年04月10日 20:27:21 小宝2333 阅读数:21529 版权声明:本文为博主原创文章,未经博主允许不得转载. https://b ...

  5. java springboot整合zookeeper入门教程(增删改查)

    java springboot整合zookeeper增删改查入门教程 zookeeper的安装与集群搭建参考:https://www.cnblogs.com/zwcry/p/10272506.html ...

  6. SpringBoot第九篇: springboot整合Redis

    这篇文章主要介绍springboot整合redis,至于没有接触过redis的同学可以看下这篇文章:5分钟带你入门Redis. 引入依赖: 在pom文件中添加redis依赖: <dependen ...

  7. es springboot 不设置id_原创 | 一篇解决Springboot 整合 Elasticsearch

    ElasticSearch 结合业务的场景,在目前的商品体系需要构建搜索服务,主要是为了提供用户更丰富的检索场景以及高速,实时及性能稳定的搜索服务. ElasticSearch是一个基于Lucene的 ...

  8. springboot整合shiro使用shiro-spring-boot-web-starter

    此文章仅仅说明在springboot整合shiro时的一些坑,并不是教程 增加依赖 <!-- 集成shiro依赖 --> <dependency><groupId> ...

  9. db2 springboot 整合_springboot的yml配置文件通过db2的方式整合mysql的教程

    springboot整合MySQL很简单,多数据源就master,slave就行了,但是在整合DB2就需要另起一行,以下是同一个yml文件 先配置MySQL,代码如下 spring: datasour ...

最新文章

  1. 静态网页制作html语言入门
  2. 小白视觉第一步保存图片
  3. 云炬随笔20171213
  4. 一休和尚 小布偶 晴天娃娃
  5. 令人惊叹的前端路由原理解析和实现方式
  6. nginx+keepalived搭建主从负载均衡并迅速切换
  7. 使用SQL Server代理生成计划
  8. nvidia控制面板一直闪退如何解决?
  9. ubuntu linux 教程 pdf,Ubuntu 12.04 菜鸟完全使用教程(二) PDF
  10. excel中的数据怎么导入matlab中,将excel中的数据导入matlab教程的方法步骤
  11. Sourcetree下载-使用-快速入门
  12. 服务器fs改变文件内容,SeaweedFS文件系统
  13. Python中切片(Slicing)的运用(:运算符)
  14. Bootstrap框架使用及可视化布局
  15. VMware Workstation Pro v15.0.0官方正版
  16. 用html5看板娘,记在nuxt.js中引入一个萌哒哒的看板娘(Live2d模型)
  17. 如何进行git ssh文件的配置
  18. 大厂面试真题解读:Tomcat的连接器是如何设计的?
  19. mediawiki mysql配置_Mediawiki 常见配置功能
  20. 人大金仓数据库添加FIND_IN_SET函数

热门文章

  1. SAP外协采购单和销售单需求关闭预留未清处理方法
  2. 信息系统集成-辅助知识-知产/法律法规/标准化
  3. java web打包神器_前端开发人员的桌面应用神器 Electron
  4. AI实践之路:朴素贝叶斯
  5. 三角分解(LU分解)
  6. amt是什么意思_汽车中的AT、MT和AMT是什么意思?有什么区别?
  7. username的用法
  8. 根文件系统树的制作及详解
  9. EXCELt添加单引号
  10. markdown语法高级篇