pyqt使用.ui文件的两种方法

前言

Qt时是最常用的界面开发库之一,原生的Qt程序开发是使用的C++语言,而pyqt模块则让你可以用python语言来开发Qt程序。

在Qt开发环境中Qt Designer是非常方便的界面设计工具,通过Qt Designer设计的界面会保存为.ui文件。打开这些.ui文件可以看出,他们其实是记录界面信息和格式的xml文件,python是不能直接使用这类.ui文件,需要将.ui转化后才能使用。本文将介绍在通过pyqt模块使用这些.ui文件的两种方法。

方法一:将.ui文件转化为.py文件后使用

pyqt模块中提供将pyuic5.bat工具可以.ui文件转化为.py文件,在我的机器上目录为:’D:\WinPython\python-3.4.4\Scripts\pyuic5.bat’

在命令行中执行如下命令,即可生成指定的.py文件:

1
D:\WinPython\python-3.4.4\Scripts\pyuic5.bat -o UI_QtWindow.py QtWindow.py

打开转化后的.py文件可以看到,pyuic.bat工具自动生成了一个继承于“object”的界面类。在使用,通常新建一个界面继承于这个类和QtWidgets的基类的新类。如下我是创建的QMainWindow界面ui,所以继承于QMainWindow和生产的Ui_MainWindow类:

1
2
3
4
5
class testWindow(QMainWindow, Ui_MainWindow):
"""docstring for testWindow"""
def __init__(self):
super(testWindow, self).__init__()
self.setupUi(self)

在自动转换生成的类中提供了一个setupUi()函数,在这个函数中实现个各种初始化操作,创建界面上的各种窗体对象。setupUi函数需要在外部手动调用。

同理.qrc资源文件也许转化后才能使用,在我的机器上转化工具路径为:D:\WinPython\python-3.4.4\Lib\site-packages\PyQt5\pyrcc5.exe,转换方法和.ui文件类似。

方法二:通过uic模块动态加载.ui文件

在pyqt中有uic模块,它提供了loadUiType()函数可以直接加载.ui文件。使用如下:

1
2
from PyQt5 import uic
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatFile)

其中返回的Ui_MainWindow就是转换的界面类。和生成的类和方法一实际效果是一致的,只是不需要手动转化,也不会生成专门的界面的.py文件,直接使用Ui_MainWindow即可。使用时同样也需要手动调用setupUi函数。

注意点

  1. 在Qt Designer中以什么为原型的窗口,在代码中使用是也需要继承于这个基类,否则会出错。例如创建的ui是以QMainWindow为原型创建的,而在代码中却继承于QWidget,这样是不行的。

  2. 在使用方法二时,需要注意.ui文件使用的资源文件;如果在Qt Designer中应用了外部的资源,那么如果直接加载而不管资源文件时会出错

Compartir

用pyinstaller打包python脚本

前言

用python写的脚本做工具十分方便,但是却只能够再本机或者其他安装了相同python开发环境的机器上运行。所以一般需要外发的时候程序的时候都会将python项目打包成exe可执行的文件。

目前将python转化为exe文件的方法又两种:

  1. 用py2exe工具打包
  2. 用pyinstaller工具打包

py2exe打包的exe只能再相同的操作系统下运行,且打包文件页需要同exe下的dll和一些库的压缩包。而pyinstaller可以通过命令参数选择生成一个独立可执行的exe文件还是包含exe和dll的文件夹,pyinstaller支持多种python版本(包括2.x和3.x的版本),使用起来也相对的更加灵活,所以本文仅介绍pyinstaller的使用。

安装pyinstaller

  1. 方法一: 是用pip安装

    保证python的环境正确,且安装的pip工具后,在命令行中执行以下命令:

    1
    pip install pyinstaller
  2. 方法二: 下载源码安装

    在github上https://github.com/pyinstaller/pyinstaller下载源码,在命令行执行以下命令:

    1
    2
    3
    4
    cd bootloader
    python ./waf configure build install
    cd ..
    python setup.py install

pyinstaller的使用

在命令行中执行以下命令,可以将指定的文件转化为exe文件包。

1
pyinstaller Test.py

执行完上面的命令后,会自动生成两个文件夹和一个新文件:build/、dist/、Test.spec。 dist目录存放最终生成的程序,build目录存放exe的中间文件,.spec文件用来提供用户自定义生成参数。

在上面的命令行中加入-F的选项,则可以指定生成为一个单独可执行的exe文件。

1
pyinstaller -F Test.py

打包的文件可以用UPX去压缩,命令如下,但是前提是需要先安装好UPX。

1
pyinstaller -F Test.py --upx-dir upx391w

使用.spec文件定制转换

通过Analysis会输出五中类型:

  • pyz:python的模块
  • scripts:代码源文件
  • binaries:动态库
  • datas:数据文件可以是任意文件类型
  • zipfiles:zip格式的依赖文件,一般是egg格式的库文件

这五类为后面提供使用。

  1. 设置exe文件打包的文件

    设置exe字段,exe打包了python模块、源代码、动态库、数据文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    exe = EXE(pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    name='QtWindow',
    debug=False,
    strip=False,
    upx=True,
    console=True )
  2. 设置输出文件夹的包含的内容

    由于exe中已经打包了很多文件了,但是我并没有将界面ui文件一起打包,所以输出文件夹时把需要用到的界面文件包涵进去。

    1
    2
    3
    coll = COLLECT(exe,
    [('ui/testMainWindow.ui', './ui/testMainWindow.ui', 'DATA')],
    name='dist')

参考

  1. PyInstaller安装方法及简单的编译exe (python3)
  2. pyinstaller使用-python项目转换成exe可执行文件
  3. pyinstaller打包文件
Compartir

PyQt开发环境

前言

最近接手一个工作项目,需要用python开发,用Qt做界面,这对我来说很又意思,因为对于一直习惯于在IDE下用C++开发的我来说,从来没这么混搭干过。貌无疑问,C++才是Qt是原生开发语言,不过对于像Qt这样被广泛使用的图像库来说,肯定是提供了多种其他语言支持的库了的,在python中就是PyQt了。

实际上开发的过程并没有什么特殊的,但是环境的搭建却需要注意一下。原因是:

  1. 第一,python自身有两个版本的分支,并不是所有的库都支持这两个版本
  2. 第二,Qt虽然没有版本分支,但是目前老版本Qt4和新版本Qt5都使用的比较多,需要注意二者之间的差异
  3. 第三,python是解释型语言,开发的程序要到其他的机器上去执行,需要对其进行打包,将python脚本转化Windows通用的exe可执行程序。

下面我们就将对以上这几个问题进行说明。

环境的搭建

  1. Python版本

    python版本的不同决定了你使用PyQt库版本的不同,目前官方PyQt5只支持python3,而python2的版本只能乖乖的使用QtPy4的版本了,如果像在python2上使用PyQt5能够就只能找非官方的发布或者自己编译了,这个成本就有点大了。

    另外,python第三方库相互之间的依赖也是意见很烦人的事情,为了避免麻烦,我自己是安装的python的发布包。WinPython和Anaconda。

  2. PyQt使用

    上面说过不同版本的python对PyQt的支持情况。所以我目前的两个安装环境如下:

    • 公司:WinPython3 + PyQt5
    • 个人:Anaconda2 + PyQt4

    实际上以上这两个发布包中都有自带的PyQt库,已经不需要手动再安装了。而一个使用WinPython3,另一个使用Anaconda2的原因,仅仅是因为工作需要和个人习惯而已(一直以来我都是用的Anaconda发布的python2.7的版本)。

    另外需要说明的是在WinPython3中自带Qt Designer,可以方便ui的布局设计,但是Anaconda2中却没有,所以为了在我自己的电脑上使用Qt Designer,我不得不自己安装一个原装Qt,使用原装Qt提供的Qt Designer来设计.ui文件。

  3. python程序的打包

    Python程序的打包也是一个比较麻烦的东西,通常有两个打包工具:py2exe和pyinstall,这个我会放在后面单独说明。

Compartir

Untiy3D学习——第一个3D小游戏项目1

前言

Unity 3D的学习,相比系统的按部就班的学习,我更希望直接通过做一些小的项目来实现。这样效率更高,因为毕竟自己的空闲时间不多。所以这几天在网上看了一些其他人用Unity制作游戏流程的演示视屏,同时也为拟定了一个小游戏作为自己的第一个Unity项目。

第一个3D游戏的目标与计划

以下为我拟定的游戏目标:

  • 游戏类型: 3D赛车竞技游戏

  • 游戏评判标准: 完成一次比赛的最终得分

  • 记分规则:

    • 比赛用时: 时间越短,分数越高
    • 奖励: 赛道上的奖励物品,得到的越多分数越高
    • 陷阱与障碍: 赛道上的陷阱和障碍需要避开,触碰到的越多,分数越少

作为Unity初学者我的第一个游戏,很显然是无法指望一下就做得很完善好玩的。所以其他的一些细节我都先不考虑,做出一个最简单最基本都游戏原型来再说,然后再进一步完善方案。

考虑游戏需要的一些基本元素,用C#编写脚本,我将制作方案简化如下:

  1. 场景——马路

    整个场景的主体就是马路,且不考虑其他复杂类型,直接做成一条水平平行且笔直的马路。

  2. Player——小球

    赛车游戏的player主题本来是赛车的,但是其建模和动力系统的控制都太复杂,所以这里直接用简单的球体来代替。

  3. 键盘输入来控制运动

    将小球加入物体系统,外物受力为重力和摩擦力。小球的运动直接简化为前后左右四个方向的受力,通过键盘来控制。

  4. 计时器

    赛车类的游戏最重要的就是比赛的用时,所以需要计时器来记录

  5. 起点和重点的感应

    为了精确计时,应当设置起点和终点的感应,来配合定时器一起计时

  6. 菜单

    一个完整的游戏的必备,负责设置游戏的一些参数,在这里就可以简化到只有游戏的暂定和继续以及游戏的退出。

创建场景和Player

用Unity内置的3D对象Plane或者Quad来做马路,用球体模型Sphere来充当Player,在透视视图中将两个调整到合适的位置。如下图为我摆放的马路、小球和主摄像机的位置:

场景中各元素的位置

直接将贴图推到马路上,Unity会自动创建其材质,就如上图所示。

而对于小球,为了达到方案中受力的作用,我们需要将其加入物理系统。添加小球的
Rigbody(刚体)组件:Add Component –> Physics –> Rigidbody ,在其中勾选“Use Gravity”,使其受重力的影响。

实际上在Rigbody中还可以设置如下选项(选择常用的说明):

  • Mass : 物体的质量
  • Drag: 空气阻力
  • Angular Drag: 转动空气阻力
  • Is Kinematic: 选中则物体不受物体系统的控制

脚本的运行框架

在Unity中一般会在物体对象上创建Script组件来控制对象的行为和游戏的运行流程,其中每个脚本都有共同的内置方法,其中一些重要的方法的执行顺序为:

Awake() --> Start() --> FixedUpdate() --> Update() --> LateUpdate() --> OnGUI() --> Destroy()


  1. Awake

    Awake方法是在脚本对象建立起来之后最先调用

  2. Start

    Start方法是在第一帧Updata前调用

  3. FixedUpdate、Update、LateUpdate

    这三个方法是在当MonoBehaviour启用时不断被调用的,update跟当前平台的帧数有关,而FixedUpdate是真实时间,所以处理物理逻辑的时候要把代码放在FixedUpdate而不是Update,LateUpdate是在所有Update函数调用后被调用。

    Update是在每次渲染新的一帧的时候才会调用,也就是说,这个函数的更新频率和设备的性能有关以及被渲染的物体(可以认为是三角形的数量)。在性能好的机器上可能fps 30,差的可能小些。这会导致同一个游戏在不同的机器上效果不一致,有的快有的慢。因为Update的执行间隔不一样了。

    而FixedUpdate,是在固定的时间间隔执行,不受游戏帧率的影响。所以处理Rigidbody的时候最好用FixedUpdate。FixedUpdate的时间间隔可以在项目设置中更改,Edit->ProjectSetting->time 找到Fixedtimestep,就可以修改了。

  4. OnGUI

    渲染和处理GUI事件时调用,UI相关的操作需要在这里面实现。

  5. Destroy

    Destroy方法在对象销毁时调用。

输入系统和运动控制

如方案所叙,小球的动力来源为,在水平面上前后左右四个方向上的外力,四个方向上的外力的有无和作用时间由键盘来控制。

在小球上添加脚本组件,通过代码检测键盘输入,从而控制外力的作用。Unity中由Input类来操作外部的输入,用w、s、a、d四个键分别控制四个方向,检测C#代码如下:

1
2
3
4
bool hasUpKey = Input.GetKey(KeyCode.W);
bool hasDownKey = Input.GetKey (KeyCode.S);
bool hasLeftKey = Input.GetKey (KeyCode.A);
bool hasRightKey = Input.GetKey (KeyCode.D);

要产生力的作用,需要用刚体组件中的AddForce方法,获取组件的方法需要用到ameObject.GetComponent方法,如在x轴正方向上添加一个值为2的力的代码如下:

1
gameObject.GetComponent<Rigidbody> ().AddForce (2, 0, 0);

以上这些逻辑代码在FixedUpdate方法中实现。

计时器和触发器

Unity中提供Time类实现时间的操作,为了实现计时器的功能,只需要计算起始时间和当前时间的时间差即可,同样在FixedUpdate函数里面实现:

1
spendTime = Time.time - startTime;

起点和终点的触发器,可以用碰撞触发来实现。在马路的起点和终点处分别放置碰撞物体,并在其在Box Collider组件中勾选Is Tigger,下图所示的为起点触发设置:

起点触发

在小球的脚本中添加OnTriggerEnter函数,当小球碰撞到了起点线就会触发这个函数,并通过参数来区分碰撞的物体,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
void OnTriggerEnter(Collider other)
{
if (other.name == "startLine")
{
raceStart = true;
startTime = Time.time;
}
else if (other.name == "endLine")
{
raceFinish = true;
}
}

定时时间显示可以在OnGUI方法中通过GUI.Label函数来实现,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
GUI.color = new Color(0xff, 0xff, 0);
GUI.skin.label.fontSize = 15;

if (raceStart)
{
timeStr = "Timer: " + spendTime.ToString ("f2") + "s";
}
else
{
timeStr = "Timer: 0s";
}

GUI.Label(new Rect(Screen.width-150, 20, Screen.width, Screen.height), timeStr);

菜单创建

制作菜单有如下步骤:

  1. 创建文字UI

    通过创建UI –> Text来实现,在Text组件中设置文字的各种属性:如显示文字、字体、大小、颜色等等文字格式,另外还可以添加阴影等文字特效组件,如下图所示:

    UI Text的组件设置

    在这个本次制作中我制作了两个菜单项:一个为主菜单,一个为子菜单。主菜单一直三个功能:游戏的暂停、继续和推出,子菜单为推出确认菜单。将菜单拖放到合适的位置,如下图所示:

    Unity菜单制作

  2. 添加Button组件

    在菜单中有些是提示的文字,有些是提供交互的按钮选项。对于那些需要有按钮功能的文字,要在其各自对象下添加Button组件:Add Commponent –> UI –> Button,如下图所示:

    Unity菜单文字添加按钮功能

    在Button组件中设置各种配置如颜色,当然最重要的是添加其点击处理函数。

  3. 添加按钮点击消息处理函数以及功能的实现

    在脚本中编写各个按钮点击处理函数,并在各自的按钮组件中正确的指定。在相关按钮处理函数中实现各自的功能:

    1. 暂停/继续

      同通过Time.timeScale可以控制游戏的运行快慢,将Time.timeScale 设置为0表示暂停播放,Time.timeScale设置为1为正常运行。

      同时需要在逻辑计算的代码部分,加入暂停的判断。因为Time.timeScale只能显示的画面停下来,而输入、计算等仍需要手动的控制停止。

    2. 隐藏子菜单

      UI Text需要用Canves对象来承载,所以Canves对象是UI Text对象的父级对象,将主菜单和子菜单的分别放在不同的Canves对象中,通过控制子菜单的Canves对象来设置隐藏,代码如下:

      1
      2
      quitMenu = quitMenu.GetComponent<Canvas> ();
      quitMenu.enabled = false;

摄像机的跟随

在游戏运行时,游戏的画面都是从摄像机的拍到的,所以为保证在小球,游戏画面还能够看到比较清晰的看到小球视角,就需要将摄像机跟这小球一起移动。这里包括两方面的内容:一是位置的跟随,一是视角的跟随。

  1. 位置的跟随

    位置的跟随可以先获取小球的位置,然后在设置摄像机的位置,在摄像机脚本的Update方法中,在这里我实现的是摄像机的水平高度不变,其他两个轴的位置与小球保持固定,如下代码:

    1
    transform.position = new Vector3(playerObj.transform.position.x + 4, transform.position.y, playerObj.transform.position.z);
  2. 视角跟随

    视角跟随有非常简单的方法,可以将摄像机的视角中心对准小球:

    1
    transform.LookAt (playerObj.transform);
Compartir

Unity3D学习——基本操作介绍

前言

考虑到学习成本,之前一直在犹豫Unity 3D是否有学习的必要,因为对于这样一款专长3D游戏引擎的开发工具,并不在我的专长范围内。不过由于最近接触到VR/AR领域,需要学习一些3D的工具,而新版Unity 3D 对目前市面上一些主流的VR/AR软件开发较好的支持,也让其获得越来越多的VR/AR开发者的使用,同时Unity良好的跨平台特性,让我下定了学习的决心。

软件介绍

  1. 下载与安装

    Unity软件官方地址:https://store.unity.com/cn。在这个地址上下载的不是完整的安装包,而是仍然需要联网下载的安装程序,所下载的功能模块是依据用户自己选择而定的。

    安装Unity的时,我不得不吐槽一下,Unity官方提供的免费的personal版本,建议不要使用,直接破解吧。由于personal版本对使用者的条件有比较严格的限制,如果信息填写的条件不符合,软件的license是死活也激活不了。也不知道是我智商堪忧,还是软件开发者太傻逼,我在尝试使用personal版本时,它就硬生生的卡在severy界面,不管怎么选择填写信息都没用,就连个提示都不给,一副免费版爱用不用的架势,简直是浪费使用者的时间。

  2. 软件界面

    尽管Unity 是作为一款3D游戏引擎而为人所知的,但是实际上它已经是一款十分完整的开发环境了。如下图所示为Unity的UI界面,和其他3D软件十分相似,其主要面板的作用在图中又做说明:

    Unity界面示意图

  3. 使用的脚本

    Unity主要使用的脚本语言是C#或javascript,小工程比较适合选用
    javasript,但是实际项目或比较大的工程就建议使用C#,因为很多插件都是C#写的。

基本操作

  1. 视图场景和物体对象的操作

    和其他3D软件类似,位置、旋转角度和大小缩放,是3D场景和其中的物体对象最基本的属性。在Unity界面上面有提供一组按钮来实现相关操作,具体如下图所示(相关按钮在红色方框内,中间三个为面向物体,两边针对场景):

    控制器切换

    对场景的操作是可以全部通过鼠标来实现:

    • 左键拖放、中键拖放:视角的位置移动
    • 右键拖放:视角的角度
    • 滚轮滚动:视角远近

    对于场景中的物体,在Unity中位置、角度、大小被统一在Tranform组件中。对这些属性的基本操作步骤是:选中物体,在3D视图中,可以通过快捷键或工具栏选项来切换控制方法,然后鼠标操作完成。

    另外也可以通过快捷键,来快速切换方法如下:

    • w:切换为位置控制
    • e:切换为旋转角度控制
    • r:切换为物体大小控制
    • q:取消物体对象的控制
  2. 添加3D物体对象

    有多种方法向场景中添加物体,最简单的就是:在Hierarchy面板中鼠标右键 –> 3D Object, 在其中选择自己需要添加的物体对象。

    添加Object

    在Unity中内置了最基本的物体对象模版:

    • Cube: 立方体
    • Sphere: 球体
    • Capsule:胶囊体
    • Cylinder:圆柱体
    • Plane: 平面
    • Terrain: 地形编辑体
  3. 添加组件

    在Unity中对象所拥有的属性,都是通过添加组件和修改组件的参数来实现。常见的组建有:

    • Transform: 包括位置、旋转角度和物体大小
    • Mesh: 指定物体网格形状
    • Collider: 指定物体碰撞体属性,属于物理系统模块
    • Renderer: 指定物体的渲染
    • Rigidbody: 指定物体刚体属性,属于物理系统模块,里面有一系列物理特性如:重力、摩擦力等

    添加组建的操作非常简单,先选中要修改的物体对象,让后选择“Add Component”,如下图所示:

    添加组件

  4. 其他操作

    1. 创建脚本: 在Project面板中右键 –> Create 选择C#或Javascript
    2. 将脚本绑定对象: 直接将脚本拖放到视图中的对象上
Compartir

你所不知道的Minecraft——Minecraft科普知识整理

前言

作为游戏玩家,在Minecraft(简称MC)的世界里我简直是菜鸟中的菜鸟,但是MC超高的自由度还是让我沉迷其中。而MC的魅力不仅仅在于游戏本身,对我来说游戏之外的MC也同样精彩。我敬佩于原开发者Notch(Markus Alexej Persson,中文:马库斯·阿列克谢·泊松)是怎样的脑洞在工作之余够构思出这么一款神奇的游戏,惊讶于在这个动不动就是4k级画质游戏的今天它仅仅靠着一堆粗糙的像素块就赢得如此多玩家的心,更加感慨无数的mod开发者的共同努力造就了今天Minecraft的辉煌。因此我怀着浓厚的兴趣和崇高的敬意在网上查找着MC的资料,整理成这篇科普性的文章,所以实际上本文的标题也许应该修改为《我所不知道的Minecraft——Minecraft科普知识整理》。

Minecraft

Minecraft的前生今世

Minecraft,中文名:我的世界,是由Mojang AB(创始人Notch)开发的高自由度的沙盒游戏,2009年发布,仅仅过了5年的时间,Minecraft就成为史上最畅销的PC游戏。

Minecraft的开发始于2009年5月10日,《矮人要塞》、《模拟乐园》、《地城守护者》和《Infiniminer》等几款游戏的启发,Notch创作了Minecraft。当时Notch为了专注于独立开发最,开始还维持在Jablum网站的全职工作,后来就该做兼职了,随后他索性就辞去了工作,并建立了Mojang AB公司全力开发Minecraft。

Notch

2011年8月16日,使适用于索尼Xperia Play的便携版本发布,随后适用于所有Android版本也于10月7号发布,iOS版本则于11月17号发布。

2011年11月18,Minecraft的官方正式版发布。

2012年5月5日Minecraft登陆Xbox,短短数小时内就回收了开发成本开始盈利。

2013年2月11日,树莓派版发布,其为树莓派独占,其基于携带版本开发,开放源代码。树莓派版本意在故意编程者学习编程,使用其API修改游戏代码。

2014年9月15日,微软以25亿美元收购Mojang工作室,收购后Mojang,Notch本人、公司CEO Carl Manneh和联合创始人Jakob Porser将会离开公司,至此游戏史上一段传奇的经历终于告一段落,Minecraft终归微软的门下。

Minecraft迷人的原因

作为一个没有接触Minecraft的人,看到其他人如此痴迷于一个粗糙画质的游戏里时候,总是会非常好奇,到底是怎样的魅力让Minecraft能够吸引如此多的玩家?在我个人主要原因有如下几点:

  1. 自由、可交互

    自由是Minecraft最大的特点,在Minecraft那近乎无限大的地图空间里,你可以做任何事情,你也可以任何事情也你不做。正如其中文名“我的世界”那样,在游戏里你会觉得整个世界就是你的。

    另外可交互也是Minecraft拥有极高的可玩性的原因。由于Minecraft是方块组成的世界,而这些方块被赋予了各种各样的属性,因此Mincraft中所有物体都是“实实在在”的物体,而不是和其他游戏那样仅仅是一张视觉上的贴图。所以在Minecraft里你可以砍树、可以挖矿、可以种田,你可以破坏任意看起来像边界样的东西(当然基岩除外~~),你也可以用方块创造任何一样东西。

    玩家在MC中的设计
    玩家在MC中设计的建筑

  2. 红石系统

    直到现在,我都觉得红石系统真Minecraft中天才的设定,它的出现使得在游戏中实现自动化成为了可能。玩家们因此也乐此不疲地充分发挥自己的想象力,各种自动农场、自动刷怪楼、自动养鸡场、红石音乐、红石武器层出不穷。不过我想即使是Notch和Mojang AB也可能会难以想到,竟然有玩家借助红石系统实现各种电路器件,更有甚者直接在游戏中直接做出了一台计算机!真是脑洞有多大,世界就有多大!我也许永远也料不到那些高端玩家们,下一刻会用Minecraft玩出什么新花样出来。

    红石实现电路的逻辑门

  3. 分享与创作

    尽管Minecraft是自身就是一款非常优秀的游戏了,但是Minecraft能在短时间里流行的原因很太程度上在于玩家们互动和分享,而在游戏制作之初官方几乎是没做什么宣传和推广。创建服务器后,Minecraft就是一个MMORPG,能够让更多的人一起在游戏的世界里探险、竞技或是创作,同时不少玩家将他们玩游戏的经历录制成视屏发到视屏网上分享给更多的人。

    而在此之上插件和MOD的出现,又让Minecraft的可玩性又上升一个等级。插件和MOD都是利用开发者们从Minecraft中提取出来的API,对原始游戏进行修改的二次开发的程序包。因此在Minecraft里,你可以不仅仅是一个玩家,还可以是个开发者。由于MojangAB对MOD开发者们的友好的态度,所以基于Minecraft官方版本的各种第三方MOD就不断涌现出来,而这些MOD是集合了全世界玩家的脑洞与智慧的。于是大家都调侃道,换一个MOD,或者仅仅是换一个材质包,你会发现你们玩的根本不是同一个游戏。

    GTA5风格的MOD
    射击类MOD

  4. 商业模式

    商业模式上的成功,我是不怎么懂得,但是仍然是得益于Minecraft极强的可塑性,让不少Minecraft各种大型服务器的兴起,由于通过插件或Mod,这些服务器的管理员能够有足够的权限自己Minecraft服务器中定制自己的游戏玩法和游戏规则以及付费特权等级,而Minecraft超高的人气也让这群人,能够从普通玩家哪里收获不少的回报。

    但是也正是由于某些服务器的收费太过火,导致Mojang不得不出台EULA规定来强制限制,不过这也导致了后面Minecraft服务器的衰退。

你所不知道的Minecraft

  1. Minecraft地图多大

    虽然Minecraft的地图足够大,但是还是有边界的,以1.8以后的版本为例,在MC中文Wiki中有说明:

    “在1.8及以后的版本,分布在X/Z 29,999,999以外的假区块将不被渲染,就像在万圣节更新之前的版本中 X/Z 31,999,999 以外的区块不会被渲染。同样的,用于防止玩家进入更远的地方的隐形墙也会被移动并改为新的 世界边界,允许玩家利用”/worldborder center”命令进入X/Z 30,000,000 以外的区域并移动边界。 然而,如果玩家试图越过这道界限,无论是单人游戏还是多人游戏,玩家都会“掉线”,并发送信息显示玩家进入了“非法区域”,当玩家重新进入游戏是,他们会出现在他们越过世界界限之前的位置。值得注意的是,如果玩家利用传送的方式越过边界,那么他会永远的停留在“非法区域”并再也不能玩那个存档。 使用地图编辑器或者“NBT editor”修改玩家所处位置可以弥补这个错误。”

    有玩家按照之前正负32,000,000为边界,每个方块1m来换算参考视屏,那Minecraft的世界足足有8个地球表面那么大,当然这些知识理论的计算。

  2. Minecraft为什么需要启动器

    Minecraft需要启动器的原因只是因为它是Java编写的,而java程序依赖于JVM虚拟机,但是JVM需要传入相应参数才能让java程序正常运行,所以启动器最核心的功能就是完整这个传参的作用。

    对于Minecraft来说,在版本一次次更新后,启动器要完成的任务也越来越多,主要有如下几点:

    1. 设置JVM的运行java程序的环境,如设置JVM内存、垃圾回收机制
    2. 加载各种需要的类库
    3. 管理资源文件
    4. 正版登陆以及验证
    5. 版本管理,让多个MC版本共存并自由切换使用
    6. 依赖管理
  3. Minecraft中MOD和插件的区别

    插件只面向服务器,只能一定程度上修改服务器端的逻辑,往往依赖于一个成熟的API(如Bukkit),不同版本的差异非常小。

    MOD则是基于对Minecraft相对较深的定制,大部分模组客户端和服务器都需要,由于涉及到了比较核心的代码,所以版本之间差异较大一般不兼容,现在MOD使用的API大多是使用forge的。

    由于插件和MOD分布式基于不同的API系统,所以在没有整合前是不能通用的。

  4. 不是开源的Minecraft为什么可以二次开发

    确实Minecraft代码没有开放,但是可以通过反编译得到源码。不过反编译的代码实在太难用了,虽然通过了编译的代码在清晰上肯定还是比不少原始代码,不过这口锅主要还是得由Mojang来背,由于Notch最开始的只是自己玩玩,到了Mojang时也只是以小规模的产品去设计,导致后面可扩展性就是一个坑。

    但是在2010底,一个叫hey0的大神发布了hMod在之前比较混乱的源码之上整理出一套还能够给开发者使用使用的代码,可惜原作者更新了一段时间后就离开了。接下来的任务交给了Dinnerbone,不过Dinnerbone后面决定推倒重来,于是就有了Bukkit计划。对于开发者的我来说,这段历史对我确实很有吸引力,所以这里的信息会收集的详细一点。

    Bukkit计划世界实际分两个部分:Bukkit API 和 CraftBukkit。Bukkit API是抽象接口,CraftBukkit为具体实现,下图为知乎作者 Tiger Tang的原图:

    Bukkit项目

    使用Bukkit API开发的小程序一般就同成为插件(plugin),由于后面各种原因Bukkit的原开发团队核心成员的离去,其开发速率越来越慢,所以许多人私下制作CraftBukkit的优化版本,这其中最有名的是md_5的Spigot,而为了解决多服务器同步和通信问题,md_5和他的团队有共同开发了Bungeecord。

    在另一方面,客户端上,另一群开发者们对Minecraft进行了反混淆,做出了可读的源码包Minecraft Coder Pack(简称MCP),开发者们可以通过MCP来制作MOD。后面为了统一不同开发者对MCP的修改,就出现了各种MOD API,如Forge。

    在一段时间捏,由于Bukkit或Spigot和以MCP为基础的API是不兼容,为了解决这个问题,md_5大神又制作了整合Forge+Spigot+CraftBufkkit的服务端整合包MCPC-Plus,让玩家们同时享受插件和MOD的乐趣。

参考资源

  1. MC中文Wiki:http://minecraft-zh.gamepedia.com
  2. 百度百科、360百科
  3. 知乎 “Minecraft 的多人游戏是如何发展起来的?”: https://www.zhihu.com/question/28323894/answer/40396131
  4. 知乎 “《 Minecraft 》为什么要以启动器的形式启动?”:https://www.zhihu.com/question/49997128
  5. 视屏:http://www.bilibili.com/video/av2715272
Compartir

VR-AR——一些基本信息整理和个人理解

前言

不知从何时起VR、AR以及MR这些曾经只能在电影或科普书上才能找到的概念开始出现在大众人们的视线里,让人不禁感慨科技发展之迅速。从比较早期的Google Glass,到Cardboard、GrearVR,再到Oculus Rift、HTC Vive,我看到的是一些伟大的科技公司在VR、AR领域的不断的尝试与创新,一步一步努力将那些实验中的玩具带到普通消费者面前。受益于那些先驱者的努力,如今的VR、AR已经从当初的书本概念的变成的了实际的产业。

虚拟科技

前一段时间火遍全球的手机AR游戏pokemon go,如下图所示,虽然中国大陆玩不了,不过我也由此开始关注起了这个看起来充满科技感和未来感的领域。

AR游戏Pokemon Go

从我了解到的情况来看,目前由于国产手机盒子类的产品已经烂大街,但是实际体验比最简易的Cardboard提高却不大,而另一方面体验好的的HTC Vive和Oculus Rift价格巨贵,而且还需要高性能的PC机的支持。这让失去了刚开始时的新鲜感和神秘感的VR和AR产业的发展似乎走到了一个拐点,但是不可否认的是当前的VR和AR还仅仅处于初级阶段,不管是硬件上还是算法上还是内容应用上,它还有十分广阔的空间等待挖掘。

概念说明

对这些新概念的描叙网上也没有一个同一固定的说法,但是大致表达的意思是一致的。我这里综合一些资料来说明:

VR(虚拟现实): 即Virtual Reality。VR技术就是借助计算机技术以及其他硬件传感设备,模拟产生一个三维空间的虚拟世界,提供对使用者对视觉、听觉、触觉等感官模拟。

AR(增强现实):即Augmented Reality,AR技术就是通过电脑技术,将虚拟的信息应用到真实世界中,真实的环境和虚拟实时的叠加到同一个画面或空间同时存在。

随着微软推出Hololens,MR的感念也出现了。

MR(混合现实):即Mixed Reality,MR是混合VR和AR的结合,指合并现实和虚拟世界而产生的新的可视化环境,虚拟的物体能够对现实的环境进行识别和交互。就目前MR产品来看,它和AR比较接近,从概念上来讲MR和AR最大的区别就是与虚拟和现实的交互,即比较深层次的融合。

当前VR/AR设备分类和简介

从当前VR/AR的设备来看,主要可分为三类:

  1. 移动端设备

    移动端的VR设备,由智能手机加上带有透凸镜夹手机的盒子组成,以Google Cardboard和三星GearVR为代表。而移动端AR则比较简单,直接用智能手机就可以实现。下图为Google Cardboard的展示图。

    • 优点: 组装简单、成本低廉
    • 缺点: 体验差

    目前国内此类VR厂商众多,主要有暴风墨镜、焰火工坊等。

    Google Cardboard

  2. 主机类设备

    主机类主要是VR设备,主要由头戴显示设备、PC主机(或游戏主机)、以及其他传感设备组成。它能够借助PC主机强大的计算能力和图像处理能力实现更加逼真的虚拟环境。代表产品主要是 Oculus Rift和HTC ViVe,下图为HTC Vive的展示图。

    • 优点: 体验好、虚拟环境逼真
    • 缺点: 价格昂贵、携带不便、操纵较繁琐

    目前国内正在研发的VR厂商有乐相科技、蚁视科技、3Glasses等。

    HTC Vive

  3. 一体式设备

    一体式设备是指需要其他设备来支持或组装,而自己就是一台独立VR或AR设备,典型的有Google Glass和微软的Hololens。由于好的VR设备需要强大的计算能力,而目前的一体式设备计算能力还不能达到主机的性能,所以当前市面上的一体式设备都为AR或者MR。下图为Hololens的展示图。

    • 优点: 便携性好、体验好
    • 缺点: 性能较弱,导致不能处理太复杂的场景

    Macrosoft Hololens

技术简介

以下会从当前比较典型的VR/AR设备上,简单的了解它们实现VR/AR的关键技术或手段。另外由于一体式设备目前真正的消费产品还极少,微软的Hololens最近发给用户的也只是开发者版本,所以资料比较少,这里就不介绍了。

  1. 移动端VR技术

    移动端VR技术主要是Google Cardboard和三星GearVR。我们反复的提及Google Cardboard,是因为它确实对VR整个产业的推广都起了非常的大的作用。它的作用是两方面:一是它向其他同行示范了即使用最简单的原料、最低廉的成本也科技做成一套成型的VR设备;二是Cardboard SDK为其他开发者针对这个简单的设备提供了完整的开发坏境。而这些最低廉的设备和简单的方案对将VR推向普通消费者的有很大的促进作用。

    而相比Google Cardboard三星GearVR在硬件设备上更加高端,它使用的Oculus公司的方案,也比CardBoard方案有更低的延迟、更好丰富的体感控制,所以也有更好的体验,而后Google推出的DayDream规范也是借助了GearVR的很多研究成果的。

    移动端VR发展的基础就是智能手机,由于搭载了多种传感器,这就使得VR所需要的地址、方位、运动等信息都能够通过智能手机来收集。因为虚拟现实视觉体验是最重要的一部分,所以以下主要从视觉角度介绍VR方案中使用技术。

    1. 双画面显示加凸透镜

      • 为了解决当屏幕靠的与眼睛足够近时,眼睛无法聚焦
      • 为了让人产生深度的感觉

      当前的VR方案基本上都是一个虚拟的图像,用算法分成两个图像分布给人的左右眼来看,同时两个图像的画面是有些小区别的,这样来达到身临其境的效果。

      双画面显示

    2. 变换画面

      由于凸透镜对画面有变形,边沿还会有色散,所以使用凸透镜的方案大多都会对显示的图像进行反变形,对边沿进行反色彩。

      变换后的双画面显示

    3. 固定盒子

      盒子的作用是:

      • 固定手机、凸镜和人体头部
      • 遮住不必要的光线干扰

    目前移动端VR的存在的问题有:

    • 无法精确定位:手机上民用级别的GPS精度只有2-3m
    • 无法精确测量高度:现在手机大多用的气压测量高度误差太大
    • 无法捕捉除头以外的动作
    • 分辨率太低
  2. 主机类VR技术

    主机类的VR,它的头戴显示设备与移动端VR解决方案比较类似,目前几乎都是双画面显示,它最大的优势就是能够借助PC机或者游戏主机强大的计算和图像处理能力。相对移动端VR它解决了如下问题:

    • 高分辨率屏幕显示:Oculus Rift采用了两块1200x1080的OLED屏幕
    • 低延迟画面流程:Oculus Rift为90Hz的刷新率
    • 局部空间的精确空间定位
    • 身体的动作捕捉

    从上面可以看到,主机类的VR技术主要是 视觉人机交互这两方面带来的用户体验的提升。由于显示的方法与移动VR技术类似,所以以下讲解主要集中在人机交互上,而人机交互体验的提升主要依靠是空间的精确定位和动作的捕捉,因此下面的内容也主要集中在这两方面。

    1. Ocuclus Rift

      Oculus Rift的定位是依靠两个部件:

      • 头带设备上的多个红外发射器
      • 两个摆在对角的100Hz的高速摄像机

      用高速摄像机拍摄的图像只需要红外光线,滤除其他可见光,根据检测到头盔上发出红外的位置来实现空间定位和头部运动。

    2. HTC Vive

      HTC Vive采用的是Lighthouse激光定位技术,同样和Rift一样同样是信号收发设备分离设计。在头戴设备上为多个激光接收器(70多个),在两边放的不是摄像机二是激光发射机。根据不同位置接收器接收发射信号的时间长短,来计算定位空间位置和运动。相比Rift它的延迟小、计算量低,定位更加精准、适用性更强。

      下图为HTC Vive的定位示意图:

      HTC Vive的定位系统

参考资料

以上内容主要为我最近在网上查找信息的整理以及个人理解的笔记,主要参考有:

  1. 《中国VR行业研究报告:现状、机会、发展趋势——中投研究院》
  2. 视屏《真实的梦境——VR 虚拟现实产品巡礼》
  3. 知乎多个VR/AR相关回答
Compartir

图像与视频处理——图像修复简介

图像修复原理和大致流程

如下图所示,为从原始图像到被破坏再到被修复的整个流程的模型框图:

图1 Image Restoration

上图,原始图像f(x,y),经过退化函数H,然后又叠加入了噪声成为被破坏后的图像g(x,y),图像修复的目的找出对应的处理滤波器,尽量的还原原始图像f(x,y)。

原始图像退化的原因可能有:拍摄时没有对焦,运动产生的模糊。噪声加入的原因也能够使多方面的,有可能是拍摄设备本身的电磁噪声。因此从f(x,y)到g(x,y)可以写成如下表达式:

g(x, y) = f(x,y) * h(x, y) + n(x, y)


注意:1. f(x,y)与H(x,y)是卷积的操作 2. 噪声大多数都是加性噪声,如果有少量的乘性噪声,其处理方法也可以将其转换为家性噪声,然后以加性噪声的方法来处理

由于我知道了图像破坏的模型后,图像的修复就是其逆过程,我们如果可以知道了H(x,y)和n(x,y),就可以反推得到原始图像f(x,y)。

噪声模型

为了方便研究H(x,y)和n(x,y),研究者们总结出了一些常用的噪声模型,这些噪声模型既包含了理论的模型也含有实际出现的噪声,可以方便大家套用和简化计算。我这里只是简单介绍其特性,其函数表达式以及详细分析可以参考其他专业资料。

以下为6种常用的噪声模型的函数曲线图。

图2 常用的噪声模型

  1. 高斯噪声(Gaussian)

    如上图所示第一条曲线为高斯噪声。高斯噪声是一种理想的模型,服从正太分布,在实际情况中不会出现,但是高斯噪声使用确实非常广泛的,其原因之一是数学上很好计算,其次它是其他噪声很好的近似。

  2. 瑞利噪声(Rayleigh)

    上图中第二条曲线为瑞利噪声,是在实际中存在的噪声,比如磁共振。

  3. 伽马噪声

    上图第三条曲线为伽马噪声。

  4. 指数噪声

    上图第四条曲线为指数噪声,起一个重要的特征是没有负噪声。当图像做预测编码是导致的误差是指数噪声。

  5. 均匀噪声

    上图第五条曲线为均匀噪声,当图像做量化时导致的量化噪声就是均匀噪声。

  6. 脉冲噪声

    上图中的最后一条曲线为脉冲噪声,椒盐噪声就是属于脉冲噪声的类型。

这里有网友总结的各个噪声模型的表达式和Matlab代码可供参考:http://www.myexception.cn/image/1709093.html

图像噪声类型的评估

图像加入噪声后的图像的直方图分布会受到噪声的影响,直方图的分布会变得和其加入的噪声的分布类似,因此我们可以通过检测图像的直方图来评估噪声类型。

实际操作时,我们为了让直方图更明显,先取图像中颜色变化较小的一小块区域来做直方图,这样一来,直方图的形状就主要受其噪声类型的影响。但是如果整个图像噪声分布不是均匀的,那就可能要在不同位置多取几个区域检测了。

图3 图像噪声类型的评估

如上图,最坐标的原始图像,取蓝色框中的区域得到其直方图,因此可以很直接的看出:最左边的直方图是高斯噪声,中间是瑞利噪声,最右边的是均匀噪声。

另外,如果直方图从肉眼不能直观的区分噪声类型,那么可以通过一一猜测的办法,通过用标准的工具做函数拟合,看看那种类型拟合出来的误差小。

噪声的处理

从前面图像破坏的模型表达式可以看到,一般的噪声都是加性的噪声,而通过前面的噪声评估我们可以得到噪声的类型,图像修复是要去除噪声,就可以做逆向操作:

g(x, y) - n(x, y)


退化函数的评估

通常退化函数也被称为模糊函数,前面提过主要是两种情况:拍摄时没有对焦,运动产生的模糊。

评估退化函数比较困难,有时候会需要一些实验和尝试。一般拍摄失焦的情况与高斯模糊比较类似,可以用高斯模糊来模拟。运动运动模糊,则可以理解为运动图像在时间上的积分。

退化函数的处理

退化函数对原始图像是卷积的作用,图像修复为了去除退化函数的影响,通常的操作是利用傅里叶变换。

假定噪声已经去除,则原始图像被破坏的表达式为:

g(x, y) = f(x, y) * h(x, y)


对上式做傅里叶变换(注意下式的x是乘号):

G(u, v) = F(u, v) x H(u, v)


这样操作后表达式就从卷积运算变成了乘法操作,得到:

F(u, v) = G(u, v) / H(u, v)


最后再做傅里叶逆运算。

Compartir

用Python+OpenCV进行图像梯度操作

图像的梯度

对于梯度,首先要了解的是他是一个向量,所以它是既有 方向又有 大小的物理量。

对于二维图像的梯度,它的物理意义是:图像上各个pixel点灰度变化大小的衡量。图像梯度的最重要性质是,梯度的方向在图像灰度最大变化率上,它恰好可以反映出图像边缘上的灰度变化。

由于现在的数码图像都是离散数字量,所以图像的梯度可以通过对其两个方向上分别求导来获得,一般最简单的计算方法可以如下(当然还有其他更复杂的求法):

G(x,y) = dx i + dy j; 
dx(i,j) = I(i+1,j) - I(i,j); 
dy(i,j) = I(i,j+1) - I(i,j); 


Sobel算子

sobel算子中文名为索贝尔算子,是图像的一阶梯度算子,它的主要作用是对图像做边缘检测。对于一个3x3的矩形框内,soble算子的计算公式为:

3x3矩形框

Gy = (P7+2*P8+P9)-(P1+2*P2+P3)
Gx = (P7+2*P8+P9)-(P1+2*P2+P3)
|G| = |Gx| +|Gy|


sobel算子对比普通的一阶求导方法会复杂些,从单向计算变成了双向计算,从一条线上的计算变成了一个面上的计算,这样可以认为是一种差分操作,因此它的抗噪声能力是更好的。

对sobel算子的理解,有网友做比较好的总结:http://blog.csdn.net/yanmy2012/article/details/8110316

用python+openCV代码如下:

1
outimg = cv2.Sobel(img_gray,cv2.CV_64F,0,1,ksize=3)

测试图片结果如下:

sobel算子

Compartir

图像与视频处理——图像的模糊、去噪和增强及其OpenCV操作

引言

《图像与视频处理》第三章的内容,前半段是直方图讲解,后半段则是对图像一些简单滤波和增强处理的讲解,主要包括均值滤波、非局部均值滤波、中值滤波以及图像的增强。

从效果上来看,这些处理对图像的影响就是三方面:模糊去噪增强。由于这些概念理解起来相对简单,并没有涉及到比较复杂的滤波器,所以我这里就合在一起说明。

以下为上面三种的滤波器简单对比

处理方法 作用
均值滤波 主要对图像进行平滑操作,去噪的同时容易引起图像模糊
非局部均值滤波 有很好的去噪效果,但是查找的过程运算量大
中值滤波 对椒盐噪声的过滤具有非常好的效果

均值滤波

均值滤波非常简单,其操作为:在需要操作的像素点上选择其邻域部分,如下图为3x3的矩形区域,对这些点求均值,结果代替原始像素点的值。

均值滤波

当然选择区域的大小、形状是可以根据实际需求修改的,不同位置的像素的加权权重也是可以修改的。

在openCV中提供均值滤波 blur函数,由于它是去除变化剧烈的高频部分,所以也可以算是低通滤波了。

python+openCV代码实现均值滤波如下:

1
img2 = cv2.blur(img, (3,3))

上面的代码是在3x3的矩形框了求取的均值,如果需要设置权重,可以使用filter2D()函数。

均值处理后的图像如下:

原图像
均值滤波图像

非局部均值滤波

非局部均值滤波的原理是很简单的,即:选择处理的图像的小区,在整个图像上查找与区域相似度高的区域,对这些相似的区域对应点相加求平均,替换掉原来的值。

在这个过程中相似区域的查找是很关键的一部分,不同设计者的判断标准不一样,可能会导致最终的效果有好有坏;另外由于需要在整个查找相似的区域,计算量也相对会大一些。

中值滤波

中值滤波与均值滤波类似,也十分简单,只是将求平均值的操作变成了找中间数的操作。正是由于这样,中值滤波不会产生新的值,知识用其他pixel的值代替处理的pxiel值,所以对图像的影响会比均值的影响小。

中值滤波是非常简单且常用的滤波方法,它对椒盐噪声具有很强的滤波效果(椒盐噪声就是在图像上随机出现黑色白色的像素)。

openCV中提供 medianBlur函数来处理中值滤波,medianBlur函数要求它的参数中的矩形框为正奇数,python+openCV代码如下:

1
img2 = cv2.medianBlur(img, 3)

经过中值滤波后,图像如下:

原图像

边沿查找和图像增强

通过对离散二维图像的数据求二阶导数,可以找到图像中变化较大的像素点。通过对原图像中的这些像素点的值进行增强,可以达到增强图像的效果。

Compartir