今天开始努力学习

面向谷歌编程选手许若芃


  • Home

  • Categories58

  • Archives85

  • Search

算法:回溯Backtracking

Posted on 2019-10-16 | In 算法 , 回溯

Unity练习FlappyBird

Posted on 2019-10-02 | Edited on 2019-10-08 | In Unity , 练习

教程及素材源自unity官方的learning资料FlappyBird

整体思路:在游戏里物体本体是不会移动的,只有后面的背景滚轴一直在移动,然后每次在玩家视野外生成随机高度的柱子。柱子和背景一起滚动。

生成鸟的物体

sprite

  • sprite是一种半透明的texture。不会直接被用于mesh,而是会用在长方形或者正方形上
  • 修改texture type就可以修改
  • 与canvas render的区别:前者必须放在canvas里面,而后者可以放在hierarchy的任何地方
  • sprite支持网格构造,可以清除不必要的透明元素,可以一定情况下避免overdraw的问题

sorting layer

  • 在sprite render里面会有一项叫做sorting layer,这个功能可以决定画面的前景和后景的遮挡关系。写的越靠下的越前

rigidbody + collider

  • 需要设置刚体和碰撞关系
  • 这里面的碰撞器设置的种类是多边形的

animator(getcomponent)

  • 在这个游戏里,鸟的不同动作会触发不同的动画,所以需要为这个鸟构建一个动画来表现
  • 在animation里面,可以给鸟不同的动作不同的clip。在运行状态下修改鸟在不同clip里面的renderer。
  • 在animator里面可以设置不同动画之间切换的逻辑关系
    • 一种是根据条件切换,需要为不同的条件设置不同的paramter(这里设定的是trigger,这个状态可以直接在script里面set,注意拼写需要一样)(正常 -按-> 挥动翅膀/ 正常 -撞墙-> 死亡)
    • 一种是根据时间切换(挥动翅膀 -> 正常状态)

鸟的行为逻辑

  • 运动:本身的x轴不会运动,y轴在每次按鼠标的时候上升(addForce),不按的时候重力自由落体(对应上升动画)
  • 碰撞:碰撞到地面或者柱子都会死亡(对应死亡动画)
  • 在鸟死亡的时候,会对应鸟的死亡状态在controller里面的切换

UI制作

  • UI使用的就是普通的UI模式,注意所有text都是在canvas里面的
  • 导入素材包字体,可以给字体加阴影
  • UI的分数变化在gamecontroller里面进行操作
  • 字体锚点位置调整需要按alt/option

gameControll

  • 设定了一个static的GameControl(这是这个自建类的名字)的object,名字是instance。设定成static之后,无论在哪里的code里面想要访问这个instance,只需要callGameControl.instance就可以了
  • 为了保证里面拥有这个instance,需要在awake的时候进行检查

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void Awake()
    {
    if (instance == null)
    {
    instance = this;
    }
    else if(instance != this)
    {
    Destroy(gameObject);
    }
    }
  • 在gameControl里面设置好了游戏结束的变量,这个变量可以直接在bird的script里面访问,这样就可以直接在bird里面决定游戏结束没结束,再在现在的control里面决定分数的变化,scene的切换等

  • 也可以在这里操作,游戏重新开始
    1
    2
    3
    4
    5
    6
    7
    void Update()
    {
    if (gameOver && Input.GetMouseButtonDown(0))
    {
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }
    }

地面(及背景:作为地面的子物体)

  • 地面应该有collider,这样鸟撞到地面上才会死。需要用rd
  • 地面应该在start开始就按照一个速度进行负移动,如果游戏结束的话,地面停止移动
  • 地面应该复制两份,当每次第一份快要移动到头的时候,第二份移动到第一份前面去(这个距离可以直接用collider的size来决定
  • 地面的rd应该设置成kinematic,也就是除了script让移动,其他的方法不会让他移动

障碍物

  • 障碍物应该设置成prefab,制作好的东西直接拖进prefab文件夹就可以了。在用的时候可以直接在gamecontrol的物体里面操作这个prefab,直接拖进去就可以了
  • 障碍物本身应该增加了一个box collider的trigger,然后在每个柱子本身里面加上了OnTriggerEnter2D(Collider2D other),也就是在这个trigger的区域里面遇到鸟的时候,会call加分的函数

pool

  • 生成柱子的方法,目前的方法是每次生成五个柱子,存在一个array里面,每次时间到了就随机新的柱子的位置。如果五个柱子都用完了就重头开始,也就是从index是0的柱子开始,重新定位坐标
  • 在初始化五个柱子的时候,用了Object.Instantiate,也就是把这五个柱子在指定的位置复制了五次。其中rotation的参数设置的是Quaternion.identity,也就是没有旋转的意思
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ColumnPool : MonoBehaviour
{
public int ColumnSize = 5;
public GameObject columnPrefab;
public float SpwandRate = 4f;
public float columnMin = -2f;
public float columnMax = 2f;

private GameObject[] columns;
private Vector2 objectPoolPosition = new Vector2(-15f, -25f);
private float timeSinceLastSpwand;
private float spwandXPosition = 10f;
private int currentColumn = 0;

// Start is called before the first frame update
void Start()
{
columns = new GameObject[ColumnSize];
for (int i = 0; i < ColumnSize; i++)
{
columns[i] = (GameObject)Instantiate(columnPrefab, objectPoolPosition, Quaternion.identity);
}

}

// Update is called once per frame
void Update()
{
timeSinceLastSpwand += Time.deltaTime;

if (GameControl.instance.gameOver == false && timeSinceLastSpwand >= SpwandRate)
{
timeSinceLastSpwand = 0;
float spawnYposition = Random.Range(columnMin, columnMax);
columns[currentColumn].transform.position = new Vector2(spwandXPosition, spawnYposition);
currentColumn++;
if(currentColumn == 4)
{
currentColumn = 0;
}
}
}
}

以上,简易版的flappybird就制作完毕了

日语敬语学习

Posted on 2019-09-14 | Edited on 2019-09-16 | In 日语 , 敬语

从头开始了解

一些经常听到的用法

  • 本日 = 今日
  • まことに = 本当に
  • ご案内申し上げます = 知らせます
  • ただいま = いま
  • 〜におきまして = で
  • 〜でございます = 〜です
  • 来場する = 会場に来る

敬语的分组

  • 尊敬语:用来描述对方的行为,直接表示敬意
  • 谦让语;描述自己做的事,贬低自己,间接的表示敬意
  • 丁宁语:让整个对话的气氛都变得很丁宁,气氛比较郑重

基本常识

  • 一般来说,礼貌程度可以分成三个阶层,分别是疯狂使用敬语的 -> 使用ですます的 -> 使用普通形态的朋友间的对话
  • 一般来说,对外的人用敬语,对内的人不同敬语
    • 比如有人打电话到了公司,问你的部长在不在,你自己说部长的时候就不用用敬语了

下面开始根据不同的场合使用敬语

访问

访问时候的特定用语

  • 玄关处
    • ごめんください
    • すいません
  • 部屋に入る時
    • お邪魔します
    • 失礼します
    • 失礼いたします
  • 部屋を出る時
    • 失礼します
    • 失礼いたします

お/ご〜ください

  • 〜てください的丁宁用法
  • masu型去masu加上后面的お,或者suru型直接加后面的ご
  • 例子
    • お入りください
    • お上りください -> 请进的意思 come in
    • おかけください -> 请坐,比如沙发,椅子啥的。和打电话没有关系
    • 日本語でお話しください
    • ご注意ください
  • 注意:这里没有te,不要顺便加上te,没有te,没有!!!!!

つまらないものですが…

  • 一点小东西,不成敬意
  • 更随意的时候可以说(给别人买了吃的的话):美味しいので買ってきました

お〜になります

  • 〜ます的丁宁语,suru的动词不能用这个用法
  • 也就是说一般的动词,如果不是特殊型的话,可以用这个用法代替平常直接用masu
  • 例
    • この教科書は鈴木先生がお書きになります
    • 社長、今朝の新聞をお読になりましたか

上面的尊敬语的特别变形

  • 食べます -> (🙅‍♀x)お食べになります -> (●)召し上がります
  • します -> (🙅‍♀x)おしになります -> (●)なさいます
  • 見ます -> (🙅‍♀x)お見になります -> (●)ご覧になります
  • 也就是说,如果是三类动词的话,后面的する直接变成なさいます
  • 注意:特别变形如果想用ください的时候,可以直接用特别变形之后的动词加上てください、现在这里是有te的,比如おっしゃってください 请说

被动:更加简单一点的用法

  • 使用和被动态相同的方法来表示尊敬,不用像上面的お〜になります这么麻烦,根据上下文可以推测实际的意思
  • 例
    • 書きます -> 書かれます/ 読みます -> 読まれます
    • 出ます -> 出られます
    • します -> されます/ 来ます -> 来られます
  • 注意:这种用法不能和ください一起用,不能用被动后面加ください,要用ください的话请直接用上面的那个带ください的方法
  • 注意:被动型 不要顺嘴和させ说混

特殊敬语构成表

动词 尊敬语 谦让语
行きます いらしゃいます/おいでになります 参ります/伺います
来ます いらしゃいます/おいでになります  参ります
います いらしゃいます/おいでになります おります
言います おっしゃいます (許と)申します/(意見を)申し上げます
見ます ご覧になります 拝見します
食べます/飲みます 召し上がります いただきます
知っています ご存知です 存じております/知っております/(金子部長を)存じ上げております
思います お思いになります 存じます
します なさいます いたします
くれます くださいます
あげます さしあげます
もらいます いただきます
会います お会いになります お会いします/お目にかかります
聞きます お聞きになります お聞きします/伺います
あります あります ございます
寝ます お休みになります
着ます お召しになります
住んでいます お住まいです
持ちます/持っていきます/持ってきます お持ちになります お持ちします
死にました お亡くなりになりました
〜です でいらしゃいます でございます
〜ています ていらしゃいます でおります
  • 尊敬语和谦让语的总结
    • 句型
      • 尊敬 お/ご〜になります お/ご〜ください
      • 谦让 お/ご〜します
    • 简单用法
      • 只有尊敬语可以用被动来表示尊敬
    • 特别型见表
  • 注意尊敬语:

    • 吃和穿长得差不多,但是吃喝里面不需要前面的お
    • 说里面带促音
    • 虽然想听起来很奇怪,但是真的是这样的
    • 住这个词有些奇怪
    • 死一定是过去式的
  • 注意谦让语

    • 来和去都可以是 参。 但是去还有伺う。同时伺う还有听的意思
    • 存じ 在知道和想里面都可以用,注意区别。知道是te型的,所以是おります

打招呼

经常使用的あいさつ

  • 朝
    • おはようがざいます
    • おはよう
  • 会社から帰り時
    • それでは、お失礼にします/失礼いたします
    • じゃ、お先に
  • お礼
    • ありがどうございます -> いいえ/こちらこそ/どういたしまして
    • ありがどう -> ううん/大丈夫だよ
  • 天気
    • いい天気ですね/暑いですね/雨がよく降りますね -> そうですね
    • いい天気だよ/暑いね/よく降るね -> そうだね
  • 別れる時
    • 失礼します/失礼いたします -> お気をつけて/それではまた
    • じゃあね -> 気をつけてね/じゃ、また

谦让语句型

  • お〜します/ご〜します
  • 例子
    • 看见拿着东西的社长 お持ちします
    • 说明的时候 ご説明します
    • 我来帮你 お手伝いします
  • 一般使用谦让语的时候都会省略“我”的主语
  • 对于上级的人不能用 てあげる (要用さし上げる)

谦让语特别型

  • 更多见上面的表
  • 例子
    • メールを拝見しました
    • 駅前で偶然先生にお目にかかりました

例

来週の東京へのご出張のことですが、空港までお迎えにまいります/うかがいます ので、ご到着になる(到着される)時間を~存じさせてください~(お知らせください,这里的主语是对方不是自己)。
空港で資料をお渡ししますので、車の中でご覧ください。
ご昼食の後、会議の場所までお送りします。
どうぞよろしくお願いいたします

邀请

打招呼 声を掛ける -> 找人帮忙的时候的搭话

  • 部長、すみません
  • いま、よろしいですか/ちょっとよろしでしょうか
  • いま、お時間いただけますか

打听别人的安排 予定を聞く

  • 日曜日、何かご予定がありますか
  • 来週の火曜日、小林さんのご都合はいかがでしょうか

邀请

  • 部長にもぜひ来て頂きたいですか 语气比较强的邀请
  • 部長にもご出席いただけないかと思いまして 后面的思いまして带有表示原因的意思
  • よろしかったら、部長もいらしゃいませんか
  • よろしければ、部長もいかがでしょうか
  • もしご都合がよろしければ、部長もいかがかと思いまして

お/ご〜なく(不是什么词都能用的,后面不要加te)

  • ご心配なく
  • ご遠慮なく
  • お気遣いなく
  • おかまいなく

〜ております

  • ています的谦让语
  • 例子
    • お返事をお持ちしております
    • 当日お会いできるのを楽しみにしております

例子:邀请老师

  • よろしければ、先生もいらしゃいませんか/先生も来てきただきたいと思っています
  • 先生のご都合はいかがでしょうか
  • お返事をお持ちしております

请求

打招呼 呼びかける

  • あの、ちょっとよろしいでしょうか
  • 今、お忙しいでしょうか
  • お時間いただきてもよろしいでしょうか

(実は)〜のですが

  • 持ち帰って我が社のものと検討したいのですが。。。
  • 実は使い方がよくわからないのですが。。。

いただけませんか/ご(お)〜いただけませんか

  • 后面那种说法更好一点,中间可以直接填动词的masu型
  • この予告編のDVDを一枚お送っていただけませんか 
  • 注意这里没有te!!!

继续请求

  • 日本語訳をつけていただけないかと思いまして
  • 日本語訳をつけていただけるとありがたいんですが。
    * 思いまして就表示了没说完,但是后面跟着:你能接收我的请求吗的意思

打招呼的方式

朋友 ですます 敬语
ねえ、あのね 可 不可 不可
あの- 可 可 可
悪いんだけど/悪いけど 可 不可 不可
よかったら 可 可 可
すみませんが 不可 可 可
よろしかったら 不可 不可 可
申し訳ありませんが/恐れ入りますが/恐縮ですが 不可 不可 可

文末

朋友 ですます 敬语
~て(よ/ね) 可 不可 不可
~てくれない  可 不可 不可
~てくれませんか  不可 可 不可
~てもらえませんか  不可 可 不可
~いただけませんか  不可 可 可
~いただけませんでしょうか  不可 可 可
~いただきたいんですが  不可 可 可
~いただけないかと思いまして  不可 不可 可
~いただけるとありがたいんですが  不可 不可 可

练习句型

  • すみませんが、〜ていただけませんか
  • 申し訳ないんですが、〜ていただけるとありがたいんですが
    • 用在非常难以开口请求的郑重恳请的情况下
  • あのー、〜てもよろしでしょうか

写推荐信

  • 教師の推薦状が必要なのですが、お書きいただけないでしょうか。
  • 先生の研究室にごあいさつに伺いたいと思いまして
  • 先生のご都合がよろしい時間をお知らせいただけるとありがたく存じます
  • 返事をお待ちしております

拒绝 断る

〜はちょっと。。。

  • 让对方看到自己为难的样子,知道自己有困难

断る

  • 例1:拒绝的时候说到句尾可以不说清楚
    • あ、コピー手伝ってくれないか
    • 今、ロビーでお客様が待っていらっしゃるので。。。
  • 例2:句尾用まして(ます)、でして(です)来表示原因
    • 残念ながら今回は伺えないんです。今夜は友人と会う約束がありまして。。。
    • すみません。お酒はちょっと苦手でして。。。
  • あります -> ございまして/だ -> でして

謝る 拒绝了以后的道歉

  • 被拜托了事情的时候 お役に立てなくて、申し訳ありません。
  • 被邀请了的时候。请先说谢谢 せっかくお誘いくださいましたのに、(すみません)

拒绝了但是还要保持良好的关系

  • 今回は伺えないんですが、また 今度/次回/次の機会 に お誘いください/ご一緒にさせてください

练习

  • 〜はちょっと苦手でして
  • お誘いくださいましてありがどうございます
  • 残念ながら、その日は山田さんと会議の予定でございます。
  • 申し訳ありませんが、参加できません
  • せっかくのお誘いなのにすみません。
  • 今回は伺えないですが、また今度にお誘いください

申し出る 自己主动提出申请

お/ご 〜 (いた)しましょうか

  • 使用自谦语来表示郑重的主动提出,可以让我来干这件事的意思!!没有te
  • 例子
    • お荷物をお持ちしましょうか
    • 資料をお送り致しましょうか
    • 加藤さんには私からご連絡致しましょうか

〜させていただきます

  • 原本是征求对方许可之后做某事,后来发展成敬语用法(させていただきいてもよろしいでしょうか)
  • 未经许可就用的话有强加的意思
  • 例子
    • 会議の日は昼食を用意させていただきます
    • 今日の午後、会議室を使わせていただきたいんですが
    • 今日は申し訳ないんですが、早めに帰らせていただけませんか
    • このパソコンを使わせていただいてもよろしいでしょうか

〜させてください

  • 表达对方同意之后非常强烈的想做这件事
  • 例子
    • 今 度の仕事は私に担当させてください
    • 今夜は私にごちそうをさせてください

お詫びする 道歉

道歉常用句

  • 申し訳ありません(でした)/ 申し訳ございません(でした)
  • 大変失礼いたしました / ご迷惑をおかけしました / どうかお許しください

报告自己的失误

  • 実は、お約束の時間に伺えなくなってしまったんです
  • 11日を21日だと聞き間違えてしまいました

传达反省的心情

  • 以後/今後は気をつけます
  • 二度とこのようなミスをしないように、注意/確認/徹底 いたします

别人对自己道歉的时候

  • 轻松
    • あ、いえいえ、あまりお気になさらないでください
  • 严肃
    • こういうのは困ります
    • こういうことをされると困るんですよ
    • これから気をつけてください

句子

  • お/ご〜してしまいまして、申し訳ございませんでした
  • お/ご〜くださいましたのに、伺えませんで、失礼いたしました(表示的意思是你都邀请我做了,你都准备好了,之类的,但是我做不了)
    • 或者不加o,后面加te也可以

卑微

  • お忙しい中、お時間を作ってくださいましたのに、時間を間違えてしまいまして申し訳ございませんでした。今後は十分注意いたしますので、お許してください。

提意见

问别人的意见

  • これについてはどう思われますか/この点についてはいかがですか
  • みなさんのご意見は/何かご意見はありますか

用一句话表示赞成和反对

  • 赞成:いいと思います
  • 反対:うーん/それはちょっと。。。/どうでしょうか。。。

开始陈述自己的意见

  • ちょっと、よろしいでしょうか

说自己的意见

  • 和平的提案(一般用这种)
    • V/Aい のではないでしょうか
    • N/Aな なのではないでしょうか
    • 例
      • 予算がもっとかかってしまうのではないでしょうか
      • 時間が足りなくて、無理なのではないでしょうか
  • 提议 具体的方案
    • V たらどうかと思います(が)
    • N がいいかと思います(が)
    • 例
      • 時間がかかるので、1ヶ月前から準備したらどうかと思いますが
      • 結婚のお祝いには、二人が長く使えるコーヒーカップなどがいいと思います
  • 归纳意见
    • それよりも Vた 方がいいと思います
    • それよりももっと簡単に準備できる発表に変えた方がいいと思います

接收意见

  • 〜はいいことだと思いますが/それもそうですが

说明理由

忘年会は中華料理がいいのではないでしょうか。というのは、人数が急に増えても大丈夫ですし、若い人はたくさん食べたいという人も多いですし、料理の数も多くで、人気がありますので。。。こちらの方がいいと思います。

整体句型

  • よろしいでしょうか。〜(な)のはいいことだと思いますが、〜(な)のではないでしょうか。それよりも、〜た方がいいと思いますが、いかがでしょうか。

写邮件

  • お疲れ様です。アレクスです。
  • メールを拝見しました。
  • まず席のことですが、フランス料理はいいと思いますが、一人一人の席が離れていてみんなで話すことできないのではないでしょうか。
  • 人数がまだ決まっていないということですが、それなら人数が変わっても大丈夫な中華料理がいいっと思います。今度のお客様はアジアからのお客様が多いと伺っておりますので、アジア料理の方が慣れていていいのではないでしょうか。
  • ~中華料理がいいのではないでしょうか。というのは、人数が急に増えても大丈夫し、お客様はアジア料理の方が慣れているかもしれません。~
  • それよりも、中華料理の方がいいと思いますが、いかがでしょうか。

接收预约

〜でございます 接电话

  • 用于说自己或者自己团体的事情
  • でございます和でいらしゃいます是一个意思,一个用在自己一个用在对方

承ります(うけたまわる) 接受预约

  • 对目上的人接收预约时候的敬语
  • ご予約、承っております
  • ご予約は、私、鈴木が承りました

〜でいらしゃいます 确定预约的人数或者名字

  • 失礼ですが、田中さんでいらしゃいますか
  • 3名様でいらしゃいますか
  • お元気でいらしゃいますか
  • 不能用在和对方无关的事情上

お/ご 〜 になれますか

  • 在日语里直接问目上的人できます比较失礼,所以用这种方法的比较多。只有当有非常稀奇的技能的时候才会用できます
  • 社長はスペイン語がお話になれますか

お/ご〜いただけます = 〜てもらえます(表示的是可以做的意思,没有授受的含义)

  • この建物の中で、wifiがお使いいただけます
  • 特急券をお求めになれば、特急にご乗車いただけます

〜はなさいますか = 〜にしますか = に決めます

  • 料理はどのコースになさいますか

させていただきます 再一次确认

  • 用多了会有强迫的意思
  • ご注文を 繰り返させて/確認させて/復唱させて いただきます
  • 誠に勝手ながら本日は午後七時で閉店させていただきます

サービス敬語

お/ご〜になりましたら 如果你决定好了的话

お決まりになりましたら、お呼びください

お/ご〜くださいませ 丁宁的说请求的时候

  • お一人一枚ずつお取りくださいませ
  • 何かありましたら、ご相談くださいませ
  • ご質問がおありでしたら、お答えいたします
  • お困りでしたら、お手伝いいたします

短语

  • お決まりでしたら(お決まりになっていましたら)、伺います
  • ご予約をご希望なら(ご希望になるなら)、こちらで承ります
  • 先にお並びの方(お並びになっている方)から順にお入りください
  • 整理券をお持ちですか(お持ちになっていらっしゃいますか)

常用服务用语

  • お待たせしました
  • かしこまりました
  • お飲み物はいかがいたしましょうか

けっこうです

接收商量

询问别人的想法的时候

  • 对目上询问想干什么的时候,不能用〜したい来问
  • 先生は何を食べたいですか(X)
    • 先生は何を召し上がりますか
    • 先生はどのようなものがお好きですか

提案する

  • 提建议的时候用とか不是很丁宁,変成 など
  • ビールを召し上がるなら、銀座ホールなどはいかがでしょうか
  • 日本文化体験なら、鎌倉のお寺で座禅をなさったらいかがでしょうか

ご存知ですか ー 存じております/存じ上げております

  • 对事物的话用前者,对人的话用后者
  • アスク商事の高橋部長をご存知ですか ー はい、存じ上げております(回答别人问话的时候)

ご〜(漢字)です 同样表达尊敬语的意思

  • 何かご心配ですか
  • 明日の会議、ご出席ですか

演讲 发表

开始

皆まさ、おはようございます。本日は、〜についてお話しします。

对演讲时的观众说话应该用敬语

在进入话题之后,比起敬语更应该用desu masu

  • ですから = だから
  • ご存知のように/ご存知の通り
  • 〜られております(考える/言う/評価する)

结束

  • 以上、〜いついて紹介いたしました
  • ご静聴ありがどうございます

面试

てまいりました=てくる

  • 高校生の時日本語の勉強をしてまいりました
  • 私はこれまで、通訳の仕事に田鶴わってまいりました

〜ておりますN

私が研究しておりますテーマは、日本語の敬語についてです

〜次第です = 〜んです

  • 御社のビジネスは、私の研究テーマと重なっていると思い、大変興味深く感じた次第です

换种说法

| 〜について面白いと思いました | 〜について興味深く感じました |
| すごく/とても | 大変/非常に |
| どんな | どのような |
| 〜できたらいいなと考えています | 〜できたらと考えております |
| 〜くれたらいいなと思います | 〜くれたらと考えております |
| 〜したいです | 〜できたらと思います |

自己紹介

本日は面接の機会をくださいましてありがとうございます。
早速ですが、自己紹介をさせていただきます。
私はXXと申します。
2018年来日いたしまして、現在、XXXを研究しております。
どうぞよろしくお願いいたします。

被问到问题要先回答 はい,不要加那么多犹豫词

不要太多的用できます

  • 少しでもお役に立てたらと思います

例

私はゲームのプログラムの開発を続けてまいりました。私が使っておりますソフトの開発を多く手がけていらっしゃる御社の事業内容を伺って、非常に興味深く感じました。さらにより良いゲームソフトを開発できたらと考えております。

接电话

はい、XXXでございます

いつもお世話になっております

  • こちらこそ、お世話になっております

(会社名)のXXと申しますが、XX様/役職、いらっしゃいますか

名前 はただいま、XX中でございます

常用语

  • 不在的时候
    • XXはただいま席を外しておりまして。。。
  • 让他一会回电
    • 折り返しXXに電話させましょう
  • 接收留言
    • よろしければ、私がご用件を承りますが。。。
    • 承知いたしました。XXXに申し伝えます。私、XXが承りました
  • 稍后再拨
    • 恐れ入りますが、XX分過ぎにもう一度おかけいただけますでしょうか
    • それでは、XX分後にこちらからおかけします
  • 再一次请教姓名
    • 失礼ですが、もう一度お名前を伺ってもよろしいでしょうか
  • 挂电话
    • では、失礼いたします
  • 换人接
    • お電話かわりました。XXです

采访

〜中/ところ、ありがとうございます

  • お忙しい中/お寒い中/雨の中、わざわざありがとうございます
  • お急ぎのところ/お疲れのところ/お休みのところ、申し訳ありません

重复对方说的话

扩展对方说的话

想确认时

  • 今、何とおっしゃいましたでしょうか。/と、おっしゃいますと
  • その〜と言うのは、どのような意味ですか

报告

有顺序的报告

  • まず、XXXについて報告します
  • 以上、概要いついてご報告しました
  • 次に、
  • その次に/それから
  • 最後に

とのことです = そうです 转述听到别人的话

请看

  • ことらの写真をご覧ください
  • ご覧いただくとお分かりのように、。。。

发表感想

  • 。。。と思います
  • 。。。のではないでしょうか
  • た 方がいいと思います

结束报告

  • 以上で報告を終わります
  • 以上、XXXについてご報告しました
  • 何か質問はありませんか/ご質問がおありでしたらどうぞ

司会的敬语

虽然是朋友,但是在很多人面前说的时候也要丁宁一点

おVです = おVになっていらっしゃいます

  • 皆さんお揃いですので、
  • 皆さんお見えですので、

そろそろ始めたいと思います

常用语

  • 大きな拍手でお迎えください
  • 〜さんの前途を祝して/今後のご活躍とご健康を祈って、乾杯をしたいと思います
  • 乾杯の音頭は〜先生にお願いしたいと思います
  • お手元のグラスをお持ちください
  • ごゆっくりお楽しみください
  • ここで一言ご挨拶申し上げます
  • では、〜さまにお祝いのことばをいただきたいと思います
  • そろそろお聞きにしたいと思います

邮件

| 挨拶 | いつもお世話になっております |
| お礼 | メール、ありがどうございます |
| 始める | では、XXXの件ですが |
| 知らせる | 次回は先生をお迎えして下記の通りお食事をすることにいたしました |
| お願い | ご検討いただきますようお願いいたします/お目通しくださいますようお願い申し上げます |
| 自分の希望 | お目にかかりたいと存じます/ゆっくりお話を伺いたいと存じます/一度おいでいただけたらと存じます |
| 終わり | お待ちしております/よろしくお願いいたします/取り急ぎお返事申し上げます |
| もとめる | 以上、ご案内/ご招待 申し上げます |
| 付け加える | なお、 |

一些

一些特定说法

家人称呼

我 他 普通 他 敬语
父 ちち お父さん お父様
母 はは お母さん お母様
兄 あに お兄さん お兄様
姉 あね お姉さん お姉様
弟 おとうと 弟さん 弟様
妹 いもうと 妹さん 妹様
夫(おっと)/旦那/主人 ご主人 ご主人様
妻(つま)/家内(かない) 奥さん 奥様
子ども お子さん お子様
息子 息子さん ご子息(しそく)
娘 娘さん お嬢様

人称

ですます 敬語 友達
わたし わたくし わたし/僕/俺
わたしたち わたくしたち わたしたち/僕たち/俺たち
皆さん 皆様 みんな
お客さん お客様 客
友人 ご友人 友達
あの人 あの方 あいつ/彼/彼女
お店の人 お店の方 店員
係の人 係の方 係
駅員さん 駅員さん 駅員
アメリカの人 アメリカの方 アメリカ人

公司,人员,学校等

自己的 他人的
弊社(へいしゃ)のXXX/うちのXXX XXX+职位
弊社/我が社/当社 御社(おんしゃ)/貴社(きしゃ)
本校/当校 御校/貴校
本学(特指大学) 御学/貴学

常用 お/ご 词

  • 动词
    • お
      • お電話します
      • お約束します
      • お持ちします
    • ご
      • 報告
      • 紹介
      • 遠慮
  • 形容词
    • お
      • お好き/お嫌い
      • お元気/お疲れ/お急ぎ
    • ご
      • ご健康/ご無理
      • ご満足/ご不快
  • 名词
    • お
      • お電話/お写真
      • お返事/お食事
      • お手紙/お荷物/お持ち物
      • お名前/お気持ち
      • お金/お礼/お土産
      • お弁当/お風呂
      • お飲み物/お品物
      • お手洗い
      • お見舞い/お祈り/お祝い
    • ご 
      • ご家族/ご夫婦/ご長男
      • ご住所/ご印鑑/ご予算/ご意志/ご本
      • ご署名/ご注文/ご計画
      • ご予約/ご招待
      • ご出席/ご参加/ご登録/ご入金
      • ご入学/ご出発
      • ご結婚/ご関係

日子的说法

普通 敬语
今日 本日
昨日 昨日 さくじつ
あした あす/みょうにち
おととい いっさくじつ
あさって みょうごにち
今年 本年
去年 昨年(さくねん)
おととし 一昨年 いっさくねん
1ヶ月 ひと月

副词的转换

普通 敬语
いま ただいま
さっき 先ほど
後で 後ほど(のちほど)
この間 先日
その日 当日
もうすぐ 間もなく
赶紧开始 さっそく
急いて/すぐに 早急に(さっきゅう)/至急(しきゅう)
すぐに ただちに
前に あらかじめ
〜たらすぐに 〜次第、
残念 あいにく
ぜひ
丁寧に 丁重に
だいたい 概ね(おおむね)
少し 少々(しょうしょう)

动词的转换

普通 敬语 用法
受け取る/もらう 受領する 配送物
受け取る/もらう 拝受する 配送 邮件 信
査収する 确认内容之后查收,自己不用
納める 赠品,贵重物品等
金を払う 納める 税金
送る 送付する 邮寄品,邮件
発送する 配达物
入金する 银行汇款
捺印する 盖章
使う 使用する 物品
利用する 物品,服务
ほしい/したい 希望する
売る 販売する
売り出す 発売する
買う 購入する
求める(もとめる)
読む 拝読する 邮件,信
聞く 拝聴する 意见,演讲
書く 記入する 申请用纸
書く 記す(しるす)
知らせる 通知する
頼む 依頼する
受ける 承る
考える 検討する
わかる 承知する/理解する/了承する
あきらめる 断念する
忘れる 失念する
帰国する
出社する/出勤する 来自己的公司
退社する/退勤する 下班回家
失礼する
帰宅する
退社/退職する 辞职
開店する
閉店する
来店する
来場する
座る かける

数据结构之Tree

Posted on 2019-09-14 | In 数据结构 , 树

基本作用

  • 树是图的一种,但是不是首尾连在一起的
  • 树的其中一类是从 self-balanced tree BST演变出来的,包括红黑树,AVL,Splay,Treap等等(经常在面试出现但是实际不常用)
  • 另一种大类是 Trie(字典树),能保证字典排序。前缀搜索,正则匹配,数据压缩,构建索引等等用处

二叉树,最基础的结构

定义

  • 每个数的节点最多只有两个子节点
  • 子节点分左右,必须不能颠倒

应用环境

  • hash表,sets
  • 数据库,优先队列
  • LDAP查找信息,在XML/HTML中进行搜索

不同分支:

  • full binary tree:除了叶节点(也就是一个子节点都没有的点),其他的都有两个子节点
  • complete binary tree:除了最后一层外,其他层的节点都有两个子节点,最后一层的子节点必须是左对齐
  • perfect binary tree:形成完美的三角形

BST 二叉搜索树

定义

  • 两个子节点里面,左边的必须小于父节点,右边的必须大于父节点

操作

  • 插入:
    • 如果没有任何点,作为root
    • 如果大放到右边的子树,小放到左边的子树
    • 重复2直到找到空位
  • 删除:
    • 删除叶节点:断掉这个点和父节点的联系
    • 删除只有一个子节点的点:把父节点对待删除点的reference改为父节点对待删除点子节点的reference
    • 两个子节点的点:左节点不动,右边的换到父节点的位置上/右节点不同,左节点换到父节点
    • 删除root:需要更改对root的reference
  • 遍历
    • 顺序:左-> 中 -> 右
    • 反序:左 -> 右 -> 中
    • DFS:中 -> 左 -> 右

平衡二叉树 AVL树

  • 左右两个子树的高度差不超过1
  • 且子树本身也是平衡树
  • 在构建平衡树的时候确保他们平衡,从而导致最差的时间复杂度也是 logN
  • 虽然在插入或者删除的时候,可能会在旋转上花费时间,但是整体性能更加稳定

旋转

  • 对于需要旋转的情况来说,一共有四种基本状况
  • 对于左左或者右右:但旋转
  • 对于左右或者右左:双旋转

红黑树

  • 节点是红色或黑色
  • 叶节点都是黑色的
  • root是黑色的
  • 每个红节点必须有两个黑子节点,也就是说不能路径上有两个连续的红色
  • 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点

B树

定义

  • 用来处理排序后的数据,查找,插入,删除,循序存取都在对数时间完成
  • 对于普通的二叉树,可以有多于两个的节点
  • 优化大块数据的读写操作,加快存取速度

在构建的时候,每一个点的存储数量是有限的,超过上限的时候,本节点分别成三部分,一个往上移动,另外两个分开

B+树

  • 只有达到叶节点才算命中,B树可以在非叶命中
  • 更适合文件索引系统

B * 树

  • 节点利用率从 1/2变成了 2/3

Trie树 字典树

  • hash树的变种,保存大量字符串
  • 利用公共前缀减少查找时间

特点

  • 根节点不包括字符,除了根节点都只包含一个字符
  • 从根节点到某一节点,一路连过去就是相关的字符串
  • 每个节点的子节点的字符都不相同

参考来源

  • [Data Structure] 数据结构中各种树
  • 初学者应该了解的数据结构: Tree

Unity的shader

Posted on 2019-09-14 | In Unity , 入门

参考来源
这里

定义

  • shader,着色器,是一段负责将输入的mesh用指定的方式和输入的贴图,颜色等作用,然后输出
  • 输入贴图或者颜色,以及对应的shader,就可以得到一个material,然后将可以把材料给到renderer来进行输出
  • shader如果是自己来写的话,需要新创建一个shader文件
    • 比如在这里老师写的omniProcam的投影的shader,里面的参数就包括了fisheye相机的参数等等。这部分的参数也就是shader的输入,定义了这个shader需要的属性
    • 需要在里面设定不同的subshader,这部分是代码的主题,在每一个里面包含不同的pass。然后运行的时候会从最优先的着色器开始找。在shader的最后需要一个fallback,也就是说所有的subshader都不能运行的时候,需要一个返回情况

代码讲解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Shader "Custom/Diffuse Texture" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200

CGPROGRAM
#pragma surface surf Lambert

sampler2D _MainTex;

struct Input {
float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}

属性

  • Properties里面定义了这个shader的属性,这里面的所有属性将作为input提供给子着色器
  • _Name("Display Name", type) = defaultValue[{options}]
  • 格式
    • _属性名
    • “display name” 显示给用户的可读的名字
    • type属性的类型
      • 颜色,RGBA
      • 2D,2的指数大小的贴图
      • rect,非2的指数大小的贴图
      • cube,立方体纹理
      • range,一个范围里面的数
      • float,任意一个浮点数
    • 属性的默认值,比如颜色可以设定成“white”
    • opinion项,至少需要在贴图后面加上空白的花括号,只和2d rect或者cube有关系

subshader

  • tag:比如渲染类型,如果是非透明的物体要写在opaque里面,透明的写在transparent里面
  • LOD:level of detail
  • CGPROGRAM,开始的标记,从这里开始是一段CG程序。和最后的ENDCG是对应的
  • #pragma surface surf Lambert一个编译指令,声明了要写一个表面的shader,指定了光照模型
  • sampler2D对贴图进行操作,2d的贴图模型。虽然在之前的属性里面声明过一次,但是因为这里面是cg代码,还是需要重新声明一次
  • 需要在struct里面定义出来需要输入和输出的数据类型
  • uv:uv mapping指的就是把一个2d贴图上面的点按照一定规则映射到3d模型上。如果在贴图变量前边加上uv.uv_MainTex指的就是提取这个变量的uv值,也就是说二维坐标
  • surf函数,surf是之前定义的光照模型,有两个参数
    • In里面的内容是uv值,也就是说每次都会调用贴图上面的坐标点才计算输出
    • inout是输出值

十大经典排序

Posted on 2019-09-03 | Edited on 2019-09-04 | In 算法 , 排序

参考出自:五分钟学算法

  • 时间复杂度
    • 最好情况
    • 最坏情况
  • 空间复杂度: 需不需要开辟新的空间
  • 排序方式:in-place还是不是in - place
  • 排序稳定性: 也就是之前顺序的东西在排序之后是否还顺序

冒泡排序

  • 前面一个数和后面一个比,如果前面的数比后面的大(或者小),就交换他们两个
    • 这样交换一次之后的最后一个数就是所有数字里面的最大数
    • 也就相当于最大的数像冒泡一样冒出来了,第一轮过后,第二轮可以直接冒倒数第二个数,也就是说每一轮的内循环次数可以逐渐减少
  • 需要重复n次(但是每次对越来越少的数字进行上述操作),以确保所有的交换都已经完毕了。
  • 增加了一个flag的判断,如果在一轮里面没有任何交换产生,那就说明所有的元素都已经排序完毕了(因为如果还有数字往上冒必然会在前面有交换

    • 这样如果是正序排列的话,可以直接跳出循环,不用进行比较,时间复杂度是n
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15


      def bubbleSort(num):
      n = len(num)
      for j in range(1, n):
      flag = True # 如果在这轮没有任何交换,就可以说明排序已经完成了
      for i in range(n - j):
      if num[i] > num[i + 1]:
      temp = num[i]
      num[i] = num[i + 1]
      num[i + 1] = temp
      flag = False
      if flag is True:
      break
      return num
  • 时间复杂度:

    • 当正序排列的时候,因为可以直接跳出循环,所以只需要遍历一次所有的数保证他们排列正常,所以时间复杂度是n
    • 当倒序排列的时候,需要把所有都移动一遍,所以时间复杂度是 n ^ 2
    • 平均的复杂度是n方
  • 空间复杂度:
    • 因为交换只需要一个额外的temp来储存临时变量,空间复杂度是1
  • in-place:是的
  • 稳定性:稳定,因为一次换过来的东西就不动了,在判断大小的时候也是判断的大于而不是大于等于,也就是说前面换到后面的大数永远会在后面的数的前面
    • 比如[0, 8, 1, 8, 2]。首先会把第一个8换到第二个8的前面,因为判断条件没有等于,所以越不过去。

选择排序

  • 从所有元素中找到最小(或者最大)元素,然后放到数组的第一个(也就是和数组的第一个交换位置),然后这个就算是固定住了
  • 然后从第二个到最后一个中选择现在最小的,和数组的第二个交换位置,前两个就固定住了
  • 以此类推

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16


    def SelectSort(nums):
    n = len(nums)
    for i in range(n):
    Min = float("inf")
    index = None
    for j in range(i, n):
    if nums[j] < Min:
    Min = nums[j]
    index = j
    if index != i: # 这样可以减少一些根本不用交换的情况,下一个位置上本来就是最小的
    temp = nums[i]
    nums[i] = nums[index]
    nums[index] = temp
    return nums
  • 时间复杂度:

    • 最好情况和最坏情况都不能避免走两个循环,都是n ^ 2
  • 空间复杂度: 1, 来储存temp的值和暂时的最大值的变量
  • in-place:是的,换位置就可以,不需要单拿出来
  • 稳定:
    • 不稳定,因为在交换位置的时候,并不知道现在的东西被交换到哪里去了
    • 比如:[3, 3, 0, 9],当0和3交换位置的时候,把第一个3交换到第二个3后面去了

插入排序

  • 在第1轮,认为第1个已经排好序了,然后从第二个开始拿出来,把它放在排好序的里面的合适的位置上
  • 从第二轮开始依次类推,所以还是两个循环
  • 在第i轮里面,前i个元素已经是排好序的了
  • 在插入的过程当中,需要考虑如果把所有的需要移动的数字的坐标都移动一位。这时候比较有效的考虑方法是从最右边开始往左边移动,只要右边的数比现在的temp要大,这一位(实际上这一位指的是j - 1,因为j是移动之后的坐标)就需要移动。移动之后再减1
  • 在所有的都移动结束之后,如果j这个位置和i的位置不一样,就说明发生了插入,那么就是nums[j] = 被插入的数字temp
1
2
3
4
5
6
7
8
9
10
11
12
13


def InsertSort(nums):
n = len(nums)
for i in range(1, n):
temp = nums[i]
j = i
while j > 0 and temp < nums[j - 1]:
nums[j] = nums[j - 1]
j -= 1
if j != i:
nums[j] = temp
return nums
  • 时间复杂度
    • 最好的时候,不需要插入,最大值直接放在了前面排好序的最右边,也就是没有内循环,n
    • 最差的时候,反序,需要全都循环一遍 n2
  • 空间复杂度 1
  • in-place
  • 稳定性:稳定,因为如果是[2, 0, 0, 1],第一个0先插入变成了[0_1, 2, 0_2, 1],然后插入第二个0的时候因为比较的时候没有比等于,所以会变成[0_1, 0_2, 2, 1]

希尔排序

  • 选择一个序列来对这个数组进行排序,比如如果是10个数,可以是5 2 1这样的,最后一个一定是1(设定的公式是3xn + 1不知道为什么)
  • 然后根据这个序列把数组分成这个序列个数的组,对每组的数字进行插入排序。比如用5分成两份,那就要进行5次,两个之间的排序
  • 一共进行的排序次数是和序列的个数有关的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def ShellSort(nums):
n = len(nums)
gap = 1
while gap < n / 3:
gap = gap * 3 + 1 # 一个神奇的选择方法,也不知道为什么但是确实很好用
while gap > 0:
for i in range(gap, n):
# 这里执行的是插入排序,和上面的插入排序一样,只不过每次跳gap个了
temp = nums[i]
j = i
while j > 0 and temp < nums[j - gap]:
nums[j] = nums[j - gap]
j -= gap
if j != i:
nums[j] = temp
# 直接int就可以向下取整,因为加1并不影响取整效果
gap = int(gap / 3)
return nums
  • 关于增量,不同的增量对时间复杂度有不同的影响
    • 目前应用最多的是 Knuth增量:1,4,13,40,…,(3^k - 1)/2,也就是代码里面的这个增量
    • 这时候的复杂度是 N^(3/2)
  • 时间复杂度:
    • 根据不同的步长不同而有所差别,还有的步长还没计算出来复杂度
    • 如果是原版的,也就是原长度一直除2的话
      • 最好效果:n,也就是不需要内循环
      • 最烂效果:n^2
  • 空间复杂度 1
  • in-place
  • 不稳定,因为很有可能因为分组的不同把两个数的顺序颠倒,比如两组的后面都是3,但是第一组的前一个是2,第二组的前一个是4,这样就把第二个3换到前面去了

归并排序

  • 归并排序是分治法的一个典型的应用,可以把有序的子列合并,然后得到新的有序的子列
  • 比较方法
    • 首先比较两个子列的初始值a[i]和b[j],把比较小的那个(比如i)放进新的list[k]里面,并且让i和k分别加一,然后继续比较i和j,然后结果放进k里。
    • 如果有一个子列已经取完了,那么可以直接把另一个里面的剩余元素复制到新的list的最后
    • 因为现在使用的子列已经是排好序的了,所以可以使用这种比较方法。初始状态认为每一个数字都是一个单独的子列,所以往上合并的时候都是有序的了
  • 实现:
    • 申请一个新的空间,大小是两个子列的大小之和
    • 两个指针分别从初始位置开始
    • 根据上面的方法移动指针
    • 在实现的过程中需要用到拆分和合并两个步骤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def MergeSort(nums):
n = len(nums)
if n < 2:
return nums
middle = int(n / 2)
L, R = nums[:middle], nums[middle:]
return merge(MergeSort(L), MergeSort(R))


def merge(L, R):
M = []
i, j = 0, 0
while L and R:
if L[0] <= R[0]:
M.append(L.pop(0))
else:
M.append(R.pop(0))
while L:
M.append(L.pop(0))
while R:
M.append(R.pop(0))
return M
  • 在python实现中,其实并不需要用坐标表示,可以直接用pop把每次需要取的东西取出来

  • 时间复杂度

    • 无论最好或者最坏的情况都需要把所有东西都比较一回,一共是logn层,每层的实际内容都是n个,所以最终的复杂度是nlog(n)。这样看出来归并排序对于最好和最坏的情况比较稳定
  • 空间复杂度:
    • 临时数组的时间n + recursive的时候的空间logn = O(n)
  • out of place
  • 稳定性:稳定,因为在左边的一定是在左边

快速排序

  • 选取数组的第一个作为标准,然后把比这个标准小的都放在左边,比标准大的都放在右边
  • 然后再分别对左右进行快速排序
  • 注意,在不是python的情况下,需要通过角标互换的方法得到结果
  • 实现
    • 选择一个基准piv
    • 数列最左边的标记为左标记,最右边的标记是右标记
    • 将左标记向右标记移动
    • 如果左标记的值超过了piv的值,停止
    • 移动右标记
    • 当右标记小于piv的时候,停止移动
    • 当左右标记都停止的时候,交换两个数字
    • 然后继续移动,直到两个标记碰到一起,这时候把这个值和piv交换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def QuickSort(nums, s, e):
if s < e:
i, j = s, e
piv = nums[i]
index = i
while i < j:
while (i < j) and nums[j] >= piv:
j -= 1
while (i < j) and nums[i] <= piv:
i += 1
nums[i], nums[j] = nums[j], nums[i]
nums[i], nums[index] = piv, nums[i]

QuickSort(nums, s, i - 1)
QuickSort(nums, j + 1, e)
return nums
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def QuickSort_1(nums):
n = len(nums)
if n < 2:
return nums
temp = nums[0]
less, more, equal = [], [], [temp]
for i in nums[1:]:
if i < temp:
less.append(i)
elif i > temp:
more.append(i)
elif i == temp:
equal.append(i)

# less = [x for x in nums[1:] if x < temp]
# more = [x for x in nums[1:] if x > temp]
# equal = [x for x in nums if x == temp]
return QuickSort(less) + equal + QuickSort(more)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def QuickSort_3(nums):
if len(nums) < 2:
return nums
i, j = 0, len(nums) - 1
piv = nums[i]
index = i
while i < j:
while (i < j) and nums[j] >= piv:
j -= 1
while (i < j) and nums[i] <= piv:
i += 1
nums[i], nums[j] = nums[j], nums[i]
nums[i], nums[index] = piv, nums[i]
return QuickSort_3(nums[:i]) + [piv] + QuickSort_3(nums[i + 1:])
  • 第一种方法input的时候需要确定最开始和结束时候的index。看起来只有第一种方法是in-place的实现?
  • 时间复杂度:
    • 最差的时候和冒泡排序是一样的(也就是排好的),这时候的复杂度是n^2
    • 最好的时候是完全平分,这时候是 nlogn
  • 空间复杂度:如果用第一种方法,只耗费recursive时候的空间,也就是logn
  • in-place
  • 不稳定,因为不知道在换的时候就把什么奇奇怪怪的东西换到前面去了

堆排序

  • 一种类似二叉树的设计,子节点的数值总是大于或者小于父节点的数值。首先要让数据形成这样的结构
  • 每次操作的时候,都把root的值和最后一个节点交换,交换后的最后一个节点移动出堆,然后再重新移动堆让他保持上面说的性质
  • 一般通过一维数组来访问
    • 父节点i的左节点:2i+1
    • 父节点i的有节点:2i+2
    • 子节点的父节点: floor((i-1)/2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def HeapSort(nums):
# start是从最后一个父节点开始的,构建出heap
for start in range((len(nums)-2)//2,-1,-1):
MinHeap(nums,start,len(nums)-1)

for i in range(len(nums)-1,-1,-1):
nums[i],nums[0] = nums[0],nums[i]
# 因为这里换到最后去的数字就已经确定是最大值了,所以再考虑的时候不用考虑他了
MinHeap(nums,0,i-1)
return nums

def MinHeap(nums, start, end):
dad = start
child = dad * 2 + 1
# 如果子节点还在这个堆里面的话
while child <= end:
if child + 1 <= end and nums[child] > nums[child + 1]:
# 比较两个子节点,选出来更小的那个
child += 1
if nums[dad] < nums[child]:
break
else:
nums[dad], nums[child] = nums[child], nums[dad]
dad = child
child = dad * 2 + 1
  • 注意:如果是maxheap(即root上的数字是最大的数字的话),实际排出来的是由小到大,因为max的数字在每一次都被换到了最后面
  • 时间复杂度:nlogn
  • 空间复杂度:1
  • 上面的代码可以原地完成的 in place
  • 稳定性:不稳定,这种瞎换的很难搞清楚到底换到哪里去了

计数排序

  • 扫描一遍整个数组,找到最大值max和最小值min,花费时间n
  • 创建一个新的数组,大小是max-min + 1
  • 然后用新数组里面的index来统计每个数字出现的次数,最后整理出来
1
2
3
4
5
6
7
8
9
def CountingSort(nums):
Max,Min = max(nums),min(nums)
counting = [0 for i in range(Max-Min+1)]
result = []
for n in nums:
counting[n-Min] += 1
for n,i in enumerate(counting):
result += i * [n + Min]
return result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def CountingSort_2(nums): #并不创建新的数组
Max= max(nums)
bucketLen = Max + 1
bucket = [0]*bucketLen
sortedIndex = 0
n = len(nums)
for i in range(n):
# 如果现在的这个位置是空的
if not bucket[nums[i]]:
bucket[nums[i]] = 0
bucket[nums[i]] += 1
for j in range(bucketLen):
while bucket[j] > 0:
nums[sortedIndex] = j
sortedIndex += 1
bucket[j] -= 1
  • 不是比较排序,时间上来说比任何比较排序都快
  • 没法用在排序的东西不是数字的情况下,数字差异非常大的情况会很占内存。排序的必须是整数
  • 时间复杂度
    • n+k,只需要在整个数组里找出最大值和最小值,然后在k时间里面数数每个数字出现了多少次。其中k是这些整数的范围
  • 空间复杂度
    • k用来储存计数的数组
  • 稳定:为了保证数组的稳定性,需要反向填充数组(现在的方法不能保证稳定性)

桶排序

  • 思想基于上面的计数排序,但是没有分那么多种
  • 主要想法就是先把现在的内容分到k个不同的桶里面,再在每个桶里面分别排序
  • 步骤
    • 把数据分到k个桶里
      • 每个桶的范围是 floor((max-min+1)/ k)
      • 放入桶的编号为 floor((数字-最小值)/每个桶的范围)
    • 对每个不为空的桶排序
    • 连接每个不为空的桶
  • 时间复杂度:
    • 最好n+k -> 平均分
    • 最差是n^2 都分到一个桶里了
  • 空间复杂度 n+k
  • 稳定,注意先放进桶里的要先拿出来,才能保证稳定

基数排序 radix sort

  • 非比较的整数排序的算法。也可以用在字母上,也就是LSD和MSD
  • 把整数按位切割成不同的数字,然后每个位的数字分别比较。需要把比较的位放进0-9的九个桶里
  • 步骤
    • 所有数统一到一个长度,短的话前面补0
    • 从最低位开始,依据最低位进行排序
    • 一直排到最高位,排序之后就是有序的了

unity显示相机画面并在opencv处理

Posted on 2019-08-22 | In Unity , OpenCV

打开相机

显示方法

首先需要明确,目前看到的显示图片有两种方法,一种是渲染到实际的gameobject上面去,另一种是draw到GUI上面去。关于gameobject在上一个显示图片里面有了大致的了解。这里主要说的内容包括

  • 相机显示的必备步骤
  • 关于GUI
  • 关于renderer

相机内容显示

  • 在unity中,有一个专门的类叫做WebCamTexture,我们需要为读取进来的相机texture创建一个新的对象。一般来说,需要三个部分,相机纹理,相机名字(string)以及相机是否打开(bool)

start部分

  • 在这部分,我们首先需要把创建的cameraTexture实例化
  • 其次,我们需要调用StartCoroutine函数,在其中调用测试函数来确定相机是否打开

StartCoroutine

  • 在一般的执行里面,unity是逐帧运行的,所以当操作花费时间的时候,帧率下降,就会发生卡顿
  • 这部分开始了一个协程(Coroutine),使用yield,可以在任何部分暂停这个Coroutine的执行。如果被成功暂停,它会在下一帧恢复正常。所以这个方法在多帧运行之中非常好用。
    • unity会假装开辟一个新线程来执行,但是不会影响主线程的持续效果
    • 参考
  • 从这里的功能来说,yield会检查用户有没有授权,如果没有授权的话,运行被终止,跳到下一帧。如果授权成功了的话,运行成功,相机打开。

IEnumerator

  • 在StartCoroutine调用的是一个IEnumerator函数,他通过yield一个bool来决定是不是继续运行这个函数

授权

  • 在test里面需要考虑有没有用户的授权
  • 有授权的情况下,需要把目前的WebCamTexture(注意这里不是建立的实例)的device的数据传递给WebCamDevice,包括类型,名字等等。
  • 然后需要把包括这个相机名字,size和fps的信息传给之前cameraTexture的实例
  • 以上都设定好之后,WebCamTexture.Play会激活这个相机,让他开始工作
  • 然后再讲相机的texture渲染到object的表面上
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
    if(Application.HasUserAuthorization(UserAuthorization.WebCam))
    {
    WebCamDevice[] devices = WebCamTexture.devices;
    cameraName = devices[0].name;
    cameraTexture = new WebCamTexture(cameraName, 1024, 768, 15);
    cameraTexture.Play();
    isOpen = true;
    renderer.material.mainTexture = cameraTexture;
    }

GUI

  • GUI主要是提供了图形化的窗口,实际上显示的元素是直接显示在game画面上的,也就是说这部分是和实际相机拍摄到的画面独立的。无论相机如何移动,物体如何改变,最终GUI的画面都会显示到同样的地方

MonoBehaviour.OnGUI()

  • 注意OnGUI函数并不需要我们自己去调用,不需要再update里面调用!
  • OnGUI是API里面自带的函数,我们需要在这个函数中渲染和处理GUI的event
  • 在实际应用中,OnGUI可能每一个frame被call很多次,每次event(例如鼠标操作,键盘等等)发生的时候都会call这个函数
  • 例如下面官方的例子,每次鼠标点击的时候,就会print出相应的话来
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    using UnityEngine;
    using System.Collections;

    public class ExampleClass : MonoBehaviour
    {
    void OnGUI()
    {
    if (GUI.Button(new Rect(10, 10, 150, 100), "I am a button"))
    {
    print("You clicked the button!");
    }
    }
    }

GUI.DrawTexture

  • 在GUI的实现中,我们需要将相机读取到的部分draw的GUI的上面,所以调用了这个函数
  • 需要确定的参数包括:位置,需要渲染的texture,缩放比例等等

实现

  • 代码部分参考
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class showCamera : MonoBehaviour
    {
    protected WebCamTexture cameraTexture;
    protected string cameraName = "";
    protected bool isOpen = false;

    //protected MeshRenderer renderer;

    // Start is called before the first frame update
    void Start()
    {
    //renderer = this.GetComponent<MeshRenderer>();
    cameraTexture = new WebCamTexture();
    StartCoroutine(Test());
    }

    // Update is called once per frame
    void Update()
    {
    }

    IEnumerator Test()
    {
    yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
    if(Application.HasUserAuthorization(UserAuthorization.WebCam))
    {
    WebCamDevice[] devices = WebCamTexture.devices;
    cameraName = devices[0].name;
    cameraTexture = new WebCamTexture(cameraName, 1024, 768, 15);
    cameraTexture.Play();
    isOpen = true;
    //renderer.material.mainTexture = cameraTexture;
    }
    }

    void OnGUI()
    {
    if(isOpen)
    {
    GUI.DrawTexture(new Rect(0, 0, 400, 300), cameraTexture, ScaleMode.ScaleToFit);
    }
    }
    }

渲染到object上面

  • 和之前的操作类似,需要
    • 构建MeshRenderer的object
    • 在start里面读取出物体的MeshRenderer(getcomponent)
    • 最后打开相机后,把相机的内容渲染到MeshRenderer上面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class showCamera : MonoBehaviour
{
protected WebCamTexture cameraTexture;
protected string cameraName = "";
protected bool isOpen = false;

protected MeshRenderer renderer;

// Start is called before the first frame update
void Start()
{
renderer = this.GetComponent<MeshRenderer>();
//cameraTexture = new WebCamTexture();
StartCoroutine(Test());
}


IEnumerator Test()
{
yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
if(Application.HasUserAuthorization(UserAuthorization.WebCam))
{
WebCamDevice[] devices = WebCamTexture.devices;
cameraName = devices[0].name;
cameraTexture = new WebCamTexture(cameraName, 1024, 768, 15);
cameraTexture.Play();
isOpen = true;
renderer.material.mainTexture = cameraTexture;
}
}

//void OnGUI()
//{
// if(isOpen)
// {
// GUI.DrawTexture(new Rect(0, 0, 400, 300), cameraTexture, ScaleMode.ScaleToFit);
// }
//}
}

将图片放入opencv

来源

  • 得到了web的texture之后,可以直接用openCV的部分把这个玩意转换成mat,然后处理
  • 这里的问题是刚开始mat的大小莫名其妙的是16,所以需要加上一个判断条件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OpenCVForUnity.CoreModule;
using OpenCVForUnity.UnityUtils;
using OpenCVForUnity.ImgprocModule;

public class showCamera : MonoBehaviour
{
protected WebCamTexture cameraTexture;
//protected string cameraName = "";
//protected bool isOpen = false;
private Color32[] colors;
private Mat rgbaMat;
private Texture2D tex;

// Start is called before the first frame update
void Start()
{
//renderer = this.GetComponent<MeshRenderer>();
//cameraTexture = new WebCamTexture();
//StartCoroutine(Test());
cameraTexture = new WebCamTexture(WebCamTexture.devices[0].name, 640, 480);
cameraTexture.Play();

StartCoroutine(init());
}


private IEnumerator init()
{
Debug.Log(cameraTexture.width);
if (cameraTexture.width <= 16)
{
while(!cameraTexture.didUpdateThisFrame)
{
yield return new WaitForEndOfFrame();
}

cameraTexture.Pause();
colors = cameraTexture.GetPixels32();
cameraTexture.Stop();

yield return new WaitForEndOfFrame();
cameraTexture.Play();

tex = new Texture2D(cameraTexture.width, cameraTexture.height, TextureFormat.RGBA32, false);
rgbaMat = new Mat(cameraTexture.height, cameraTexture.width, CvType.CV_8UC4);

GetComponent<Renderer>().material.mainTexture = tex;

}
}

private void Update()
{
Debug.Log(cameraTexture.width);
if (cameraTexture.didUpdateThisFrame && rgbaMat != null)
{
Utils.webCamTextureToMat(cameraTexture, rgbaMat);
//Imgproc.cvtColor(rgbaMat, rgbaMat, Imgproc.COLOR_RGB2HSV);
Utils.matToTexture2D(rgbaMat, tex);
tex.Apply();
}
}

}

编程珠玑ProgrammingPearls

Posted on 2019-08-20 | Edited on 2019-09-02 | In 算法 , 编程珠玑

第一章

问题

  • 开始的问题是如何对文件进行排序 -> merge sort
  • 整合问题之后,问题变成了需要对7位数字进行排序,这样的话需要的时间就远小于merge sort了

另一种方法

  • 如果在每个byte里面存一个数字,那么1MB可以存143000左右的号码(e6/7)
  • 但是如果把每个数字表示成一个32位的int(也就是说每7位数存成一个32位的整数,那么这7位数就占4个byte),那么可以存250000左右的号码
  • 从这个角度考虑,快排的速度比merge快

实现

  • 从上面的问题分析来看,用bitmap或者bit vector来表示数据很常见。
    • 比如,可以用一个20bit的string来表示{1,2,3,5,8,13}
    • 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0
    • 在这个里面,出现在集合里的数字就表示为1,没有出现的就表示为0
  • 在实际解决问题过程中,7位数字可以表示成一个小于千万的数。如果用一个千万的二进制串来表示,那么如果整个文件里面有现在的号码的时候,这个位才被表示为1,否则就被表示为0
  • 分为三个阶段
    • 关闭所有的位,即千万个位全都是0
    • 从输入文件里面导入所有的数字,比如2897的话,就是b[2897]=1
    • 全部输入完毕之后,再根据现有存在的数字就可以直接排序,输出了

处理原则

总原则:在开始处理问题之前分析问题,才能让问题更好解决

  • 确定正确的问题 -> 最重要的一点
  • 选择了bitmap的数据结构:选择这个数据结构是根据电话号码不会重复这个特殊条件得到的
  • multi-pass
  • 时间和空间的trade off
  • 简单设计

第二章 算法

问题1:

  • 如果有最多40亿个排好序的32位浮点数,其中有遗漏的数据,如何找到遗漏的数据。考虑内存足够的时候和内存不够的时候的情况
    • 如果内存足够,可以像第一章说的一样,用位图来表示这些数据,然后看哪些没有

如果内存不够?

  • 二分查找
    • 必须定义范围,范围里面每个数字的表示方法和探测方法
    • 比如如果把这些数据分成两部分,比如1-10里面取中位数,因为缺数据的原因,总是会有一边的个数少,那么缺的数据就肯定在少的这边

问题2:

  • 将具有n个元素的向量x左旋i个位置,时间上与n成正比,有十几字节的额外空间
  • 直接方法
    • 储存到额外数组 -> 太浪费空间了
    • 定义一个函数将数组每次移动一个位置 -> 太浪费时间了(虽然时间上和n成正比)
  • 另一个思考
    • 把一个数组分成不同的组,每次把对应组的内容转移,直到所有内容都转移成功。比如把x[0]挪出去,x[3]诺到x[0],x[6]挪到3,然后0挪到6。然后再挪x[1]和他的对应的内容们
  • 另一种思考方法:旋转x实际就是把ab转换成ba
    • 如果a是前i个元素,a比b短,把b分割成b1和b2,让b2和a的长度一样
    • 那么可以先交换a和b2 -> b2 a b1
    • 然后再集中精力交换b1和b2里的元素,也就是说这可以是一个recursive的表示方法
  • 转置:这个看起来在写Leetcode的时候非常好用啊!!!但是注意在python里面reverse要自己写
    • 如果把问题看成转置,实际上数组ab可以
      • 先转置a:aTb
      • 再转置b:aTbT
      • 再转置整个数组:(aTbT)T = ba
    • 也就是说,如果abcdefg想让他旋转三位,实际上可以做到的是
      • reverse(0,2):cbadefg
      • reverse(3,6):cbagfed
      • reverse(0,6):defgabc

问题3

  • 找到一个单词的变位词:比如pots和stop

解决方法

  • 注意,找到所有的可能性是很愚蠢的,比如一个22个字母的词,所有的变位22!大概是10e21,时间爆炸了
  • 核心思想 -> 排序,排序之后的变位词就都一样了
  • leetcode 242,49
    • 这个题的核心思路就是,每个单词按字母顺序排序之后的答案就是这个单词的key,如果两个单词的key一样的话这两个单词就是变位词,如果不一样的话就是新的词
    • 在python里面直接用字典可以很好的储存变位词

第三章 数据结构

数据结构的意义就是让代码可以更加简短整洁 -> 比如用数组代替循环

  • 原则:能用小程序解决的就不要用大程序
    • 把重复性代码改写
    • 封装复杂的结构
    • 尽可能使用高级工具
    • 让数据去构造程序

第四章 正确编写程序

写一个完全正确的binary search吧!

  • 注意点
    • 求中位数的时候是前后相加,除以二
    • 注意跳出循环的条件是 start> end
    • 为了满足上面的循环条件,需要每次判断完mid之后,把start或者end移动一位,不然会陷入死循环
  • 后面的9,11,14会用到程序的验证技术
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Solution:
    def search(self, nums: List[int], target: int) -> int:
    start = 0
    end = len(nums) - 1
    mid = (start + end) // 2

    while start <= end:
    if target == nums[mid]:
    return mid
    elif target > nums[mid]:
    start = mid + 1
    mid = (end + start) // 2
    elif target < nums[mid]:
    end = mid - 1
    mid = (start + end) // 2
    return -1

第五章 次要问题

  • 虽然每次写完了程序,大家基本都会选择把它直接插入系统,然后强烈的希望他能运行
  • (哭了,写的也太真实了)

测试用例

  • 设置极小的测试用例(比如0个,1个,2个元素等等)
  • 设置可以自动生成的测试用例
  • 计时,测试不同方法的时间

调试 -> 引发bug是会有实际的逻辑原因的,调试的时候需要关注这些问题


第六章 性能透视

在后面的三章会说到提高运行效率的三个方法,在第六章主要讲的是各个层次如何组合为一个整体

案例

  • 一个模拟天体间受力关系,来模拟运动的程序,通过对程序的改进,在n=1000的程度下,把速度从一年提升到了不到一天,速度提升系数约为400
  • 改进方法
    • 算法和数据结构,把时间复杂度n2 -> nlogn(二叉树)
    • 算法优化,优化了两个粒子靠的很近的情况
    • 数据结构重组,减少了局部计算的次数
    • 代码优化:64位浮点数改为32位,计算时间减半。用汇编重写了某个函数,给缓慢的函数加速
    • 硬件,提升了硬件
  • 算法加速不一定是独立于硬件的,比如在超级计算机上,树形结构对时间的影响就很小

设计层次

  • 问题的定义
  • 系统结构 -> 第七章,封底估计
  • 算法和数据结构 -> 2,8章
  • 代码优化 -> 9
  • 系统软件
  • 硬件:比如实现某个功能的专门硬件

原则

  • 如果需要少量加速,研究最好的层次。虽然修改算法是非常常见的答案,但是在研究之前最好考虑一下所有可能的层次。比如硬件?这种的,最好能找到一个得到最大加速,又所需精力最少的层次
  • 如果需要大量加速,需要研究多个层次。就像上面的案例一样

封底计算

在处理问题之前,需要对这个问题的规模有一个大概的估计,才能更好的处理问题

帮助封底计算

  • 两个不同方面的答案对比
  • 量纲检测
  • 经验法则
  • 实践

性能估计 + 安全系数

Unity与openCV显示图片

Posted on 2019-08-20 | In Unity , OpenCV

关于opencv库

  • unity带了opencv库,但是这个库是based on java的基础上的,也就是说我继用过opencv的c++和python之后这回要用java了
  • OpenCV for Unity文档
  • 注意:需要在载入opecv的asset之后,把StreamingAssets文件夹移动到Asset里面,需要操作tool--set plugin settings
  • opencv自带了很多example,把这些加入到building setting里面就可以用了

显示图片

首先明确一点,unity里面显示图片没有imshow这种东西,需要把图片的mat转化成texture格式,然后把这个texture加到object上面

  • 在这里我建立了一个plane的object,并且调整了相机的角度,用来显示图片
  • 这部分在start里面进行,也就是现在的图片是静态显示

var

  • var是用来推断这个变量类型,因为var之后直接创建了变量,所以可以推断出来。但是java还是静态语言
  • 这种样子是不行的var foo; foo = "foo";
  • 在for循环里可以

imread

  • 基础功能和以前一样,读取一张图片,存为mat格式
  • 路径中使用了Application.streamingAssetsPath,也就是上文中说到需要移动到asset文件夹里的opencv自带的文件夹。
  • Imgcodecs和Imgproc等都是以前没有接触过的库,如果需要图片正常显示,需要把格式从BGR改成RGB

Texture2D

  • 这个是处理物体表面纹理的一个class,构建新的的时候需要确定这个texture的大小
  • 在这里需要创建一个新的texture2D,才能在之后把mat转到texture里面

Utils.matToTexture2D(dst, tex)

  • 用于mat和纹理的转换,同样也有texture转到mat的方法

GetComponent()

  • 得到这个gameObject的一个部分,尖括号里面的名字取决于现在这个object里面有什么
  • 这里用的是plane,里面自带renderer的属性,并且renderer里面带有material,用来修改构成这个object的材料

总结

  • 用unity显示图片的中心思想就是这个图片变成了object上面的texture,这个图片不能脱离object而独立存在,所以需要首先为这个图片构建object

最终结果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OpenCVForUnity;
using UnityEngine.UI;
using OpenCVForUnity.ImgcodecsModule;
using OpenCVForUnity.ImgprocModule;
using OpenCVForUnity.CoreModule;

public class remove : MonoBehaviour
{
void Start()
{
var dst = Imgcodecs.imread(Application.streamingAssetsPath + "/image.JPG");

Imgproc.cvtColor(dst, dst, Imgproc.COLOR_BGR2RGB);

//Debug.Log(dst.channels());
Texture2D tex = new Texture2D(dst.width(), dst.height(), TextureFormat.RGBA32, false);
OpenCVForUnity.UnityUtils.Utils.matToTexture2D(dst, tex);
gameObject.GetComponent<Renderer>().material.mainTexture = tex;

}



}

OmniProcamUnity文件总结

Posted on 2019-08-19 | Edited on 2019-08-20 | In 研究室 , OmniProcamV2

文件构成

  • Lib
    • libOmniProCam
    • libOmniProCamCalibration
  • OmniProcam
    • Projection
      • Camera
      • ProjectionTarget
      • RenderTexture
      • Shader
    • DebugUI
    • LibOmniProCamManager

其中,在lib里面有calibration用的接口,在里面设定好了投影仪需要的参数数量和相机需要的参数数量。在lib里面直接放了老师写好的dll,所以其实cs文件是在访问这些dll的内容

Camera

  • 目的:初始化相机

变量

  • 创建一个class:cameraInitializer,继承了Monobehaviour
    • MonoBehaviour是每一个unity的script的基础类
  • public的gameobject,用来决定setup哪个相机,这个相机直接从unity的UI里面拽进去
  • protected的camera类,targetcamera
    • projected可以在这个class以及所有继承这个class的里面被访问,但是private只能在这个class中被访问
    • Camera是unity里面一个表示相机的类
  • 创建了两个float的数组,大小和之前设置好的相机参数,和投影仪参数一样
  • 初始化三个4x4的矩阵,分别是相机的intrinsic,extrinsic以及相机的投影矩阵
    • Matrix4x4可以表示transformation的矩阵,包括平移旋转等等

函数

  • void Awake()
    • 功能
      • 在开始之前初始化variable或者game state,在整个stript里面只被call一次
      • 在所有的object初始化结束之后
      • 通常在start之前被call
    • 效果
      • 初始化了calibration
      • 设定好了目标的相机,并且把这个相机setup
  • protected void setupCamera(Camera targetCamera, int cameraIndex)
    • 直接call了dll里面写好的功能(但是这里得到的是projector的,为什么?),得到了各种参数
    • 关于GChandle
    • 然后把distortion和都记录下来了,直接把translation和rotation(相机的外矩阵)赋值给了目标相机、这样目标相机就能直接移动到应该到的位置上了
  • 另外两个函数可以返回这里目前没有用到的distortion k(4个)和c(2个)

device

1234…9
RUOPENG XU

RUOPENG XU

85 posts
58 categories
92 tags
© 2022 RUOPENG XU
Powered by Hexo v3.8.0
|
Theme – NexT.Gemini v7.0.1