0

Kinect で動作する Processing のカラー トラッキング プログラムがあります。写真のどこかをクリックすると、この色が保存され、その周りに楕円が描かれます。myPort.write() を介して 3 つの int 値 (赤、緑、青の 1 つ) を Arduino に送信し、これら 3 つの値を Arduino の 2 つの変数に保存したいだけです。私の目標は、赤の変数が最高の場合は赤の LED を点灯させ、緑の変数が最高の場合は緑の LED を点灯させることです。

グーグルで見つけたいくつかの例を試しましたが、何も機能しません。Arduino が変数の正しい値を取得する方法がわかりません。

編集: ここに私の処理コードがあります。泣きそうになるまで、他のいくつかのチュートリアルからそれを接着しました..

    import processing.serial.*;
Serial myPort;

import SimpleOpenNI.*;

SimpleOpenNI kinect;
// Frame
PImage currentFrame;
color trackColor;

int r1, g1, b1, r2, g2, b2;


void setup()
{
  size(640, 480);

  String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
  myPort = new Serial(this, portName, 9600);

  kinect = new SimpleOpenNI(this);
  kinect.enableRGB();

  trackColor = color (255, 0, 0);
  smooth ();

  currentFrame = createImage (640, 480, RGB);
}

void draw()
{
  kinect.update();

  currentFrame = kinect.rgbImage ();
  image(currentFrame, 0, 0);

  currentFrame.loadPixels();

  // Before we begin searching, the "world record" for closest color is set to a high number that is easy for the first pixel to beat.
  float worldRecord = 500;

  // XY coordinate of closest color
  int closestX = 0;
  int closestY = 0;

  // Begin loop to walk through every pixel
  for (int x = 0; x < currentFrame.width; x ++ ) {
    for (int y = 0; y < currentFrame.height; y ++ ) {
      int loc = x + y*currentFrame.width;
      // What is current color
      color currentColor = currentFrame.pixels[loc];
      r1 = (int)red(currentColor);
      g1 = (int)green(currentColor);
      b1 = (int)blue(currentColor);
      r2 = (int)red(trackColor);
      g2 = (int)green(trackColor);
      b2 = (int)blue(trackColor);

      // Using euclidean distance to compare colors
      float d = dist(r1, g1, b1, r2, g2, b2); // We are using the dist( ) function to compare the current color with the color we are tracking.

      // If current color is more similar to tracked color than
      // closest color, save current location and current difference
      if (d < worldRecord) {
        worldRecord = d;
        closestX = x;
        closestY = y;
      }
    }
  }

  // We only consider the color found if its color distance is less than 10.
  // This threshold of 10 is arbitrary and you can adjust this number depending on how accurate you require the tracking to be.
  if (worldRecord < 10) {
    // Draw a circle at the tracked pixel
    fill(trackColor);
    strokeWeight(4.0);
    stroke(0);
    ellipse(closestX, closestY, 30, 30);
  }




  if (mousePressed == true) {
    color c = get(mouseX, mouseY);
    //println("r: " + red(c) + " g: " + green(c) + " b: " + blue(c));

    // Save color where the mouse is clicked in trackColor variable
    int loc = mouseX + mouseY*(currentFrame.width);

    trackColor = currentFrame.pixels[loc];

 println("red " + r2);
 println("green " + g2);
 println("blue " + b2);

 int colors[] = {r2, g2, b2};

 for(int i=0; i < 3; i++) {
   myPort.write(colors[i]); 
 }

} 
 println("ClosestX " + closestX);
  myPort.write(closestX);
}

そして、いくつかの値を取得する方法がわからない私のArduinoコード。

    int val;
int ledPin = 13;
int freq;
int piezoPin = 9;

int redLED = 3;
int greenLED = 5;
int blueLED = 7;

int red, green, blue;

void setup() {
  pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
  Serial.begin(9600); // Start serial communication at 9600 bps

  digitalWrite(ledPin, LOW);
}

void loop() {
  if (Serial.available() > 0)
  { // If data is available to read,
    val = Serial.read(); // read it and store it in val
}

 if(red > green && red > blue) {
 digitalWrite(redLED, HIGH); //light Red LED
 }

  if(green > red && green > blue) {
 digitalWrite(greenLED, HIGH); //light Red LED
 }

 if(blue > red && blue > green) {
 digitalWrite(blueLED, HIGH); //light Red LED
 }


  //Piezo buzzing higher when X-Position of tracked color is higher. 
  if (val < 100) {
    freq = 50;
  }
  else if (val < 200) {
    freq = 200;
  }
  else if (val < 300) {
    freq = 400;
  }
  else if (val < 400) {
    freq = 600;
  }
  else if (val < 500) {
    freq = 800;    
  }
  else (freq = 1000); 

  tone(piezoPin, freq);

}

EDIT2: はい、LED の点灯に加えて、ピエゾ ブザーから音を出したいのですが、それはかなりうまく機能するので、質問はありません... まだ.

助けてください!!

4

1 に答える 1

0

arduino へのシリアル通信は、一度に 1 バイトで動作します。運が良ければ、Processing Color の 3 つのコンポーネントも 3 バイトです。

  • 赤の 1 つ (0-255)
  • 緑用の 1 つ (0-255)
  • 青の 1 つ (0-255)

必要なのはもう少し情報だけで、それらを別々に保つことができます。

1 バイトの最小値と最大値は 0 ~ 255 であるため、3 つの異なるバイトを追跡するために使用できる安全な文字はありません。そのため、送信する情報の開始位置と終了位置を把握する方法が必要です。

これを行う簡単な方法は、メッセージのヘッダーとフッターを設定することです。何かのようなもの :

<color>[byte (red)][byte (green)][byte (blue)]</color>

このようにフォーマットされたメッセージを読み取って解読する場合は、Processing から受け取った値を格納する小さなバッファーが必要になるため、それらを読み戻して、メッセージ フォーマットと一致するかどうかを確認できます。

したがって、Arduino側では、これが必要です:

String buffer = "";

String messageBegin = "<color>";
String messageEnd = "</color>";


//we read our serial data in the SerialEvent() function
//this is called *after* a loop(), and only if there is serial data in the buffer.
void serialEvent()
{
   while(Serial.available())
   {
       buffer += (char)Serial.read();
   } 
}

void loop() 
{
  //now, inside loop, we no longer need to worry about gathering data from serial.
  //we do still need to figure out if our message is complete, and then parse it.

  //if our buffer contains both the beginning and the end of a message
  //in the right order.
  int beginIndex = buffer.lastIndexOf(messageBegin);
  int endIndex = buffer.lastIndexOf(messageEnd);

  if(beginIndex != -1 && endIndex != -1 && beginIndex < endIndex)
  {
       //we have a complete message!
       //our red color starts 7 characters after where the message begins,
       //because our "messageBegin" is 7 characters long
       string lastMessage = buffer.substring(beginIndex+7);
       //this is arguably not the prettiest way to get our byte values back.
       //see if you can do better for bonus points!
       byte messageAsBytes[80];
       lastMessage.getBytes(messageAsBytes, messageAsBytes.length());

       //we can now finally reconstruct the value we had from processing!
       byte r = (byte)messageAsBytes[0];
       byte g = (byte)messageAsBytes[1];
       byte b = (byte)messageAsBytes[2];

       //if we get a complete message, we can clear our buffer. (don't forget to do this!)
       buffer = "";
  }
}

処理側では、 messagebegin と messageend がライドのために一緒に送信されることを確認するだけです。

myPort.write("<color">);
 for(int i=0; i < 3; i++) {
   myPort.write(colors[i]); 
 }
myPort.write("</color">);
于 2015-09-01T13:59:41.683 に答える