void Save() { SlotScript ss = (SlotScript)target; // Create subfolder if it doesn't exist yet if (!Directory.Exists(subFolder)) { Directory.CreateDirectory(Application.dataPath + "/" + subFolder); } isOverWriteOperation = File.Exists(filename); using (StreamWriter sw = new StreamWriter(filename)) { for (int iRow = 0; iRow < ss.slotData.numberOfRows; ++iRow) { // Write row title sw.WriteLine("Row " + (iRow + 1)); SlotData.Row row = ss.slotData.rows[iRow]; for (int iSlot = 0; iSlot < row.numberOfSlots; ++iSlot) { // Write slot title sw.WriteLine(" Slot " + (iSlot + 1)); SlotData.Slot slot = row.slots[iSlot]; // Write pixel threshold level sw.WriteLine(" " + slot.pxThresholdLevel); foreach (SlotData.Cornerpoint cp in slot.areaCornerpoints) { // Write cornerpoint coordinates sw.WriteLine(" " + cp.x + " " + cp.y); } } } // for } // using }
public int GetTotalSlotCount() { int slotCount = 0; // Go through slot data for each processing camera and retrieve // the total number of slots the cameras have been setup to track for (int iCam = 0; iCam < numCams; ++iCam) { for (int iRow = 0; iRow < slotData[iCam].numberOfRows; ++iRow) { SlotData.Row row = slotData[iCam].rows[iRow]; for (int iSlot = 0; iSlot < row.numberOfSlots; ++iSlot) { SlotData.Slot slot = row.slots[iSlot]; if (!slot.IsUndefined()) { ++slotCount; } } } } return(slotCount); }
public void ExtractSlots() { // Take snapshots of binary edge detection image and // read pixels and their colors from areas of interest //////////////////////////////////////////////////////// // Go through processing cameras for (int iCam = 0; iCam < numCams; ++iCam) { if (showDebugInfo) { Debug.Log("=========== " + transform.GetChild(iCam).name + " ==========="); } // Mark renderTexture active so that Texture2D.ReadPixels() // will get pixels from it instead of the entire viewport. Transform tShaderPlanes = transform.GetChild(iCam).GetChild(1); RenderTexture.active = (RenderTexture)tShaderPlanes. GetChild(tShaderPlanes.childCount - 3).GetChild(0). GetComponent <Renderer>().material.mainTexture; for (int iRow = 0; iRow < slotData[iCam].numberOfRows; ++iRow) { SlotData.Row row = slotData[iCam].rows[iRow]; for (int iSlot = 0; iSlot < row.numberOfSlots; ++iSlot) { SlotData.Slot slot = row.slots[iSlot]; if (slot.IsUndefined()) { // Slot corner points unassigned -> stop continue; } // Get a bounding rect to define the target texture dimension Rect boundingRect = slot.GetBoundingRect(); // Create a texture matching bounding rect dimensions slot.colorTexture = new Texture2D((int)boundingRect.width, (int)boundingRect.height); // Turn user-provided cornerpoint rect Y coordinates (texture top edge // Y == 0) into OpenGL coordinate space (texture bottom edge Y == 0) SwapY(ref boundingRect, transform.GetChild(iCam).GetSiblingIndex()); // Read pixels into texture memory slot.colorTexture.ReadPixels(boundingRect, 0, 0); // Retrieve pixel RGBA components Color32[] colorData = slot.colorTexture.GetPixels32(); /* * Pixel In Polygon algorithm: * - Search the bounding rectangle of the detection area quadrilateral. * In each Y position, traverse horizontally across the width of the * rectangle, a line at a time. If at any point the pixel under scrutiny * has crossed - from left to right - an uneven number of detection * area edge lines, it must be within the detection area. In such case, * if the color in that location is white, consider a hittest a success. */ // Construct line data from detection area corner points List <Line> lines = new List <Line>(); for (int iCp = 0; iCp < slot.areaCornerpoints.Length; ++iCp) { // Get each adjacent corner point pair SlotData.Cornerpoint cp = slot.areaCornerpoints[iCp]; SlotData.Cornerpoint nextCp = slot.areaCornerpoints[(iCp + 1) % slot.areaCornerpoints.Length]; // Do OpenGL Y coord swapping SwapY(ref cp.y, transform.GetChild(iCam).GetSiblingIndex()); SwapY(ref nextCp.y, transform.GetChild(iCam).GetSiblingIndex()); // Use the bounding rect lower (OpenGL) left corner coordinate as the // (0, 0) reference point to create a line from a pair of corner points lines.Add(new Line( cp.x - (int)boundingRect.x, cp.y - (int)boundingRect.y, nextCp.x - (int)boundingRect.x, nextCp.y - (int)boundingRect.y)); } // Start counting the total and relative amount of white pixels /////////////////////////////////////////////////////////////// int numTotalPx = 0; // int numTotalPx = Mathf.RoundToInt(boundingRect.width * boundingRect.height); int numWhiteFound = 0; // Go through a black/white binary-processed source image pixel at a time for (int iColor = 0; iColor < colorData.Length; ++iColor) { int crossedLineCount = 0; // Get X and Y coordinates being checked int textureX = iColor % (int)boundingRect.width; int textureY = Mathf.FloorToInt(iColor / boundingRect.width); // Go through detection area edge lines, looking for line crossings. // Order of scanning will be according to OpenGL coordinate space, // from bottom (y == 0) to top (Y == texture height). foreach (Line line in lines) { if (line.IsPointYInRange(textureY)) { // The coordinate is within the Y axis range of the edge line. // Get the X position on the line in the Y coordinate. float lineCrossingX = line.GetXFromY(textureY); // Compare line X with the X of the location being checked if (System.Single.IsNaN(lineCrossingX)) { // Y coordinate matches horizontal detection area edge line // => pixel is to be considered to be inside the area and // taken into account. crossedLineCount = 1; break; } else if (lineCrossingX <= textureX) { // Texture X coordinate is to the right of a line crossing ++crossedLineCount; } } } if (IsOddLineCount(crossedLineCount)) { // Increase total found amount ++numTotalPx; if (IsWhiteColor(colorData[iColor])) { ++numWhiteFound; } } } // Pixel color count done -> calculate results int thresholdPixelCount = (int)(slot.pxThresholdLevel * numTotalPx); if (showDebugInfo) { Debug.Log("Parking row # " + (iRow + 1) + ", parking slot # " + (iSlot + 1) + ": " + "White pixel / total area pixel count & percentage: " + numWhiteFound + "/" + numTotalPx + ", " + ((float)numWhiteFound / numTotalPx * 100f).ToString("0.00") + "%" + "\nFree-to-reserved white pixel threshold count & percentage: " + thresholdPixelCount + ", " + (slot.pxThresholdLevel * 100).ToString("0.00") + "% " + (numWhiteFound > thresholdPixelCount ? "RESERVED" : "FREE")); } // Inform scene maintenance script about slot reservation state driveLineController.rows[iRow][iSlot] = numWhiteFound > thresholdPixelCount; } // for (int iSlot = 0; iSlot < row.numberOfSlots; ++iSlot) } // for (int iRow = 0; iRow < slotData.numberOfRows; ++iRow) } // for (int iCam = 0; iCam < numCams - 1; ++iCam) }