利用Kinect將投影變得可直接用手操控

Finally

總算是到了這一天了!假期里算法想不出來,或者被BUG折磨得死去活來的時候,總是YY著什么時候能心情愉快地坐在電腦前寫一篇項目總結,今天總算是抽出時間來總結一下這神奇的幾個月。

現在回過頭來看,上學期退出ACM集訓隊果然是對的,這次開發學到的東西太多太多,以前在ACM的時候,感覺不會的東西好多啊,真正來自己試著開發個東西,發現不會的東西果然好多。不過要是幾個老師知道我上午給新生做完ACM宣講報告下午就跟教練說退出,他們會是什么心情啊哈哈。

這些是第一次嘗試開發,如果ACM是練內功的話,那么練了三年也總該讓我拿出來用用了,不然學了三年還是只在個控制臺里玩甚是寂寞,自己親手從無到有創造出一個東西來的感覺, 實在太爽了!

先說一下這次項目印象最深的幾個教訓:

  1. 功能一旦變得復雜,就一定要在紙上先畫一畫!
    • 流程圖也好,大體思路圖也行,甚至隨手演算的過程都可以,總之一定要把思路理清楚了,思路不清的后果就是代碼越寫越亂,最后只能全部推倒重來,事先不畫圖省下的時間遠遠比不上最后重寫所浪費的時間。
  2. 命名一定要規范
    • 以前刷題的時候,也知道命名規范的重要性,只是沒想到會如此重要。之前我的代碼風格還算不錯,不過一開始寫的時候還偷下懶,省掉一兩個單詞之類,有時心急了還直接用原來的命名方法,用下劃線分割單詞(Kinect的API里都是用大小寫分割單詞的),這樣寫的弊端就是代碼也是越來越亂,而且一旦有事中斷了幾天,回來再看代碼就發現看不懂了,于是又簡單粗暴推倒重來。所以一定要有一套自己的命名風格,而且不要為了省事少些那一兩個單詞,敲個長變量名所帶來的是代碼的高可讀性,多耗費的時間遠遠小于以后推倒重來所浪費的時間!
  3. 不寫不必要的注釋
    • 到處都是注釋,反而大大降低了可讀性,一眼看去全是綠的,頭都暈了,開發中期我就被自己那么多的注釋弄得看見綠代碼就想吐,后期只注釋主要功能,提高抽象程度,代碼反而變得清晰有邏輯。所以那種基本每行都有注釋的風格,我并不認同,當然,我說的是代碼基本僅供自己一個人看的情況。
  4. 最好進行版本控制
    • 有一次就是,我做了個比較微小的改動,結果怎么調都不對,也已經忘了改動之前是什么狀態,簡直是有種欲哭無淚的感覺。還有就是進行一個大的改動之后,突然發現之前的那個版本才是對的(哭)。有個版本控制機制的話,這種情況應該能避免很多。
  5. 迭代開發似乎是個不錯的辦法
    • 之前在知乎上看到一個貼,講的是新手應該怎樣進行開發,提到的一種思路就是進行迭代開發。一開始可能什么都不懂,然后著手做了一部分之后,就對項目有了個大概的輪廓,然后推翻進行新的一輪開發,這時又對未來該怎么做有更清晰的了解,這樣不斷迭代把項目逐步推向成熟。我是迭代了4次之后出了目前這個基本完成的版本,不過在寫的時候沒刻意考慮過用這種方法,之所以迭代了4次是因為上面提到的種種原因導致推翻重來(捂臉),不過現在看來這種方法好像真的很合理。

項目介紹

好了,現在正式開始介紹一下項目本身。

背景

這個項目原本是用來參加2016年的微軟創新杯,但是在上一周,也就是3月20號的四川省區域賽中未獲獎,只能直接參戰中國區半決賽。這次區域賽失敗的原因有很多,雖然作品已經完成得差不多了,但是沒能優秀地將其展示出來,在現成演示的時候還遇到了一個巨大失誤,中途才發現,所以沒等通知結果就知道多半是悲劇了。第一次參加這類開發類的比賽,就當交學費好了,不過這次區域賽給我的感覺是,微軟還是想找幾個最有商業前途的作品,這個項目炫是很炫酷,但是實際意義不大的樣子,所以感覺中國區半決賽希望也不大。不過無所謂啦,我自己玩得嗨就行了,微軟欣不欣賞那是另外一回事,說不定哪天我就搭建出個鋼鐵俠那樣的實驗室不是?啊哈哈,最近也順便把這個項目報成了大學生創新創業訓練計劃,成功申請到國家級,算是可以安慰一下。

目標

簡單來說,此項目就是要把投影儀投出的投影變得可以直接用裸手操控,就好像投影變成了一塊大型的平板電腦,投影可以是在投影幕上、墻上甚至桌子上,任何光滑且不是反射材質的平面都行,至于為什么不能是反射材質,等下會有介紹。剛開始是計劃達到能用手指直接在投影上寫字的精度,后來發現很難做到,瓶頸在于指尖的識別算法不夠精確,這是我自己構思的一個簡單算法,未來應該會用更高級更精確的算法來替代。

開發環境

Kinect for Windows V2?+?Kinect SDK 2.0?+?OpenCV 3.0?+?Visual Studio Community 2015

Kinect

項目里利用到的一個非常重要的東西就是Kinect for Windows V2,一款微軟的動作感應器,可以算成是一類現實增強設備,發布時主要是搭配XBox來玩體感游戲,但是這么厲害的一個東西只能用來玩游戲實在太可惜,所以微軟在前幾天發布了它的Windows版本,讓它能夠在PC上進行開發。就是下面這么個東西:

原理

原理其實并不算難,主要可以參考下面這張圖。

  1. 從Kinect獲取的整個畫面中識別出投影
    • 因為操作要在投影上進行,所以需要先識別出投影是畫面中的哪一塊,這里用的算法比較簡單,先投一副純色圖像出來,然后利用投影區RGB值近似的原理,找出投影的左下角和右上角之后就確定了投影的區域,這樣做的缺點是投影區只能是矩形而且不能太歪。其實有時間的話,可以試一下利用9*9的矩陣來找出所有屬于邊緣的點,然后渲染所有邊緣點,也就找出了整個邊緣,這樣可以適應任意形狀。
  2. 從Kinect獲取的整個畫面中識別出指尖
    • 因為用手指來調用鼠標進行操作,而接觸屏幕的地方又是手指的指尖,所以需要識別出指尖。

    一開始我是基于KinectBodyIndex這個數據源來尋找指尖,首先定位出腕關節在哪,然后根據腕關節的位置向上尋找復合指尖特征的點,可以說效果很好,識別非常精確和穩定,而且能同時識別出5個指尖,這部分是我在假期里完成的,本來以為來到學校后將程序根據投影儀調整下就差不多可以用了,然而到校測試后才發現一個致命的問題,就是當手臂貼近墻壁時,整個手臂的BodyIndex數據都丟失了。因為微軟似乎認為,如果某個點要是屬于人體的話,那么它和背景的深度差至少要有二三十厘米左右(正好是人體的厚度)。這個問題讓我失眠了幾晚上...不過也是在失眠的時候想出了現在用的解決方法。ds

    現在用的方法是基于`Depth`數據來找指尖的,簡單來說就是根據指尖的特點找出所有吻合的點,然后取 位置最高的那個(因為操作的時候用的基本都是一根手指),這樣做可以減少很多工作量,因為很多非法點都直接被略去了。
  3. 將手指的位置映射成鼠標的位置
    • 因為想達到手指指哪,鼠標就點擊哪的效果,所以必須把手指在投影上的位置,映射成鼠標在電腦里相應的位置,這個其實簡單推導一下就可以得出。

      黑色框為投影屏幕,大寫的X和Y代表的是屏幕的寬和高,紅色框為電腦屏幕,假設人的手指在的位置,如果想將鼠標也映射到同樣的位置,那么就有??的等比關系成立。這里投影屏幕的寬和高在上面第一步中獲取,而電腦屏幕的寬和高,實際上是不需要考慮分辨率的,因為在鼠標的坐標系下,電腦的寬和高都被分成了65535個單位,所以寬和高可以視為65535。根據這些,就可以算出的值來。

  4. 根據手指到屏幕的距離,判斷點擊和非點擊兩種狀態
    • Kinect是帶有深度攝像頭的,也就是說它能夠知道畫面中的每一點到它的距離。似乎是利用三組紅外發射器來實現,所以也就要求物體不能是反射材質,不然會獲取不到距離。因為能夠知道屏幕的距離,也能知道手指的距離,所以如果手指距離屏幕足夠近,那么就可以判斷為點擊。但是,屏幕有可能不是絕對垂直的,Kinect也有擺歪的可能性,同時深度數據也不是100%精確,所以在計算屏幕距離時,需要考慮一個容錯值,在這個范圍內都被視為屏幕,在這里我設置的值是10cm,雖然看上去很多,但是實際效果還不錯。但是,這也帶來一個很嚴重的問題,就是手指在離屏幕的位置小于10cm的時候,也被視為了屏幕,這時候指尖就丟失了,手指變成了手指中部(因為手指不是完全平行于墻面的,而是有一定角度,所以指根的地方距離屏幕更遠),這就會產生很不穩定的現象,至今沒有解決。

上面就是核心的功能,除此之外,還要加入一些鼠標的抖動消除、誤差消除的處理,同時我還調用了Kinect的手勢識別功能,直接用手勢來完成撤銷的操作。這段時間忙著找實習,以后有時間的話,應該會優化指尖識別的算法,同時加入更多的手勢來調用操作。

效果展示

(博客園的MarkDown居然不可以插視頻,差評)

演示視頻在這里

直接在墻上玩割繩子:

用手在墻上書寫(外加用手勢來調用撤銷):

直接裸手操控PPT:

END

這個項目差不多就這么多啦,剩下的只是優化下各個功能,或者加點新東西進去。從假期里就構思了一個比較有意思的小程序,等這段時間忙結束,應該就會把它敲出來。真是越來越好玩了!

轉載于:https://www.cnblogs.com/czaoth/p/6027449.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/394751.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/394751.shtml
英文地址,請注明出處:http://en.pswp.cn/news/394751.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

my-medium.cnf_您的手機如何打開medium.com-我將讓門衛和圖書管理員解釋。

my-medium.cnfby Andrea Zanin由Andrea Zanin 您的手機如何打開medium.com-我將讓門衛和圖書管理員解釋。 (How your phone opens medium.com — I’ll let a doorman and a librarian explain.) Hey did you notice what just happened? You clicked a link, and now here y…

springboot自動配置的原理_SpringBoot自動配置原理

SpringBoot的啟動入口就是一個非常簡單的run方法,這個run方法會加載一個應用所需要的所有資源和配置,最后啟動應用。通過查看run方法的源碼,我們發現,run方法首先啟動了一個監聽器,然后創建了一個應用上下文Configurab…

Django first lesson 環境搭建

pycharm ide集成開發環境 (提高開發效率) 解釋器/編譯器編輯器調試環境虛擬機連接 設置VirtualBox端口 操作1 操作2 點擊號添加,名稱為SSH,其中主機端口為物理機的端口,這里設置為1234,子系統端口為虛擬機的…

《Drupal實戰》——3.3 使用Views創建列表

3.3 使用Views創建列表 我們接著講解Views的設置,首先做一個簡單的實例。 3.3.1 添加內容類型“站內公告” 添加一個內容類型“站內公告”,屬性配置如表3-1所示。 為該內容類型設置Pathauto的模式news/[node:nid],并且我們在這里將節點類型…

c語言函數編正切余切運算,淺談正切函數與余切函數的應用

九年義務教育三年制初級中學“數學”課本中,對正切函數和余切函數的定義是這樣下的:在RtABC中,∠C=90,a&#…

wget命令下載文件

wget -r -N -l -k http://192.168.99.81:8000/solrhome/ 命令格式: wget [參數列表] [目標軟件、網頁的網址] -V,–version 顯示軟件版本號然后退出; -h,–help顯示軟件幫助信息; -e,–executeCOMMAND 執行一個 “.wgetrc”命令 -o,–output…

idea mybatis generator插件_SpringBoot+MyBatis+Druid整合demo

最近自己寫了一個SpringBootMybatis(generator)druid的demo1. mybatisgenerator逆向工程生成代碼1. pom文件pom文件添加如下內容,引入generator插件org.mybatis.generator mybatis-generator-maven-plugin 1.3.5 mysql …

vr格式視頻價格_如何以100美元的價格打造自己的VR耳機

vr格式視頻價格by Maxime Coutte馬克西姆庫特(Maxime Coutte) 如何以100美元的價格打造自己的VR耳機 (How you can build your own VR headset for $100) My name is Maxime Peroumal. I’m 16 and I built my own VR headset with my best friends, Jonas Ceccon and Gabriel…

python_裝飾器

# 裝飾器形成的過程 : 最簡單的裝飾器 有返回值得 有一個參數 萬能參數# 裝飾器的作用# 原則 :開放封閉原則# 語法糖:裝飾函數名# 裝飾器的固定模式 import time # time.time() # 獲取當前時間 # time.sleep() # 等待 # 裝飾帶參數的裝飾器 def timer…

歐洲的數據中心與美國的數據中心如何區分?

人會想到這意味著,在歐洲和北美的數據中心的設計基本上不會有大的差異。不過,一些小的差異是確實存在的。您可能想知道為什么你需要了解歐洲和北美的數據中心之間的差異,這對你的公司有幫助嗎?一個設計團隊往往能從另一個設計團隊那里學到東…

老農過河

java老農過河問題解決 http://www.52pojie.cn/thread-550328-1-1.html http://bbs.itheima.com/thread-141470-1-1.html http://touch-2011.iteye.com/blog/1104628 轉載于:https://www.cnblogs.com/wangjunwei/p/6032602.html

python isalnum函數_探究Python中isalnum()方法的使用

探究Python中isalnum()方法的使用 isalnum()方法檢查判斷字符串是否包含字母數字字符。 語法 以下是isalnum()方法的語法: str.isa1num() 參數 NA 返回值 如果字符串中的所有字符字母數字和至少有一個字符此方法返回 true,否則返回false。 例子 下面的例…

docker快速入門_Docker標簽快速入門

docker快速入門by Shubheksha通過Shubheksha Docker標簽快速入門 (A quick introduction to Docker tags) If you’ve worked with Docker even for a little while, I bet you’ve come across tags. They often look like “my_image_name:1” where the part after the col…

動態規劃算法——最長上升子序列

今天我們要講的是最長上升子序列(LIS)。【題目描述】給定N個數,求這N個數的最長上升子序列的長度。【樣例輸入】      【樣例輸出】7        42 5 3 4 1 7 6那么什么是最長上升子序列呢? 就是給你一個序列…

如何快速掌握一門新技術/語言/框架

IT行業中的企業特點是都屬于知識密集型企業。這種企業的核心競爭力與員工的知識和技能密切相關。而如果你在企業中扮演的是工程師的角色的話,那么 你的核心競爭力就是IT相關的知識與技能的儲備情況。而眾所周知,IT行業是一個大量產生新知識的地方&#x…

c語言今天星期幾問題,C語言輸入今天星期幾

滿意答案迷茫03222015.07.24采納率&#xff1a;55% 等級&#xff1a;9已幫助&#xff1a;665人123456789101112131415161718192021#include<stdio.h>int main(void){ enum weekday{ sun, mon, tue, wed, thu, fri, sat }; int n; printf("輸入星期數(0-…

備忘錄模式 詳解

定義 在不破壞封裝性的前提下&#xff0c;捕獲一個對象的內部狀態&#xff0c;并在該對象之外保存這個狀態&#xff1b; 行為型模式 角色 發起人角色&#xff08;Originator&#xff09;&#xff1a;記錄當前時刻的內部狀態&#xff0c;負責定義哪些屬于備份范圍的狀態&#xf…

dll oem證書導入工具_技術干貨 | 惡意代碼分析之反射型DLL注入

歡迎各位添加微信號&#xff1a;qinchang_198231 加入安全 交流群 和大佬們一起交流安全技術01技術概要這是一種允許攻擊者從內存而非磁盤向指定進程注入DLL的技術&#xff0c;該技術比常規的DLL注入更為隱蔽&#xff0c;因為除了不需要磁盤上的實際DLL文件之外&#xff0c;它…

像程序員一樣思考_如何像程序員一樣思考-解決問題的經驗教訓

像程序員一樣思考by Richard Reis理查德里斯(Richard Reis) 如何像程序員一樣思考-解決問題的經驗教訓 (How to think like a programmer — lessons in problem solving) If you’re interested in programming, you may well have seen this quote before:如果您對編程感興趣…

CF908G New Year and Original Order 數位DP

傳送門 看到數據范圍到\(10^{700}\)毫無疑問數位DP。那么我們最重要的問題是如何有效地維護所有數位排序之后的數的值。 對于某一個數\(x\)&#xff0c;設\(f_{x,i} (i \in [1,9])\)表示\(x\)中的所有數位的值\(\geq i\)的數位數量&#xff0c;比如說\(f_{6345982 , 7} 2 , f_…