list of markers

Jul 2, 2010 at 4:19 PM
hi! everything seems to work just fine. but i'm getting a load of errors from web-dev-toolbar in firefox. also, it's not working properly on my mac. since i'm no programmer i can only suppose that this concerns the list somehow. the error message: unhandled error in silverlight application. der index lag außerhalb des bereichs. er muss nich negativ und kleiner als die Auflistung sein. (sorry for german - my translation: "the index was out of range. it must not be negative or smaller than the list") my code: IList<Marker> markers = new List<Marker>(); markers.Add(m1); markers.Add(m2); markers.Add(m2); arDetector.Initialize(captureSource, 1, 4000, markers); any ideas?
Coordinator
Jul 2, 2010 at 4:36 PM

Seltsam. ;)

Could you please post the full error message including the stack trace? And the complete code. Please use the "Insert Code Snippet" tool from the toolbar here.

Jul 2, 2010 at 8:48 PM
Edited Jul 2, 2010 at 8:51 PM

 

i'm using silverlight only to detect if there are any markers visible and which...
also: i wasn't able communicate the "name" property of each marker to javascript...that's why i'm simply using the markersize.
here's my c# code:



using
System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using System.Windows.Browser;
using SLARToolKit;
using System.Windows.Media.Media3D;

namespace SL_MarkerRec
{

public partial class MainPage : UserControl
{
CaptureSource captureSource;
CaptureSourceMarkerDetector arDetector;

public MainPage()
{
InitializeComponent();
}

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
// Initialize the webcam
captureSource = new CaptureSource();
captureSource.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();

// Fill the Viewport Rectangle with the VideoBrush
var vidBrush = new VideoBrush();
vidBrush.SetSource(captureSource);
Viewport.Fill = vidBrush;

// Initialize the Detector
arDetector = new CaptureSourceMarkerDetector();

var m1 = Marker.LoadFromResource("1.pat", 64, 64, 21);
var m2 = Marker.LoadFromResource("2.pat", 64, 64, 22);
var m3 = Marker.LoadFromResource("3.pat", 64, 64, 23);
var m4 = Marker.LoadFromResource("4.pat", 64, 64, 24);
var m5 = Marker.LoadFromResource("5.pat", 64, 64, 25);
var m6 = Marker.LoadFromResource("6.pat", 64, 64, 26);

var mCG1 = Marker.LoadFromResource("cg1.pat", 64, 64, 30);
var mCG2 = Marker.LoadFromResource("cg2.pat", 64, 64, 29);
var mCG = Marker.LoadFromResource("CG.pat", 64, 64, 31);
var mCZ = Marker.LoadFromResource("CZ.pat", 64, 64, 32);
var mENTS1 = Marker.LoadFromResource("entspannen1.pat", 64, 64, 33);
var mENTS2 = Marker.LoadFromResource("entspannen2.pat", 64, 64, 34);
var mHYG = Marker.LoadFromResource("hygiene.pat", 64, 64, 35);
var mKOCH = Marker.LoadFromResource("kochen.pat", 64, 64, 36);
var mSCHL = Marker.LoadFromResource("schlafen.pat", 64, 64, 37);
var mARB = Marker.LoadFromResource("arbeiten.pat", 64, 64, 38);
var mRAUM = Marker.LoadFromResource("raumnutzung.pat", 64, 64, 39);
var mPLAY = Marker.LoadFromResource("play.pat", 64, 64, 40);
var mDUM1 = Marker.LoadFromResource("dummy.pat", 64, 64, 41);
var mDUM2 = Marker.LoadFromResource("dummy2.pat", 64, 64, 42);

IList<Marker> markers = new List<Marker>();
markers.Add(m1);
markers.Add(m2);
markers.Add(m2);
markers.Add(m3);
markers.Add(m4);
markers.Add(m5);
markers.Add(m6);
markers.Add(mCG2);
markers.Add(mCG);
markers.Add(mCZ);
markers.Add(mENTS1);
markers.Add(mENTS2);
markers.Add(mHYG);
markers.Add(mKOCH);
markers.Add(mSCHL);
markers.Add(mARB);
markers.Add(mRAUM);
markers.Add(mPLAY);
markers.Add(mDUM1);
markers.Add(mDUM2);

// The perspective projection has the near plane at 1 and the far plane at 4000
arDetector.Initialize(captureSource, 1, 4000, markers);


arDetector.MarkersDetected += (s, me) =>
{
// Change to UI thread in order to manipulate the text control's projection
Dispatcher.BeginInvoke(() =>
{
// Calculate the projection matrix
var dr = me.DetectionResults;

if (dr.HasResults)
{

//SEND TO JAVASCRIPT
//Txt.Text = "1 " + dr_mcr.Marker.Width;

HtmlPage.Window.Invoke("SLCom", new object[] {dr[0].Marker.Width, dr[1].Marker.Width, dr[0].Confidence});


}
});
};
}

private void Button_Click(object sender, RoutedEventArgs e)
{
if (CaptureDeviceConfiguration.RequestDeviceAccess())
{
captureSource.Start();
HtmlPage.Window.Invoke("camPermit");
}
}
}
}



and the error message:

Fehler: Unhandled Error in Silverlight Application Der Index lag außerhalb des Bereichs. Er muss nicht negativ und kleiner als die Auflistung sein.
Parametername: index   bei System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
   bei System.ThrowHelper.ThrowArgumentOutOfRangeException()
   bei System.Collections.Generic.List`1.get_Item(Int32 index)
   bei SLARToolKit.DetectionResults.get_Item(Int32 index)
   bei SL_MarkerRec.MainPage.<>c__DisplayClass2.<UserControl_Loaded>b__1()





 

Coordinator
Jul 2, 2010 at 10:24 PM

The source of your exception is this line:

HtmlPage.Window.Invoke("SLCom", new object[] {dr[0].Marker.Width, dr[1].Marker.Width, dr[0].Confidence});

You are testing using 

if (dr.HasResults)

This only checks if there was one marker detected, but dr[1] is accessing a second marker. You are assuming that there were two markers detected but only test for one! 

You have to test for the count like this in this case:

                    if (dr.Count > 1)
                    {                   
                        //SEND TO JAVASCRIPT
                        //Txt.Text = "1 " + dr_mcr.Marker.Width;

                        HtmlPage.Window.Invoke("SLCom", new object[] {dr[0].Marker.Width, dr[1].Marker.Width, dr[0].Confidence});
                    }

There are some other errors in your code, the last parameter of LoadFromResource is the width of the marker in millimeters. It's used to detect the marker and reconstruct the position and orientation in space, it's not for identification. This is what the name is for!

This is how you will have to use it instead if you want to use "numerical" IDs / names:

            var m1 = Marker.LoadFromResource("1.pat", 64, 64, 80.0, "21");
            var m2 = Marker.LoadFromResource("2.pat", 64, 64, 80.0, "22");
            var m3 = Marker.LoadFromResource("3.pat", 64, 64, 80.0, "23");
            var m4 = Marker.LoadFromResource("4.pat", 64, 64, 80.0, "24");
            var m5 = Marker.LoadFromResource("5.pat", 64, 64, 80.0, "25");
            var m6 = Marker.LoadFromResource("6.pat", 64, 64, 80.0, "26");
I assume you' have set the size of the patterns to the default width of 80.0 millimeters when you created them.

Jul 6, 2010 at 1:37 PM

Thanks so much! that helped! on windows it's running smooth (and almost error-free) now.
unfortunatly on the mac i'm still getting a "unterminated string literal" error (that's the whole error) as soon as silverlight runs.

all this stuff is for my dimploma (design, not programming :P) and since i've got to submit it on friday i started with trying to impliment the last feature i wanted to have.
therefor i need a snapshot and i need it to be uploaded to the server ( so that i can work with it within the website ).

i have all the parts together - unfortunatly it won't work - throwing the error:

Fehler: Unhandled Error in Silverlight Application Auf einen geschlossenen Stream kann nicht zugegriffen werden. bei System.IO.__Error.StreamIsClosed()
bei System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)
bei _2010_06_13.MainPage.PushData(Stream input, Stream output)
bei _2010_06_13.MainPage.<>c__DisplayClass3.<UploadFile>b__2(Object sender, OpenWriteCompletedEventArgs e)
bei System.Net.WebClient.OnOpenWriteCompleted(OpenWriteCompletedEventArgs e)
bei System.Net.WebClient.OpenWriteOperationCompleted(Object arg)
Zeile: 0

 

here's the code (copied from various sources - probably, thats the problem)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using FluxJpeg;
using FluxJpeg.Core;
using FluxJpeg.Core.Encoder;
using System.Windows.Media.Imaging;
using System.IO;



namespace _2010_06_13
{
    public partial class MainPage : UserControl
    {
        CaptureSource captureSource;
       

        public MainPage()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            captureSource = new CaptureSource();
            captureSource.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
            
            var vidBrush = new VideoBrush();
            vidBrush.SetSource(captureSource);
            viewPort.Fill = vidBrush;
        }


        //RANDOM FOR FILENAME


        public class Utils
        {

            static Random _random;



            static Utils()
            {

                _random = new Random();

            }

            public static int RndGen(int min, int max)
            {

                return _random.Next(min, max);

            }
        }



        private void Start_Click(object sender, RoutedEventArgs e)
        {
            if (CaptureDeviceConfiguration.RequestDeviceAccess())
            {
                captureSource.Start();
                captureSource.CaptureImageCompleted += (s, f) =>
                {
                    // Do something with the camera snapshot
                    // e.Result is a WriteableBitmap
                    //Process(f.Result);
 
                    using (Stream Source = JpgEncoder.Encode(f.Result, 50))
                    {
                        //Random Filename
                        int filename = Utils.RndGen(1, 1000000000);
                        string filename2 = filename.ToString();
                        string filename3 = filename2 + ".jpg";
                        
                        UploadFile(filename3, Source);                   
                    }
                    
                };
             }
        }

        private void Snap_Click(object sender, RoutedEventArgs e)
        {
            // CaptureImageAsync fires the CaptureImageCompleted event
            captureSource.CaptureImageAsync();    
        }


        //JPG ENCODER
        public class JpgEncoder
        {
            public static Stream Encode(WriteableBitmap bitmap, int quality)
            {
                //Convert the Image to pass into FJCore
                int width = bitmap.PixelWidth;
                int height = bitmap.PixelHeight;
                int bands = 3;

                byte[][,] raster = new byte[bands][,];

                for (int i = 0; i < bands; i++)
                {
                    raster[i] = new byte[width, height];
                }

                for (int row = 0; row < height; row++)
                {
                    for (int column = 0; column < width; column++)
                    {
                        int pixel = bitmap.Pixels[width * row + column];
                        raster[0][column, row] = (byte)(pixel >> 16);
                        raster[1][column, row] = (byte)(pixel >> 8);
                        raster[2][column, row] = (byte)pixel;
                    }
                }

                ColorModel model = new ColorModel { colorspace = ColorSpace.RGB };

                FluxJpeg.Core.Image img = new FluxJpeg.Core.Image(model, raster);

                //Encode the Image as a JPEG
                MemoryStream stream = new MemoryStream();
                JpegEncoder encoder = new JpegEncoder(img, quality, stream);

                encoder.Encode();

                //Move back to the start of the stream
                stream.Flush();
                stream.Seek(0, SeekOrigin.Begin);
                return stream;
            }
        }

        

        //UPLOAD - "data": da muss das jpg rein
        
        private void UploadFile(string fileName, Stream data)
        {
            UriBuilder ub = new UriBuilder("http://www.raumnutzung2020.de/testing/SLA5/reciever.php");

            ub.Query = string.Format("filename={0}", fileName);
            
  
            WebClient c = new WebClient();
            c.OpenWriteCompleted += (sender, e) =>
            {
                PushData(data, e.Result);
                e.Result.Close();
                data.Close();
            };
            c.OpenWriteAsync(ub.Uri);
        }

        private void PushData(Stream input, Stream output)
        {

            byte[] buffer = new byte[4096];
            int bytesRead;

            while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
            {
                output.Write(buffer, 0, bytesRead);
            }
        }

    }
}

Coordinator
Jul 6, 2010 at 3:00 PM
Edited Jul 6, 2010 at 3:00 PM

This has nothing to do with Windows or Mac. And it has also nothing to do with SLARToolkit at all, but I'm a nice guy and quickly saw the problem. :)

You are uploading the file async to your server, but the source stream was already closed before the async operation was finished. It's closed here (see the comment):

using (Stream Source = JpgEncoder.Encode(f.Result, 50))
{
	//Random Filename
	int filename = Utils.RndGen(1, 1000000000);
	string filename2 = filename.ToString();
	string filename3 = filename2 + ".jpg";
	
	UploadFile(filename3, Source);   
	
} // !!!!! At the end of the using block, stream.Dispose() is called which closes the stream, but OpenWriteCompleted wasn't called before -> ASYNC!

 

Actually one would implement this whole process a bit different because there are too much dependencies and assumptions, but to keep it simple you can just remove the using, since you call stream.Close() in the OpenWriteCompleted event handler in the UploadFile methods.

Stream Source = JpgEncoder.Encode(f.Result, 50);

//Random Filename
int filename = Utils.RndGen(1, 1000000000);
string filename2 = filename.ToString();
string filename3 = filename2 + ".jpg";

UploadFile(filename3, Source);   

 

 

Viel Erfolg mit deiner Diplomarbeit!

-- René Schulte

Jul 6, 2010 at 3:09 PM
Edited Jul 6, 2010 at 3:10 PM
du bist ein genie! vielen vielen dank. mit der ganzen schnellen hilfe [+ SLAR toolkit, of course] hast dir nen eintrag in der "danke an"-section mehr als verdient :) thx agian. & greetz
Coordinator
Jul 6, 2010 at 3:24 PM

No problem. Would be nice if could send me a link / screenshots to the finished app and the diploma thesis when you're done and if it's possible.

Good luck!