Processing 的實際用途有哪些,和哪些硬體有聯繫,分別有哪些介面?相關的硬體學習起來難嗎,需要哪些知識?

上學的時候學過processing,因為能實現一些人機交互所以特感興趣,現在想利用業餘時間搞一搞,就是不知道相關的硬體的方面的知識,希望有知道的能給個意見。


Arduino

攝像頭

Kinect

物聯網 https://pachube.com

都有自帶的庫,官網上搜搜就有

對Processing感興趣的朋友,歡迎來http://www.hudo.it/ 學習與交流


鍵盤和滑鼠

Processing 不僅創建一種可視化數據的簡單方法,而且支持來自滑鼠和鍵盤的用戶輸入。Processing 通過一組函數和回調實現這一點,在獲得用戶輸入時通知 Processing 程序。

鍵盤事件

Processing 提供一小組鍵盤函數,在某個鍵被按下或釋放時通知 Processing 應用程序。您還可以進一步解析該輸入,在事件中將特殊字元呈現給用戶。

可使用 keyPressed 函數來表示一個按鍵操作。您可以在您的應用程序中定義該函數,且當按鍵操作發生時該函數被調用。然後使用回調函數中一個名為 key 的特殊變數來識別用戶按下的那個鍵。類似地,當釋放一個鍵時,您可以使用 keyReleased 函數來捕捉這一事件。注意,兩個函數都產生相同的信息,但是允許您定義何時觸發您的操作。

清單 1 顯示 keyPressed 和 keyReleased 函數。不管在哪個函數中,程序都可以解析兩種用戶按鍵:未編碼的 ASCII 字元和需要編碼的非 ASCII 字元(比如箭頭鍵)。對於編碼的字元,Processing 將 key 變數設置為 CODED 令牌,以表明必須檢查另一個名為 keyCode 的特殊變數。因此,如果 key 不是 CODED,key 變數包含按鍵。如果 key 是 CODED,keyCode 變數包含實際字元:UP、DOWN、LEFT、RIGHT、ALT、CONTROL或 SHIFT。

清單 1. keyPressed 和 keyReleased 回調

void keyPressed()
{
if (key == CODED) {
if (keyCode == DOWN) println("Key pressed: Down arrow");
if (keyCode == SHIFT) println("Key pressed: Shift key");
} else {
println("Key pressed: " + key );
}
}

void keyReleased()
{
if (key == CODED) {
if (keyCode == DOWN) println("Key released: Down arrow");
if (keyCode == SHIFT) println("Key released: Shift key");
} else {
println("Key released: " + key );
}
}

Processing 函數內還有一個特殊的 keyPressed 變數可供使用。keyPressed 函數返回一個布爾值,表示有鍵被按下(True)或無鍵被按下(False)。您可以使用該變數管理 Processing 應用程序內的鍵事件(典型回調結構之外)。

滑鼠事件

滑鼠事件遵循與鍵盤事件類似的一種結構,區別就是有多個函數支持發生的各種基於滑鼠的事件。對於滑鼠事件,可以定義 4 個基本回調:

  • mousePressed
  • mouseReleased
  • mouseMoved
  • mouseDragged

當用戶單擊一個滑鼠按鈕時,mousePressed 回調函數被調用。在回調函數內,您可以通過 mouseButton 變數(LEFT、CENTER、RIGHT)識別特定滑鼠按鈕。當釋放滑鼠按鈕時,mouseReleased 回調函數被調用。mouseClicked(您可以使用的另一個回調函數)可同時調用mousePressed 和 mouseReleased。每次滑鼠移動但未點擊滑鼠按鈕時mouseMoved 函數被調用。最後,當滑鼠移動且點擊滑鼠按鈕時mouseDragged 函數被調用。

另外有大量特殊變數可供使用。首先,mouseX 和 mouseY 變數包含滑鼠的當前位置。您可以使用 pmouseX 和 pmouseY 變數(從前一幀)捕獲滑鼠的前一位置。您可以使用 Processing 應用程序內的 mouseClicked 變數來檢測當前是否點擊了滑鼠按鈕。將該變數與 mouseButton 結合使用來識別當前點擊的按鈕。清單 2 顯示這些回調和特殊變數。

清單 2. 演示基本的滑鼠事件回調

int curx, cury;

void setup() {
size(100, 100);
curx = cury = 0;
}

void mousePressed() {
println( "Mouse Pressed at " + mouseX + " " + mouseY );
if (mousePressed (mouseButton == LEFT)) {
curx = mouseX;
cury = mouseY;
}
}

void mouseReleased() {
println( "Mouse Released at " + mouseX + " " + mouseY );
}

void mouseMoved() {
println( "Mouse moved, now at " + mouseX + " " + mouseY );
}

void mouseDragged() {
println( "Mouse moved from " + curx + " " + cury +
" to " + mouseX + " " + mouseY );
}

這些滑鼠和鍵盤事件為構建 UI 提供基礎。在將對象置於顯示屏上時,您可以使用滑鼠事件函數來識別是否有滑鼠被按下(即當按下滑鼠按鈕時對象區域內的像素是否是滑鼠游標)。

面向對象的編程

Processing 允許使用面向對象編程(OOP)技術來使 Processing 應用程序更易於開發和維護。Processing 本身是面向對象的,但允許開發忽略對象概念的應用程序。OOP 很重要,因為它提供信息隱藏、模塊化和封裝等優勢。

與其他面向對象的語言一樣,Processing 使用 Class 的概念來定義對象模板。通過類定義的對象維護一組數據和可在該數據上執行的相關操作。我們首先看看簡單類的開發,然後擴展該示例,包含該類的多個對象。

Processing 中的類定義一組數據和應用於該數據的函數(或方法)。本例中的數據是在 2-D 空間中具有坐標(xy)和直徑的一個圓。您可以使用 xy 坐標以及值為 1 的直徑來初始化圓,在本例中僅指出圓正在使用中。您可以使用 init 函數提供該信息。隨著時間的推移,圓變大。如果直徑大於 0(表示它是使用的對象),那麼您應當通過遞增其直徑來遞增圓的大小。這個遞增是由 spread 函數提供的。最後,show函數在顯示屏中展示圓。只要直徑大於 0(有效圓),您就可以使用 ellipse 函數創建圓。一旦圓增長到一定大小,您可以將其直徑設置為 0 來取消它。這個類樣例如清單 3 所示。

清單 3. 擴散水滴的類樣例

class Drop {

int x, y; // Coordinate (center of circle)
int diameter; // Diameter of circle (unused == 0).

void init( int ix, int iy ) {
x = ix;
y = iy;
diameter = 1;
}

void spread() {
if (diameter &> 0) diameter += 1;
}

void show() {
if (diameter &> 0) {
ellipse( x, y, diameter, diameter );
if (diameter &> 500) diameter = 0;
}
}

}

現在我們來看一下如何使用 Drop 類來構建一些利用用戶輸入的圖形。清單 4 給出使用 Drop 類的應用程序。第一步是創建一個水滴數組(稱為drops)。之後進行幾個定義(drops 數組中的水滴數和工作索引)。在 setup 函數中,您可以創建顯示窗口並初始化 drops 數組(所有直徑為 0 或未使用)。draw 函數相當簡單,因為水滴的核心功能在類本身內部(清單3中的 spread 和 show)最後,添加 UI 部分,該部分允許用戶定義水滴從何處開始。mousePressed 回調函數通過當前滑鼠位置(目前有一個直徑且是使用過的)初始化水滴,然後遞增當前水滴索引。

清單 4. 構建多個用戶定義水滴的應用程序

Drop[] drops;
int numDrops = 30;
int curDrop = 0;

void setup() {
size(400, 400);
ellipseMode(CENTER);
smooth();
drops = new Drop[numDrops];
for (int i = 0 ; i &< numDrops ; i++) { drops[i] = new Drop(); drops[i].diameter = 0; } } void draw() { background(0); for (int i = 0 ; i &< numDrops ; i++) { drops[i].spread(); drops[i].show(); } } void mousePressed() { drops[curDrop].init( mouseX, mouseY ); if (++curDrop == numDrops) curDrop = 0; }

您可以在圖 1 中從 清單3和 清單4中看到應用程序輸出。滑鼠被點擊了很多次,產生擴散的水滴,如圖所示。

圖 1. 清單 3 和清單 4 中應用程序的顯示窗口

圖像處理

Processing 提供有用且有趣的功能來進行圖像處理。本節探究圖像濾波、融合和對使用像素的用戶定義圖像處理的支持。

圖像濾波

Processing 通過 filter 函數提供預裝的圖像處理功能。該函數向顯示窗口直接應用一種濾波模式。清單 5 顯示一個簡單的 Processing 應用程序內濾波的使用,關聯圖 2 了解各種類型的輸出。注意,在清單 5 中,您僅為 BLUR 執行濾波,但圖 2 中顯示了其他可能性(還有對應的代碼)。

由於 filter 操作顯示窗口的內容,您僅需提供濾波模式(要執行的濾波操作類型)和質量(即濾波模式的參數)。清單 5 首先聲明 PImage 類型,這是存儲圖像的數據類型。接下來,在 setup 函數內,將您的特定圖像載入到 PImage 數據類型(img1)中。載入圖像之後,您就知道了圖像大小,然後據此設置窗口大小(使用 PImage 實例的 width 和 height 屬性)。在 draw 函數內,通過對 image 的一個調用顯示圖像。image 函數要求圖像顯示在顯示窗口,包括圖像左上角的 xy 坐標。(注意,這裡也可以指定圖像的寬度和高度。)最後,執行特定濾波模式 — 在本例中是 BLUR 模式。參見圖 2 了解其他濾波選項,將結果與原始圖像(下面圖 5 中也有提供)進行對比。

清單 5. 一個簡單的濾波應用程序

PImage img1;

void setup() {
img1 = loadImage("alaska1.png");
size(img1.width, img1.height);
smooth();
}

void draw() {
image(img1, 0, 0);
filter(BLUR, 2);
}

如圖 2 所示,Processing 提供一些封裝的圖像處理操作,常見於圖像操作應用程序中。但是您也可以逐像素地操作圖像。

圖 2. 濾波操作示例

這裡沒有顯示其他可能的濾波操作,包括:

  • OPAQUE— 將 alpha 通道設置為不透明
  • ERODE— 基於提供的質量參數減少明亮區域
  • DILATE— 基於提供的質量參數增加命令區域

部分提供有關其他 filter 模式的信息。

圖像融合

圖像可以融合,對於每幅圖像(或圖像區域)一次發生一個像素。該功能模擬 Adobe? Illustrator? 和 Photoshop? 中的一些功能。

清單 6 展示對兩幅圖像的 ADD 融合操作(如圖 3 所示)。如清單中所示,使用 loadImage 載入兩幅圖像,然後使用 ADD 模式將 img2 與 img1融合。在 blend 調用中,指定要與目標圖像(img1)融合的源圖像(img2)。接下來的 4 個參數是源圖像、xy 坐標,以及寬度和高度。緊接的參數是目標圖像的左上角坐標和目標圖像的寬度和高度。最後定義模式參數。在本例中,您請求一個 ADD 混合,它實現操作dest_img_pixel += src_img_pixel*factor (maxed at 255)。

清單 6. 融合圖像

void setup() {
size(237, 178);
smooth();
}

void draw() {
PImage img1 = loadImage("alaska1.png");
PImage img2 = loadImage("alaska2.png");
img1.blend( img2, 0, 0, 237, 178, 0, 0, 237, 178, ADD );
image(img1, 0, 0);
}

其他操作包括 BLEND(不設上限)、SUBTRACT、DARKEST(採用最暗的像素)、LIGHTEST(採用最淺的像素)、MULTIPLY (暗化圖像),等等。參考資料 部分提供其他混合模式信息的鏈接。

圖 3. 混合操作的圖像輸出像素陣列

最後的圖像處理技術採用更手工的方法。在該模式下,您可以逐個操作每個像素。顯示窗口由 color 類型的一個 1-D 陣列組成。顯示圖像後(如清單 7 中的 background 函數所示),您可以通過 loadPixels 函數在顯示窗口中訪問 pixels 陣列中的像素。loadPixels 函數將顯示窗口載入到 pixels 陣列,同時 updatePixels 函數從 pixels 陣列更新顯示窗口。

清單 7. 像素圖的圖像處理

void setup() {
size(237, 178);
smooth();
}

void draw() {
PImage img = loadImage("alaska2.png");
background(img);
loadPixels();
for (int i = 0 ; i &< img.width*img.height ; i++) { color p = pixels[i]; float r = red(p)/2; float g = green(p); float b = blue(p); pixels[i] = color(r, g, b); } updatePixels(); }

雖然顯示窗口在像素陣列中,您可以通過各種方式操作它。清單 7 顯示如何修改顯示,即首先從每個像素(變數 p)創建一個顏色類型實例。您可以使用 red、green 和 blue 函數將該變數進一步分解為單個顏色。在本例中,您在顯示窗口中將圖像的紅色部分對分,然後使用 color 函數將像素載入回來,該函數採用單個顏色並重新構建像素。清單 7 的前後對比如圖 4 所示。

圖 4. 對像素的手動圖像處理

粒子群

我們看一下展示 Processing 功能的一個應用程序 — 特別是 OOP。該例來自數值優化和機器學習。

Particle swarms 是自然激發的一個優化技術。它使用大量候選解決方案(粒子),其移動由搜索空間中找到的最佳解決方案(粒子局部最佳解決方案和全局最佳解決方案)所引導。粒子群優化(PSO)很簡單,且提供對搜索空間的有趣的可視化表示,使其成為探究數據可視化語言的理想之選。粒子群跨 2-D 空間移動,尋求全局最優效果。

優化技術

粒子群是一種有趣的新優化方法,有助於函數優化,且提供有趣的可視化呈現。還有具有類似功能的大量其他方法存在,比如蟻群優化,該方法使用蟻群來解決路徑查找問題,還有遺傳演算法,它使用大量候選解決方案來解決常規問題。

PSO 實現

PSO 的 Processing 實現由兩種類組成。第一種類是 Particle 類,它實現單個粒子。按照 PSO,每個粒子維護其當前位置、速度、當前和最佳適用性,以及最佳粒子解決方案(參見清單 8)。Particle 類提供大量方法來支持 PSO,包括一個構造函數(隨機地將粒子放在搜索空間)、一個計算適用性的函數(在本例中是 sombrero 函數,其中適用性是 z)、一個update 函數(基於當前速度向量移動粒子)以及在搜索空間中顯示粒子的一個 show 函數。還有其他三個 helper 函數,將粒子的元素呈現給用戶(適用性以及 xy 位置)。

清單 8. PSO 的 Particle 類

class Particle {

float locX, locY;
float velX = 0.0, velY = 0.0;
float fitness = 0.0;
float bestFitness = -10.0;
float pbestX = 0.0, pbestY = 0.0; // Best particle solution
float vMax = 10.0; // Max velocity
float dt = 0.1; // Used to constrain changes to each particle

Particle() {
locX = random( dimension );
locY = random( dimension );
}

void calculateFitness() {
// Clip the particles
if ((locX &< 0) || (locX &> dimension) ||
(locY &< 0) || (locY &> dimension)) fitness = 0;
else {
// Calculate fitness based on the sombrero function.
float x = locX - (dimension / 2);
float y = locY - (dimension / 2);
float r = sqrt( (x*x) + (y*y) );
fitness = (sin(r)/r);
}

// Maintain the best particle solution
if (fitness &> bestFitness) {
pbestX = locX; pbestY = locY;
bestFitness = fitness;
}
}

void update( float gbestX, float gbestY, float c1, float c2 ) {
// Calculate particle.x velocity and new location
velX = velX + (c1 * random(1) * (gbestX - locX)) +
(c2 * random(1) * (pbestX - locX));
if (velX &> vMax) velX = vMax;
if (velX &< -vMax) velX = -vMax; locX = locX + velX*dt; // Calculate particle.y velocity and new location velY = velY + (c1 * random(1) * (gbestY - locY)) + (c2 * random(1) * (pbestY - locY)); if (velY &> vMax) velY = vMax;
if (velY &< -vMax) velY = -vMax; locY = locY + velY*dt; } void show() { point( (int)locX, (int)locY); } float pFitness() { return fitness; } float xLocation() { return locX; } float yLocation() { return locY; } }

接下來是粒子群的類(參見清單 9),該類維護一個 Particles 數組(在粒子群構造函數中創建和初始化)、當前的全局最佳解決方案(xy 坐標)以及兩個學習因子。學習因子度量粒子是否應圍繞局部最佳解決方案(c2)或全局最佳解決方案(c1)成群移動(搜索)。每個因子指示將最佳解決方案應用於粒子的影響。

run 方法執行一步 PSO 模擬。首先,它計算每個粒子在粒子群中的適用性。然後查找全局最佳解決方案。有了這個信息之後,它調用 update來移動粒子,調用 show 來展示粒子群中的粒子。

清單 9. PSO 的粒子群類

class Swarm {

float gbestX = 0.0, gbestY = 0.0; // Global best solution
float c1 = 0.1, c2 = 2.0; // Learning factors

Particle swarm[];

Swarm() {
swarm = new Particle[numParticles];
for (int i = 0 ; i &< numParticles ; i++) { swarm[i] = new Particle(); } } void run() { // Calculate each particle"s fitness for (int i = 0 ; i &< numParticles ; i++) { swarm[i].calculateFitness(); } findGlobalBest(); // Update each particle and display it. for (int i = 0 ; i &< numParticles ; i++) { swarm[i].update( gbestX, gbestY, c1, c2 ); swarm[i].show(); } } void findGlobalBest() { float fitness = -10.0; for (int i = 0 ; i &< numParticles ; i++) { if (swarm[i].pFitness() &> fitness) {
gbestX = swarm[i].xLocation(); gbestY = swarm[i].yLocation();
fitness = swarm[i].pFitness();
}
}
}

void showGlobalBest() {
println("Best Particle Result: " + gbestX + " " + gbestY);
}

}

最後,使用這裡定義的類的用戶應用程序如清單 10 所示。這個應用程序為 PSO 定義一些可配置項,比如粒子數量、顯示窗口的大小(dimension)以及粒子群本身。setup 函數準備窗口和顏色,draw 執行對粒子群的調用,每 10 次迭代發出一次全局解決方案。由於該模擬使用 sombrero 函數實現優化,最佳效果是顯示的中心。

清單 10. 驅動 PSO 的應用程序

// Particle Swarm Optimization
int numParticles = 200;
int iteration = 0;
float dimension = 500;
Swarm mySwarm = new Swarm();

void setup() {
background(255);
fill(0);
size( int(dimension), int(dimension));
smooth();
}

void draw() {
background(255); // remove for trails
mySwarm.run();
if ((iteration++ % 10) == 0) mySwarm.showGlobalBest();
}

下面兩幅圖展示 Processing 中 PSO 模擬的輸出。圖 5 顯示 PSO 的時滯,而圖 6 顯示帶有軌跡的 PSO,識別粒子的最優路徑。

圖 5. PSO 模擬的時滯

從圖 6 中所示的軌跡可以很容易地看到粒子路徑,因為它們向中心處的最優解決方案聚合。您可以看到一些路徑中的閉環,這表示粒子在繼續向全局最優效果移動之前雲集了其最佳本地解決方案。

圖 6. PSO 模擬的軌跡

應用程序轉換

回顧 第 1 部分,Processing 代碼在執行之前被轉換為 Java 語言,使得將一個 Processing 應用程序轉化為一個 Java applet 或應用程序變得很容易。要執行該轉換,單擊 Processing Development Environment (PDE) 中的 File,然後單擊 Export 導出一個 applet,或單擊 Export Application 導出一個 Java 應用程序。然後 Sketchbook 目錄將包含代碼和該操作的相關文件。清單 11 展示導出的 applet(applet 子目錄)、導出的應用程序(出於特定目標的三個應用程序目錄)以及源本身(pso.pde)。

清單 11. 導出後的 Processing Sketchbook 子目錄

mtj@ubuntu:~/sketchbook/pso$ ls
applet application.linux application.macosx application.windows pso.pde

在 applet 子目錄中,您可以找到 Processing 源碼、轉換後的 Java 源碼、JAR 和 index.html 文件樣例,來查看結果。

原文作者M. Tim Jones

原文地址http://www.ibm.com/developerworks/cn/opensource/os-datavis2/


硬體的話是 Arduino


http://vdisk.weibo.com/s/QJnn

http://vdisk.weibo.com/s/PfK3

for you information


推薦閱讀:

TAG:硬體埠 | 硬體拆解 | Processing編程語言 |