public override List<TableObject> DetectRotation(List<TableObject> ObjectList) { DateTime start = DateTime.Now; //No bitmaps -> no rotation detection if (ObjectList.Where(o => o.ExtractedBitmap != null).Count() == 0) return ObjectList; List<TableObject> ObjectsWithBitmap = ObjectList.Where(o => o.ExtractedBitmap != null).ToList(); int objects = ObjectsWithBitmap.Count(); int index = 0; int _threadcount = 0; ManualResetEvent[] resetEvents; //Start 4 threads, only if >= 4 threads if (objects >= 4) { _threadcount = 4; resetEvents = new ManualResetEvent[4]; for (int i=4; i > 0; i--) { Thread t1 = new Thread(new ParameterizedThreadStart(Work)); t1.Name = "ObjectTable RotationDetection Thread #" + i.ToString(); //Copy 1/i*objectcount of the objects to the new thread int amount = (int) Math.Round((1.0/i)*objects); TableObject[] threadobjects = new TableObject[amount]; ObjectsWithBitmap.CopyTo(index, threadobjects, 0, amount); objects -= amount; index += amount; resetEvents[i-1] = new ManualResetEvent(false); t1.Start(new object[] {threadobjects,resetEvents[i-1]}); } WaitHandle.WaitAll(resetEvents); } else { //Single thread _threadcount = 1; ManualResetEvent manualReset = new ManualResetEvent(false); Thread t = new Thread(new ParameterizedThreadStart(Work)); t.Name = "ObjectTable RotationDetection Thread -"; t.Start(new object[] {ObjectsWithBitmap.ToArray(),manualReset}); manualReset.WaitOne(); } //Performance this.RotationDetectionDuration = (int) Math.Round((DateTime.Now - start).TotalMilliseconds); return ObjectList; }
private void CalculateRotation(TableObject obj) { TPoint rPoint = null, bPoint = null; //calculate the average values int x = 0, y = 0; int avRed=0, avGreen=0, avBlue=0; for (x = 0; x < obj.ExtractedBitmap.Width - 2; x++) { for (y = 0; y < obj.ExtractedBitmap.Height - 2; y++) { Color c = obj.ExtractedBitmap.GetPixel(x, y); avRed += c.R; avGreen += c.G; avBlue += c.B; } } int Pixels = obj.ExtractedBitmap.Height*obj.ExtractedBitmap.Width; avRed = (int) Math.Round((double)avRed / Pixels); avGreen = (int)Math.Round((double)avGreen / Pixels); avBlue = (int)Math.Round((double)avBlue / Pixels); //check for every suitable point, whether the point itself and at least 7 direct neighbours are red x = 1; y = 1; //The Points at the border have not enought direct neighbours for (x = 1; x < obj.ExtractedBitmap.Width-2; x++) { for (y = 1; y < obj.ExtractedBitmap.Height - 2; y++ ) { if (rPoint == null) { bool red = true; int count = CountPOints(obj, red, y, x,avRed,avBlue,avGreen); if (count >= 7) rPoint = new TPoint(x, y, TPoint.PointCreationType.screen); } } } //Same for blue point for (x = 1; x < obj.ExtractedBitmap.Width - 2; x++) { for (y = 1; y < obj.ExtractedBitmap.Height - 2; y++) { if (bPoint == null) { bool red = false; int count = CountPOints(obj, red, y, x, avRed, avBlue, avGreen); if (count >= 7) bPoint = new TPoint(x, y, TPoint.PointCreationType.screen); } } } //Were two points recognized? if ((rPoint == null) || (bPoint == null)) return; //Calculate the vector x = rPoint.ScreenX - bPoint.ScreenX; y = rPoint.ScreenY - bPoint.ScreenY; obj.DirectionVector = new System.Windows.Vector(x, y); obj.RotationDefined = true; }
private int CountPOints(TableObject obj, bool red, int y, int x, int avRed, int avBlue, int avGreen) { int count = 0; Color c; //Check 9 points (1 point and 8 neighbours) c = obj.ExtractedBitmap.GetPixel(x, y); if (CheckThreshold(c, red,avRed,avBlue,avGreen)) count++; c = obj.ExtractedBitmap.GetPixel(x + 1, y); if (CheckThreshold(c, red, avRed, avBlue, avGreen)) count++; c = obj.ExtractedBitmap.GetPixel(x - 1, y); if (CheckThreshold(c, red, avRed, avBlue, avGreen)) count++; c = obj.ExtractedBitmap.GetPixel(x, y + 1); if (CheckThreshold(c, red, avRed, avBlue, avGreen)) count++; c = obj.ExtractedBitmap.GetPixel(x, y - 1); if (CheckThreshold(c, red, avRed, avBlue, avGreen)) count++; c = obj.ExtractedBitmap.GetPixel(x - 1, y - 1); if (CheckThreshold(c, red, avRed, avBlue, avGreen)) count++; c = obj.ExtractedBitmap.GetPixel(x + 1, y + 1); if (CheckThreshold(c, red, avRed, avBlue, avGreen)) count++; c = obj.ExtractedBitmap.GetPixel(x - 1, y + 1); if (CheckThreshold(c, red, avRed, avBlue, avGreen)) count++; c = obj.ExtractedBitmap.GetPixel(x + 1, y - 1); if (CheckThreshold(c, red, avRed, avBlue, avGreen)) count++; return count; }
private static void SaveDebugBitmap(int thresholdBlack, short[,] greyArray, int thresholdWhite, TableObject obj) { int x,y; Bitmap bmp = new Bitmap(obj.ExtractedBitmap.Width, obj.ExtractedBitmap.Height); for (x = 0; x < bmp.Width; x++) { for (y = 0; y < bmp.Width; y++) { if (greyArray[x, y] >= thresholdWhite) bmp.SetPixel(x, y, Color.White); else if (greyArray[x, y] <= thresholdBlack) bmp.SetPixel(x, y, Color.Black); else bmp.SetPixel(x, y, Color.Lime); } } bmp.Save("bwrotation_" + obj.ObjectID.ToString() + ".bmp"); }
public object Clone() { TableObject obj = new TableObject(); if (Center != null) obj.Center = Center.Clone(); obj.CenterDefined = CenterDefined; if (ExtractedBitmap != null) obj.ExtractedBitmap = (Bitmap)ExtractedBitmap.Clone(); obj.Height = Height; obj.ObjectID = ObjectID; obj.Radius = Radius; obj.DirectionVector = DirectionVector; obj.RotationDefined = RotationDefined; obj.TrackingStatus = TrackingStatus; obj.TrackingFrameExistence = TrackingFrameExistence; return obj; }
/// <summary> /// Checks wheter the object is on a Menu field. Returns false, too, when the object is on a empty menu field /// </summary> /// <param name="obj"></param> /// <returns></returns> public bool IsOnMenuField(TableObject obj) { //Check for proper initialisation: if not, reinitialize if (_b1 == null) { GetRegions(out _b4, out _b3, out _b2, out _b1); } if (_b1.IsInRegion(obj.Center)) { if (_objectList.Count > 0) return true; } else if (_b2.IsInRegion(obj.Center)) { if (_objectList.Count > 1) return true; } else if (_b3.IsInRegion(obj.Center)) { if (_objectList.Count > 2) return true; } else if (_b4.IsInRegion(obj.Center)) { if (_objectList.Count > 3) return true; } return false; }
private static short[,] ConvertToGreyArray(TableObject obj, out int average) { short[,] greyArray = new short[obj.ExtractedBitmap.Width,obj.ExtractedBitmap.Height]; average = 0; int x, y; for (x = 0; x < obj.ExtractedBitmap.Width; x++) { for (y = 0; y < obj.ExtractedBitmap.Height; y++) { Color c = obj.ExtractedBitmap.GetPixel(x, y); greyArray[x, y] = (short) Math.Round(0.299*c.R + 0.587*c.G + 0.144*c.B); average += (short) Math.Round(0.299*c.R + 0.587*c.G + 0.144*c.B); } } return greyArray; }
public Type GetSimObjectType(TableObject obj) { if (!IsOnMenuField(obj)) return null; //On which menu field int m = GetMenueField(obj); MenuObject mobj = _objectList[_index + m]; //return type return mobj.type; }
/// <summary> /// Returns the number of the menu field (0-3). -1 if the object isnt on a menue filed /// </summary> /// <param name="obj"></param> /// <returns></returns> public int GetMenueField(TableObject obj) { if (_b1.IsInRegion(obj.Center)) { if (_objectList.Count > 0) return 0; } else if (_b2.IsInRegion(obj.Center)) { if (_objectList.Count > 1) return 1; } else if (_b3.IsInRegion(obj.Center)) { if (_objectList.Count > 2) return 2; } else if (_b4.IsInRegion(obj.Center)) { if (_objectList.Count > 3) return 3; } return -1; }
private List<TableObject> GenerateTableObjects(List<ObjectPoint> pointlist, DepthImage image) { List<TableObject> tableobjects = new List<TableObject>(); foreach (ObjectPoint op in pointlist) { TableObject tobj = new TableObject(); tobj.Center = new TPoint(op.X, op.Y, TPoint.PointCreationType.depth); tobj.CenterDefined = true; tobj.Radius = op.RectSize; tobj.Height = image.Data[op.X, op.Y]; tableobjects.Add(tobj); } return tableobjects; }
private void MatchObjects(ref List<TrackObject> TrackObjList, TableObject.ETrackingStatus TrackStatusFilter, double CertainityThreshold, TableObject.ETrackingStatus AssignedStatus = TableObject.ETrackingStatus.NotTracked) { //Calculate the certainity for the selected objects List<int> UsedIDs = CalculateCertainity(ref TrackObjList, TrackStatusFilter); /*//For objects with a very good certainity value, assign objectid foreach (TrackObject to in TrackObjList.Where(obj => obj.TrackCertainity >= CertainityThreshold)) { to.ObjReference.ObjectID = to.BestCertainityWithID; to.ObjReference.TrackingStatus = TrackStatusFilter; //If the assigned TrackStatus is defined, use it if (AssignedStatus != TableObject.ETrackingStatus.NotTracked) to.ObjReference.TrackingStatus = AssignedStatus; }*/ //There might be several objects with the same proposed ID. For each ObjectID, take the object with the best Certainity foreach (int checkID in UsedIDs) { TrackObject maxCertainityRef = null; double maxCertainity = 0.0; //Gett all proposed objs for this ID, and with the minimum required threshold foreach(TrackObject tobj in TrackObjList.Where(obj => obj.BestCertainityWithID == checkID).Where(obj => obj.TrackCertainity >= CertainityThreshold)) { //Take the object with the best Certainity if (tobj.TrackCertainity > maxCertainity) { maxCertainity = tobj.TrackCertainity; maxCertainityRef = tobj; } } //Assign ID to the "best" object if (maxCertainityRef != null) { maxCertainityRef.ObjReference.ObjectID = maxCertainityRef.BestCertainityWithID; maxCertainityRef.ObjReference.TrackingStatus = TrackStatusFilter; //If the assigned TrackStatus is defined, use it if (AssignedStatus != TableObject.ETrackingStatus.NotTracked) maxCertainityRef.ObjReference.TrackingStatus = AssignedStatus; } } }
private List<int> CalculateCertainity(ref List<TrackObject> newFrameObjects, TableObject.ETrackingStatus filter) { //Get only the desired objects List<TableObject> recentObjects = _historyTrackList.GetLastFrame().ObjectList.Where(obj => obj.TrackingStatus == filter).ToList(); //Dont track old objects that are already assigned to new ones (ID) List<int> AlreadyAssignedIDs = new List<int>(); foreach (TrackObject obj in newFrameObjects) { if (obj.ObjReference.ObjectID != 0) AlreadyAssignedIDs.Add(obj.ObjReference.ObjectID); } //Create a List with each ID that will be used List<int> UsedIDs = new List<int>(); //Calculate certainity for each object that isn't tracked foreach (TrackObject to in newFrameObjects.Where(obj =>obj.ObjReference.TrackingStatus == TableObject.ETrackingStatus.NotTracked)) { foreach(TableObject proposedObject in recentObjects) { //Compare each object from the last frame //and calculate the Certainity in % (value from 0 to 1) //distance between objects double distance = proposedObject.Center.DistanceTo(to.ObjReference.Center,TPoint.PointCreationType.depth); //The negative percentage (distance / max distance) is the certainity double certainity = 1 - (distance/MaxDistance); //if this certainity value is better than the saved one, store the new values an the object id for later //but only if the stored object isn't assigned to another object if ((to.TrackCertainity < certainity) && (!AlreadyAssignedIDs.Contains(proposedObject.ObjectID))) { to.TrackCertainity = certainity; to.BestCertainityWithID = proposedObject.ObjectID; if (!UsedIDs.Contains(proposedObject.ObjectID)) UsedIDs.Add(proposedObject.ObjectID); } } } return UsedIDs; }