BowlerKernel
BowlerCamDevice.java
Go to the documentation of this file.
1 package com.neuronrobotics.sdk.bowlercam.device;
2 
3 
4 import java.awt.Color;
5 import java.awt.Graphics2D;
6 import java.awt.image.BufferedImage;
7 import java.io.ByteArrayInputStream;
8 import java.io.IOException;
9 import java.net.MalformedURLException;
10 import java.net.URL;
11 import java.util.ArrayList;
12 
13 import javax.imageio.ImageIO;
14 
15 import com.neuronrobotics.sdk.commands.neuronrobotics.bowlercam.BlobCommand;
16 import com.neuronrobotics.sdk.commands.neuronrobotics.bowlercam.ImageCommand;
17 import com.neuronrobotics.sdk.commands.neuronrobotics.bowlercam.ImageURLCommand;
18 import com.neuronrobotics.sdk.common.BowlerAbstractDevice;
19 import com.neuronrobotics.sdk.common.BowlerDatagram;
20 import com.neuronrobotics.sdk.common.ByteList;
21 import com.neuronrobotics.sdk.common.Log;
22 import com.neuronrobotics.sdk.util.ThreadUtil;
23 
24 // TODO: Auto-generated Javadoc
28 public class BowlerCamDevice extends BowlerAbstractDevice {
29 
31  private ByteList tmp = new ByteList();
32 
34  //private String srvUrl = null;
35  private ArrayList<IWebcamImageListener> imageListeners = new ArrayList<IWebcamImageListener>();
36 
38  private ArrayList<highSpeedAutoCapture> captures= new ArrayList<highSpeedAutoCapture> ();
39 
41  private ArrayList<BufferedImage> images = new ArrayList<BufferedImage>();
42 
44  private ArrayList<String> urls = new ArrayList<String> ();
45 
47  private ArrayList<ItemMarker> mark = new ArrayList<ItemMarker> ();
48 
50  private boolean gotLastMark = false;
51 
57  //private highSpeedAutoCapture hsac = null;
59  if(!imageListeners.contains(l))
60  imageListeners.add(l);
61  }
62 
69  private void fireIWebcamImageListenerEvent(int camera,BufferedImage im){
71  l.onNewImage(camera,im);
72  }
73  }
74 
75  /* (non-Javadoc)
76  * @see com.neuronrobotics.sdk.common.BowlerAbstractDevice#onAllResponse(com.neuronrobotics.sdk.common.BowlerDatagram)
77  */
78  public void onAllResponse(BowlerDatagram data) {
79  // TODO Auto-generated method stub
80 
81  }
82 
91  public BufferedImage getHighSpeedImage(int cam) throws MalformedURLException, IOException {
92  //System.out.println("Getting HighSpeedImage");
93  while(urls.size()<(cam+1) && isAvailable()){
94  Log.info("Adding dummy url: "+urls.size());
95  urls.add(null);
96  }
97  while(images.size() <(cam+1) && isAvailable()){
98  Log.info("Adding dummy image: "+images);
99  images.add(null);
100  }
101  if(urls.get(cam) == null){
102  //System.out.println("URL List element is empty: "+urls);
103  urls.set(cam,getImageServerURL(cam));
104  }
105  try {
106  //System.out.println("Reading: "+urls.get(cam) );
107  ImageReader ir = new ImageReader(cam);
108  ir.start();
109  long start = System.currentTimeMillis();
110  while(((System.currentTimeMillis()-start)<200) && ir.isDone()==false){
111  ThreadUtil.wait(5);
112  }
113  if(!ir.isDone())
114  Log.error("Image read timed out");
115  }catch(Exception ex) {
116  //Log.error("Image capture failed");
117  }
118  return images.get(cam);
119  }
120 
124  private class ImageReader extends Thread{
125 
127  int cam;
128 
130  private boolean done=false;
131 
137  public ImageReader(int cam){
138  this.cam=cam;
139  }
140 
141  /* (non-Javadoc)
142  * @see java.lang.Thread#run()
143  */
144  public void run(){
145  try {
146  images.set(cam,ImageIO.read(new URL(urls.get(cam))));
147  } catch (Exception e) {
148  Log.error("Image Read threw an exception: "+e.getMessage());
149  }
150  done=(true);
151  }
152 
158  public boolean isDone() {
159  return done;
160  }
161  }
162 
163  /* (non-Javadoc)
164  * @see com.neuronrobotics.sdk.common.IBowlerDatagramListener#onAsyncResponse(com.neuronrobotics.sdk.common.BowlerDatagram)
165  */
166  public void onAsyncResponse(BowlerDatagram data) {
167  if(data.getRPC().contains("_img")){
168  ByteList d = data.getData();
169  int camera = ByteList.convertToInt(d.popList(2));
170  int index = ByteList.convertToInt(d.popList(2));
171  int total = ByteList.convertToInt(d.popList(2));
172  byte [] imgData = d.popList(d.size());
173  Log.info("Got image chunk\n"+data+"\nindex: "+index+", total: "+total+", len: "+imgData.length);
174  synchronized(tmp) {
175  tmp.add(imgData);
176  }
177  if(index == (total)){
179  BufferedImage image=null;
180  try {
181  synchronized(tmp) {
182  image = ByteArrayToImage(tmp.getBytes());
183  }
184  } catch (IOException e1) {
185  // TODO Auto-generated catch block
186  e1.printStackTrace();
187  image=null;
188  }
189  synchronized(tmp) {
190  tmp.clear();
191  }
192  images.set(camera, image);
193  fireIWebcamImageListenerEvent(camera,images.get(camera));
194  //System.out.println("Image OK");
195  }
196 
197  }
198  if(data.getRPC().contains("blob")){
199  int x = ByteList.convertToInt(data.getData().getBytes(0, 4));
200  int y = ByteList.convertToInt(data.getData().getBytes(4, 4));
201  int r = ByteList.convertToInt(data.getData().getBytes(8, 4));
202  if(x==0 && y == 0 && r == 0){
203  gotLastMark = true;
204  return;
205  }
206  mark.add(new ItemMarker(x,y,r));
207  }
208 
209  }
210 
218  public boolean updateImage(int chan, double scale){
219  return send(new ImageCommand(chan, scale))==null;
220  }
221 
228  public String getImageServerURL(int chan){
229  //Log.info("Requesting image server URL");
230  while(urls.size() < (chan+1) && isAvailable()){
231  urls.add(null);
232  }
233  if(urls.get(chan) != null)
234  return urls.get(chan);
235  BowlerDatagram b=send(new ImageURLCommand(chan));
236  urls.set(chan,b.getData().asString());
237  return urls.get(chan);
238  }
239 
246  public BufferedImage getImage(int chan) {
247  return images.get(chan);
248  }
249 
257  public void startHighSpeedAutoCapture(int cam,double scale,int fps) {
258  stopAutoCapture(cam);
259  while((captures.size() <= cam)&& isAvailable())
260  captures.add(null);
261  captures.set(cam,new highSpeedAutoCapture(cam,scale,fps));
262  captures.get(cam).start();
263  }
264 
270  public void stopAutoCapture(int cam) {
271  try{
272  captures.get(cam).kill();
273  captures.set(cam,null);
274  }catch (Exception e){}
275  }
276 
287  public boolean updateFilter(Color c, int threshhold,boolean within,int minBlobSize,int maxBlobSize){
288  boolean back = false;
289  try{
290  back = send(new BlobCommand(c, threshhold, within, minBlobSize, maxBlobSize))==null;
291  }catch (Exception e){
292  e.printStackTrace();
293  }
294  return back;
295  }
296 
302  public ArrayList<ItemMarker> getBlobs(){
303  mark.clear();
304  send(new BlobCommand());
305  while(gotLastMark == false && isAvailable()){
306  try {
307  Thread.sleep(10);
308  } catch (InterruptedException e) {
309  // TODO Auto-generated catch block
310  e.printStackTrace();
311  }
312  }
313  return mark;
314  }
315 
319  private class highSpeedAutoCapture extends Thread{
320 
322  int cam;
323 
325  double scale;
326 
328  int mspf;
329 
331  boolean running = true;
332 
340  public highSpeedAutoCapture(int cam,double scale,int fps){
341  this.cam=cam;
342  this.scale=scale;
343  if(fps == 0) {
344  mspf = 0;
345  return;
346  }
347  mspf = (int)(1000.0/((double)fps));
348  //System.out.println("MS/frame: "+mspf);
349  }
350 
351  /* (non-Javadoc)
352  * @see java.lang.Thread#run()
353  */
354  public void run() {
355  //System.out.println("Starting auto capture on: "+getImageServerURL(cam));
356  long st = System.currentTimeMillis();
357  while(running && isAvailable()) {
358  //System.out.println("Getting image from: "+getImageServerURL(cam));
359  try {
360  //System.out.println("Capturing");
361  BufferedImage im =getHighSpeedImage(cam);
362  if(scale>1.01||scale<.99)
363  im = resize(im, scale);
364  if(im!=null){
365  //System.out.println("Fireing");
367  }
368  //System.out.println("ok");
369  } catch (Exception e) {
370  e.printStackTrace();
371  }
372  if(mspf != 0) {
373  long diff = System.currentTimeMillis() - st;
375  if(diff<mspf) {
376  try {
378  Thread.sleep(mspf-diff);
379  } catch (InterruptedException e) {
380  }
381  }
382  st = System.currentTimeMillis() ;
383  }
384  }
385  }
386 
390  public void kill() {
391  //System.out.println("Killing auto capture on cam: "+cam);
392  running = false;
393  }
394  }
395 
403  public BufferedImage resize(BufferedImage image, double scale) {
404  if(image == null)
405  return null;
406  if (scale<.01)
407  scale = .01;
408  int width = (int)(((double)image.getWidth())*scale);
409  int height = (int)(((double)image.getHeight())*scale);
410  BufferedImage resizedImage = new BufferedImage(width, height,image.getType());
411  Graphics2D g = resizedImage.createGraphics();
412  g.drawImage(image, 0, 0, width, height, null);
413  g.dispose();
414  return resizedImage;
415  }
416 
424  public BufferedImage ByteArrayToImage(byte [] array) throws IOException{
425  BufferedImage image = null;
426  image = ImageIO.read(new ByteArrayInputStream(array));
427  return image;
428  }
429 }
void fireIWebcamImageListenerEvent(int camera, BufferedImage im)
boolean updateFilter(Color c, int threshhold, boolean within, int minBlobSize, int maxBlobSize)
BufferedImage resize(BufferedImage image, double scale)
void startHighSpeedAutoCapture(int cam, double scale, int fps)
BowlerDatagram send(BowlerAbstractCommand command)
synchronized boolean add(byte data)
Definition: ByteList.java:149
static final int convertToInt(byte[] b)
Definition: ByteList.java:911
static void info(String message)
Definition: Log.java:110
static void error(String message)
Definition: Log.java:92