本人因为公司需求,需要做个VR全景功能,所以研究VR功能。在网上查询了一些资料以后发现krpano软件可以满足这个需求,果断学习之,如果大家有兴趣的话可以看下这些内容:

krpano360,http://www.krpano360.com 这个网站,我是从入门教程看到初级教程,在此先感谢下网站所有人“肥宗”哥,感谢他的无私分享,如果你看完了我说的内容的话,基本也了解了krpano基本功能。

分享下krpano的下载地址:https://pan.baidu.com/s/1oAaHjB0  密码:j6w8

关于注册码,可以加我微信或者留言给我,我私信给你。

好了,言归正传。下面我们开始讲解如何krpano功能化,首先我也是参考了cdsn的大神分享的文章,在此先谢谢“J_小浩子”的文章,地址:http://blog.csdn.net/change_on/article/details/77373644,有兴趣可以先看下。

说说如何功能话krpano的思路:   先来看下krpano的文件夹结构,根目录是vtour

这是最后生成好的文件,来说明下吧,panos-放置全景图或者缩略图文件夹,plugins-公用的插件文件夹,skin-皮肤以及一些配置文件夹,tour.html-主访问页面,tour.js-js文件用户html引用,tour.swf-用于flash引用,tour.xml-主配置文件。关于具体思路请参考小浩子大神的文章,本人不在这里重复阐述,说下最后我的结果文件夹内容:

这是最后的输出文件夹内容,其中plugin,skin和tour.html是公用的,target文件夹是每次上传都不同的。

   主要是在大神们的思路和代码上进行了一些代码优化,分离了方法代码和执行代码,增加了背景音乐,底部logo和载入进度条等功能。

下面我们来看下具体的实现代码:

首先是:krpano类封装

/*** */
package krpano;/*** krpano类封装* @author Administrator**/
public class KrpanoEntity {/*** 总标题*/private String title;/*** 场景标题*/private String[] sceneTitle;/*** krpano exe执行文件地址*/private String krpanoPath;/*** 源文件地址*/private String sourcePath;/*** 目标文件夹*/private String targetPath;/*** 载入动画地址*/private String loadingPath;/*** 音乐文件地址*/private String musicPath;/*** 底部logo文件地址*/private String logoPath;public String getKrpanoPath() {return krpanoPath;}public String getSourcePath() {return sourcePath;}public String getTargetPath() {return targetPath;}public String getLoadingPath() {return loadingPath;}public String getMusicPath() {return musicPath;}public String getLogoPath() {return logoPath;}public void setKrpanoPath(String krpanoPath) {this.krpanoPath = krpanoPath;}public void setSourcePath(String sourcePath) {this.sourcePath = sourcePath;}public void setTargetPath(String targetPath) {this.targetPath = targetPath;}public void setLoadingPath(String loadingPath) {this.loadingPath = loadingPath;}public void setMusicPath(String musicPath) {this.musicPath = musicPath;}public void setLogoPath(String logoPath) {this.logoPath = logoPath;}public String getTitle() {return title;}public String[] getSceneTitle() {return sceneTitle;}public void setTitle(String title) {this.title = title;}public void setSceneTitle(String[] sceneTitle) {this.sceneTitle = sceneTitle;}}

krpano功能化的方法类:

package krpano;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.util.List;import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;/*** krpano功能化的方法* @author Administrator**/
public class UnitedMethod {public boolean copyFile(String oldPath, String newPath) throws IOException {File oldFile = new File(oldPath);if (!oldFile.exists())return false;File newFile = new File(newPath);// 判断是否有这个文件有不管没有创建if (!newFile.exists()) {newFile.mkdirs();}fileCopy(oldFile.getPath(),newPath + File.separator + oldFile.getName());// 继续调用复制方法// 递归的地方,自己调用自己的方法,就可以复制文件夹的文件夹了return true;}/*** 复制文件或者文件夹下的所有内容* @param oldPath* @param newPath* @throws IOException*/public boolean copyFolder(String oldPath, String newPath) throws IOException {File oldFile = new File(oldPath);if (!oldFile.exists())return false;File newFile = new File(newPath);// 判断是否有这个文件有不管没有创建if (!newFile.exists()) {newFile.mkdirs();}// 遍历文件及文件夹for (File file : oldFile.listFiles()) {if (file.isFile()) {// 文件fileCopy(file.getPath(), newPath + File.separator + file.getName()); // 调用文件拷贝的方法} else if (file.isDirectory()) {// 文件夹copyFolder(file.getPath(), newPath + File.separator + file.getName());// 继续调用复制方法// 递归的地方,自己调用自己的方法,就可以复制文件夹的文件夹了}}return true;}private  void fileCopy(String src,String des) throws IOException{//io流固定格式BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(des));int i = -1;//记录获取长度byte[] bt = new byte[2014];//缓冲区while ((i = bis.read(bt))!=-1) {bos.write(bt, 0, i);}bis.close();bos.close();//关闭流}/*** 删除文件或者文件夹下的所有内容* @param src*/public void delFile(String src){File file = new File(src);if(!file.exists()) return;delDir(file);}/*** 递归删除文件* @param f*/private static void delDir(File f) {// 判断是否是一个目录, 不是的话跳过, 直接删除; 如果是一个目录, 先将其内容清空.if(f.isDirectory()) {// 获取子文件/目录File[] subFiles = f.listFiles();// 遍历该目录for (File subFile : subFiles) {// 递归调用删除该文件: 如果这是一个空目录或文件, 一次递归就可删除. 如果这是一个非空目录, 多次// 递归清空其内容后再删除delDir(subFile);}}// 删除空目录或文件f.delete();}public Document readeXMLDemo(String sourcePath) throws DocumentException{File file = new File(sourcePath);if(!file.exists()) return null;// 创建saxReader对象  SAXReader reader = new SAXReader();  // 通过read方法读取一个文件 转换成Document对象  Document document = reader.read(file);  return document;//遍历所有的元素节点  // listNodes(node); }/*** 修改vr标题* @param fileFolder* @param title* @throws Exception*/public void updateVtourTitle(String fileFolder,String title) throws Exception{if(null == title || StringUtils.isEmpty(title)) return;String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;Document tour_doc = this.readeXMLDemo(tour_filePath);if(null == tour_doc) return;Element tour_root = tour_doc.getRootElement(); Attribute title_attr =  tour_root.attribute("title");title_attr.setValue(title);this.writer(tour_doc, tour_filePath);}/*** 修改每个场景的标题值* @param fileFolder* @param sceneTitles* @throws Exception*/public void updateVtourSceneTitle(String fileFolder,String[] sceneTitles) throws Exception{if(null == sceneTitles || sceneTitles.length == 0) return;String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;Document tour_doc = this.readeXMLDemo(tour_filePath);if(null == tour_doc) return;Element tour_root = tour_doc.getRootElement(); List<Element> sceneTitle_list =  tour_root.elements("scene");for(int i =0,size = sceneTitle_list.size();i < size;i++){sceneTitle_list.get(i).attribute("title").setValue(sceneTitles[i]);}this.writer(tour_doc, tour_filePath);}/*** 修改vtour.xml中的vtourskin路径地址* @param fileFolder* @throws Exception */public void updateVtourSkinAddr(String fileFolder) throws Exception{String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;Document tour_doc = this.readeXMLDemo(tour_filePath);if(null == tour_doc) return;Element tour_root = tour_doc.getRootElement(); Element vtourskin_element =  tour_root.element("include");Attribute attr =  vtourskin_element.attribute("url");attr.setValue("../" + attr.getValue());this.writer(tour_doc, tour_filePath);}/*** 增加vr背景音乐和控制按钮* @param fileFolder* @param musicPath* @throws Exception*/public void addMusicElement(String fileFolder,String musicPath) throws Exception {//tour.xml文件解析的根节点String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;Document tour_doc = this.readeXMLDemo(tour_filePath);if(null == tour_doc) return;File music_file = new File(musicPath);if(!music_file.exists()) return ;Element tour_root = tour_doc.getRootElement(); Element plugin_element =  tour_root.addElement("plugin");plugin_element.addAttribute("name", "soundinterface");plugin_element.addAttribute("url.flash", "%HTMLPATH%/plugins/soundinterface.swf");plugin_element.addAttribute("url.html5", "%HTMLPATH%/plugins/soundinterface.js");plugin_element.addAttribute("rootpath", "");plugin_element.addAttribute("preload", "true");plugin_element.addAttribute("keep", "true");//拷贝声音文件到目录下this.copyFile(musicPath, fileFolder);Element action_element =  tour_root.addElement("action");action_element.addAttribute("name", "bgsnd_action");action_element.addAttribute("autorun", "onstart");action_element.addText("playsound(bgsnd, '%SWFPATH%/"+ music_file.getName()+"', 0);");this.writer(tour_doc, tour_filePath);//skin/vtourskin.xml文件解析的根节点,增加声音控制按钮
//        String vtourskin_filePath =fileFolder + File.separator + VTOURSKIN_NAME;
//        Document vtourskin_doc = this.readeXMLDemo(vtourskin_filePath);
//        if(null == vtourskin_doc) return;
//        Element vtourskin_root = vtourskin_doc.getRootElement();
//        //查找bar_button节点
//        List<Element> list_1 = vtourskin_root.elements();
//        Element skin_layer_element = null;
//        for(Element ee : list_1){
//            if(null != ee.attributeValue("name") && "skin_layer".equals(ee.attributeValue("name").toString())){
//                skin_layer_element = ee;
//                break;
//            }
//        }
//        List<Element> list_2 = skin_layer_element.elements();
//        Element control_bar_element = null;
//        for(Element ee : list_2){
//            if(null != ee.attributeValue("name") && "skin_control_bar".equals(ee.attributeValue("name").toString())){
//                control_bar_element = ee;
//                break;
//            }
//        }
//
//        Element bar_button_element  =  control_bar_element.addElement("layer");
//        bar_button_element.addAttribute("name", "skin_btn_sound");
//        bar_button_element.addAttribute("style", "skin_base|skin_glow");
//        bar_button_element.addAttribute("crop", "64|704|64|64");
//        bar_button_element.addAttribute("align", "right");
//        bar_button_element.addAttribute("x", "130");
//        bar_button_element.addAttribute("y", "0");
//        bar_button_element.addAttribute("scale", "0.5");
//        bar_button_element.addAttribute("onclick", "pausesoundtoggle(bgsnd);switch(crop,64|704|40|64,64|704|64|64);switch(alpha,1,0.25);switch(ox,0,-12)");
//        this.writer(vtourskin_doc, vtourskin_filePath);}/*** 新增底部logo图片* @param fileFolder* @param logoFloder 存放logo和配置文件的文件夹目录* @throws Exception */public void addNadirLogo(String fileFolder,String logoFloder) throws Exception{File file = new File(fileFolder);if(!file.exists()) return ;File logoFile = new File(fileFolder + File.separator + KrpanoContants.LOGO_NAME);if(!logoFile.exists()) logoFile.mkdir();//拷贝logo文件到vr目录下this.copyFolder(logoFloder, logoFile.getPath());//tour.xml文件解析的根节点String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;Document tour_doc = this.readeXMLDemo(tour_filePath);if(null == tour_doc) return;Element tour_root = tour_doc.getRootElement(); Element plugin_element =  tour_root.addElement("include");plugin_element.addAttribute("url", "logo/nadir-logo.xml");this.writer(tour_doc, tour_filePath);}/*** 增加进度条动画* @param fileFolder* @param loadingFloder* @throws Exception*/public void addLoadingAnimation(String fileFolder,String loadingFloder) throws Exception{File file = new File(fileFolder);if(!file.exists()) return ;File logoFile = new File(fileFolder + File.separator + KrpanoContants.LOADING_NAME);if(!logoFile.exists()) logoFile.mkdir();//拷贝logo文件到vr目录下this.copyFolder(loadingFloder, logoFile.getPath());//tour.xml文件解析的根节点String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;Document tour_doc = this.readeXMLDemo(tour_filePath);if(null == tour_doc) return;Element tour_root = tour_doc.getRootElement(); Element animation_element =  tour_root.addElement("include");animation_element.addAttribute("url", "loading/loadinganimation.xml");Element text_element =  tour_root.addElement("include");text_element.addAttribute("url", "loading/loadingpercenttext.xml");Element bar_element =  tour_root.addElement("include");bar_element.addAttribute("url", "loading/loadingbar.xml");this.writer(tour_doc, tour_filePath);}/** * 把document对象写入新的文件 *  * @param document * @throws Exception */  public void writer(Document document,String filePath) throws Exception {  // 紧凑的格式  // OutputFormat format = OutputFormat.createCompactFormat();  // 排版缩进的格式  OutputFormat format = OutputFormat.createPrettyPrint();  // 设置编码  format.setEncoding("UTF-8");  // 创建XMLWriter对象,指定了写出文件及编码格式  // XMLWriter writer = new XMLWriter(new FileWriter(new  // File("src//a.xml")),format);  XMLWriter writer = new XMLWriter(new OutputStreamWriter(  new FileOutputStream(new File(filePath)), "UTF-8"), format);  // 写入  writer.write(document);  // 立即写入  writer.flush();  // 关闭操作  writer.close();  }  public static void main(String[] args) throws Exception{UnitedMethod um = new UnitedMethod();String filePath = "E:\\works\\krpano\\test\\target";//um.addMusicElement(filePath, "E:\\one.mp3");//um.addNadirLogo(filePath, "E:\\works\\krpano\\krpano_test\\vtour\\logo");//um.addLoadingAnimation(filePath, "E:\\works\\krpano\\krpano_test\\vtour\\loading");//um.updateVtourSkinAddr(filePath);um.updateVtourSceneTitle(filePath, new String[]{"千年香榧-1","千年香榧-2"});}}

krpano调用类:

/*** */
package krpano;import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;import org.w3c.dom.Document;/*** krpano执行文件* @author Administrator**/
public class ExecuteMethod {/*** @param args* @throws Exception */public static void main(String[] args) throws Exception {ExecuteMethod em = new ExecuteMethod();KrpanoEntity krEntity = new KrpanoEntity();krEntity.setSourcePath("E:\\works\\krpano\\test");krEntity.setTargetPath("E:\\works\\krpano\\test\\target");krEntity.setKrpanoPath("E:\\works\\krpano\\krpano-1.19-pr14-win");krEntity.setMusicPath("E:\\works\\krpano\\public\\one.mp3");krEntity.setLoadingPath("E:\\works\\krpano\\public\\loading");krEntity.setLogoPath("E:\\works\\krpano\\public\\logo");krEntity.setTitle("一亩云-千年香榧");krEntity.setSceneTitle(new String[]{"千年香榧-1","千年香榧-2"});em.executeKrpanoExe(krEntity);}/*** 执行krpano应用程序进行输出,输出地址为:sourcePath\\vtour* @param krpanoPath* @param sourcePath* @throws InterruptedException */private void executeKrpanoExe(KrpanoEntity krEntity) throws Exception{File sourceFile = new File(krEntity.getSourcePath());if(!sourceFile.exists()) return ;String ex = "krpanotools32.exe makepano -config=\\templates\\vtour-vr.config "+ krEntity.getSourcePath() + File.separator + "*.jpg";Runtime runtime = Runtime.getRuntime();Process p = null;try {p = runtime.exec("cmd /c start " + krEntity.getKrpanoPath() + File.separator + ex);p.waitFor();} catch (Exception e) {e.printStackTrace();}finally{InputStream is1 =  p.getInputStream();new Thread() {public void run() {BufferedReader br1 = new BufferedReader(new InputStreamReader(is1));try {String line1 = null;while ((line1 = br1.readLine()) != null) {if (line1 != null) {System.out.println("=AA==========line1======"+ line1);}}is1.close();ExecuteMethod em = new ExecuteMethod();UnitedMethod um = new UnitedMethod();em.copyVtourFiles(krEntity.getSourcePath(),krEntity.getTargetPath());//递归删除临时文件夹um.delFile(krEntity.getSourcePath() + File.separator + KrpanoContants.VTOUR_NAME);try {um.updateVtourTitle(krEntity.getTargetPath(), krEntity.getTitle());um.updateVtourSceneTitle(krEntity.getTargetPath(), krEntity.getSceneTitle());um.updateVtourSkinAddr(krEntity.getTargetPath());um.addLoadingAnimation(krEntity.getTargetPath(), krEntity.getLoadingPath());um.addMusicElement(krEntity.getTargetPath(), krEntity.getMusicPath());um.addNadirLogo(krEntity.getTargetPath(), krEntity.getLogoPath());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (IOException e) {e.printStackTrace();}}}.start();p.destroy();}}/*** 需要拷贝3个文件,如:tour.js,tour.swf,tour.xml,还有panos文件夹下的所有文件内容* @param sourcePath* @param targetPath*/private void copyVtourFiles(String sourcePath,String targetPath){UnitedMethod um = new UnitedMethod();File targetFile = new File(targetPath);if(!targetFile.exists()) targetFile.mkdir();File sourceFile = new File(sourcePath);if(!sourceFile.exists()) return ;try {um.copyFile(sourcePath + File.separator + KrpanoContants.TOUR_XML_NAME, targetPath);um.copyFile(sourcePath + File.separator + KrpanoContants.TOUR_JS_NAME, targetPath);um.copyFile(sourcePath + File.separator + KrpanoContants.TOUR_SWF_NAME, targetPath);um.copyFolder(sourcePath + File.separator + KrpanoContants.PANOS_FOLDER_NANME, targetPath + File.separator + "panos");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

krpano常量类:

/*** */
package krpano;import java.io.File;/*** 存放krpano功能化的自定义常量* @author Administrator**/
public class KrpanoContants {public static final String VTOUR_NAME ="vtour";public static final String TOUR_XML_NAME =  VTOUR_NAME + File.separator + "tour.xml";public static final String TOUR_JS_NAME = VTOUR_NAME + File.separator + "tour.js";public static final String TOUR_SWF_NAME = VTOUR_NAME + File.separator + "tour.swf";public static final String PANOS_FOLDER_NANME =  VTOUR_NAME + File.separator + "panos";public static final String TOUR_NAME = "tour.xml";public static final String VTOURSKIN_NAME = "skin\\vtourskin.xml";public static final String LOGO_NAME = "logo";public static final String LOADING_NAME = "loading";
}

下面是具体的源码下载地址:

http://download.csdn.net/download/masti/10263263

krpano功能化实现相关推荐

  1. 基于java后端的 krpano 功能化

    ###**最近领导要求全景图的展示效果跟XX公司做的一样,仔细研究了一下XX公司的效果,发现用的是krpano,了解了krpano后,就要将krpano功能化,做成一个功能.很多全景公司采用krpan ...

  2. 东平谋定农业功能化-农业大健康·万祥军:品牌化精准扶贫

    东平谋定农业功能化-农业大健康·万祥军:品牌化精准扶贫 今日东平报讯 (通讯员梁久雪)新闻中国采编网 中国新闻采编网 谋定研究中国智库网 经信研究 国研智库 国情讲坛 哲商对话 万赢信采编:山东东平县 ...

  3. pb 应用 迁移 linux_功能化生物炭应用研究取得系列进展

    土壤营养元素流失.重金属污染是当前全球面临的突出环境问题.生物炭因其具有比表面积较大.吸附性能高和成本低等优点而在环境修复领域日益受到广泛关注,被作为水处理吸附剂.土壤修复改良剂广泛应用于农业土壤改良 ...

  4. 计算机多功能发展,随着电子计算机向微型化和多功能化发展,它的体积大大缩小,成本大大降低。性能明 - 问答库...

    问题: [单选] 随着电子计算机向微型化和多功能化发展,它的体积大大缩小,成本大大降低.性能明显提高.计算机技术日益紧密地与通信技术和传感技术结合起来,逐渐形成了不同规模的各种信息网络,这些信息网络, ...

  5. C语言中惰性,利用C-H键活化接力(CHAR)实现惰性C-H的功能化

    利用C-H键活化接力(CHAR)实现惰性C-H的功能化 由 X-MOL发布于 2016-09-07 C-H键的广泛存在使得C-H键活化研究成为近年来有机化学研究的热点.到目前为止,实现C-H的选择性活 ...

  6. 叠氮功能化硫铟铜量子点CuInS Qds-N3|炔基修饰碲化镉/硫化硒量子点 CdTe/CdSe Qds-Alkyne科研试剂

    叠氮功能化硫铟铜量子点CuInS Qds-N3|炔基修饰碲化镉/硫化硒量子点 CdTe/CdSe Qds-Alkyne科研试剂 CuInS2/CuInSe2的制备方法比较单一,大多采用热注入溶剂法.该 ...

  7. CY3/Cy5/cy7/FITC/PEG/DBCO/BSA/PEI标记修饰纳米金球和纳米金棒的功能化修饰(Gold Nanoparticles)

    纳米金球和纳米金棒的功能化修饰(Gold Nanoparticles) 金纳米棒是一种尺度从几纳米到上百纳米的棒状金纳米颗粒,具有非常丰富的化学物理性质.在材料科学界正受到强烈的关注,在生物医学上应用 ...

  8. 邻菲罗啉二酰胺功能化/吡啶基改性纤维状介孔二氧化硅微球的应用

    小编今天分享了邻菲罗啉二酰胺功能化/吡啶基改性纤维状介孔二氧化硅微球的分析与应用,一起来看看吧! 吡啶基改性纤维状介孔二氧化硅微球的分析: 合成了双键改性的纤维状介孔二氧化硅纳米微球(F-SiO_2- ...

  9. 聚乙烯基吡啶阳离子功能化聚苯乙烯微球/二氧化锆/聚苯乙烯阳离子微球研究步骤

    聚乙烯基吡啶阳离子功能化聚苯乙烯微球的研究步骤: 先通过季铵化反应将吡啶甲醛(PyAL)基团键合于交联聚苯乙烯微球(CPS)表面,制得改性微球PyAL-CPS,再通过Adler反应,成功地实现了吡啶基 ...

最新文章

  1. POJ 2186 Tarjan
  2. 渗透知识-CSRF攻击
  3. java 在线电影_java电影在线影评管理系统
  4. wxWidgets:WxBase 事件循环
  5. 苹果计算机咋出记录,怎么查看Mac电脑的开机记录?
  6. Ansible 详解2-Playbook使用
  7. 为容器提供持久存储,这个方法试试看
  8. 将Maven项目发布到Nexus私服
  9. 性能分析工作strace命令用法详解及使用例子
  10. Android M cm主题,M Dark Mode CM12.1 CM13 theme
  11. Flex中动态更新List item
  12. Ubuntu20安装gcc11
  13. java poi dataformat_poi的data format可真不怎么样
  14. 设计模式-模板方法(TemplateMethod)模式
  15. 自动驾驶之-MATLAB环境下基于深度学习的语义分割
  16. 12点转成0点(原因时间格式化为十二小时制导致)
  17. 利用IPHONE自带播放器播放视频
  18. 服务器添加账号失败是怎么回事啊,outlook添加新账户时失败,该怎么办
  19. SAP-FI 科目的统驭科目类型设置错了如何更改
  20. 美团机器学习实践 密码_机器学习遇到密码学的地方

热门文章

  1. Go的Negroni库
  2. 浏览器用什么电商插件好?
  3. 蓝桥杯2022年第十三届嵌入式详解
  4. html5游戏需求文档,游戏PRD丨狼人杀APP产品需求文档
  5. 软工网络15团队作业7——Alpha冲刺之事后诸葛亮
  6. Dropout和BN(层归一化)详解
  7. 31_ElasticSearch 修改IK分词器源码来基于mysql热更新词库
  8. java计算机毕业设计自动化办公系统源码+mysql数据库+系统+lw文档+部署
  9. 移动机器人轮式里程计
  10. vs2019配置完qt出现问题解决