internal ChessboardConnections(ValidResponseData item, ValidResponseData leftConnection, ValidResponseData rightConnection, ValidResponseData bottomConnection, ValidResponseData topConnection) { this.item = item; this.leftConnection = leftConnection; this.rightConnection = rightConnection; this.bottomConnection = bottomConnection; this.topConnection = topConnection; }
public void DrawDebug(Agg.Graphics2D graphics2D) { if (validResponsesBotomToTopList.Count < 1) { return; } if (graphics2D.DestImage == null) { throw new Exception("Your graphics2D must be for a buffered Image."); } if (lowestCorrner != null) { lowestCorrner.Render(graphics2D); } int width = allResponsesGrid.Width; int height = allResponsesGrid.Height; IImageByte imageBuffer = graphics2D.DestImage; ValidResponseData prevValidResponse = validResponsesBotomToTopList[0]; foreach (ValidResponseData validResponse in validResponsesBotomToTopList) { if (validResponse.totalResponse > 0) { Vector2 start = new Vector2(10, 0); start.Rotate(validResponse.orientation * MathHelper.DegreesToRadians(22.5)); graphics2D.Line(validResponse.position + start, validResponse.position - start, RGBA_Bytes.Green); graphics2D.Circle(validResponse.position, 2, RGBA_Bytes.Red); if (validResponse.has4ChessboardNeighbors) { Ellipse elipse = new Ellipse(validResponse.position, 10); graphics2D.Render(new Stroke(elipse, 1), RGBA_Bytes.Red); } //graphics2D.Line(validResponse.position, prevValidResponse.position, RGBA_Bytes.Red); prevValidResponse = validResponse; } } #if SHOW_SUB_PIXEL_LOGIC graphics2D.Render(gray, 0, 0); #endif }
void FindChessBoardLines() { List <ValidResponseData> sortedList = new List <ValidResponseData>(validResponsesBotomToTopList); // remove all the points that can't be part of a chess board for (int i = validResponsesBotomToTopList.Count - 1; i >= 0; i--) { ValidResponseData checkItem = validResponsesBotomToTopList[i]; sortedList.Sort(new SortOnDistance(checkItem.position)); int numThatAreValid = 0; if (sortedList.Count > 5) { for (int j = 1; j < 5; j++) { ValidResponseData nextNearest = sortedList[j]; if (nextNearest == checkItem) { continue; } int delta = Math.Abs(checkItem.orientation - nextNearest.orientation); if (delta > 2 && delta < 5) { numThatAreValid++; } } // find out if it has at least 2 valid connections next to it. if (numThatAreValid < 2) { validResponsesBotomToTopList.RemoveAt(i); sortedList = new List <ValidResponseData>(validResponsesBotomToTopList); } } } // Mark how many neighbors every corner has if (validResponsesBotomToTopList.Count > 5) { foreach (ValidResponseData item in validResponsesBotomToTopList) { sortedList.Sort(new SortOnDistance(item.position)); int numNeighborsThatCouldBeOnChessboard = 0; for (int i = 1; i < 5; i++) { ValidResponseData nextNearest = sortedList[i]; if (nextNearest == item) { continue; } int delta = Math.Abs(item.orientation - nextNearest.orientation); if (delta > 2 && delta < 5) { numNeighborsThatCouldBeOnChessboard++; } } item.has4ChessboardNeighbors = (numNeighborsThatCouldBeOnChessboard == 4); if (item.has4ChessboardNeighbors) { item.chessboardConnections = new ChessboardConnections(sortedList[0], sortedList[1], sortedList[2], sortedList[3], sortedList[4]); } } lowestCorrner = null; // find the lowest corner on the board foreach (ValidResponseData item in validResponsesBotomToTopList) { if (item.has4ChessboardNeighbors) { sortedList.Sort(new SortOnDistance(item.position)); if (lowestCorrner == null) { int countOfNeighborsWith4Neighbors = 0; for (int i = 1; i < 5; i++) { if (sortedList[i].has4ChessboardNeighbors) { countOfNeighborsWith4Neighbors++; } } if (countOfNeighborsWith4Neighbors == 2) { lowestCorrner = item.chessboardConnections; } } } } // now that we have the lowest corner find the rest of the chessboard from it } }
void MergeResponsesThatAreSameFeatures() { int width = allResponsesGrid.Width; int height = allResponsesGrid.Height; foreach (ValidResponseData validResponse in validResponsesBotomToTopList) { if (validResponse.totalResponse <= 0) { continue; } int dist = 5; int yStart = Math.Max(0, (int)validResponse.position.y - dist); int yEnd = Math.Min(height - 1, (int)validResponse.position.y + dist); int numFeaturesFound = 1; int accumulatedTotalResponse = validResponse.totalResponse; Vector2 accumulatedPosition = validResponse.position * accumulatedTotalResponse; int accumulatedOrientation = validResponse.orientation * accumulatedTotalResponse; for (int y = yStart; y < yEnd; y++) { int xStart = Math.Max(0, (int)validResponse.position.x - dist); int xEnd = Math.Min(width - 1, (int)validResponse.position.x + dist); for (int x = xStart; x < xEnd; x++) { if (x == validResponse.position.x && y == validResponse.position.y) { continue; } ValidResponseData testResponse = allResponsesGrid.GetValue(x, y); if (testResponse != null && testResponse.totalResponse > 0) { numFeaturesFound++; int totalResponsOfTest = testResponse.totalResponse; testResponse.totalResponse = 0; accumulatedTotalResponse += totalResponsOfTest; accumulatedPosition += testResponse.position * totalResponsOfTest; accumulatedOrientation += testResponse.orientation * totalResponsOfTest; } } } if (numFeaturesFound < 2) { validResponse.totalResponse = 0; } else { validResponse.position = accumulatedPosition / accumulatedTotalResponse; validResponse.orientation = (int)((double)accumulatedOrientation / accumulatedTotalResponse + .5); } } int count = validResponsesBotomToTopList.Count; for (int i = count - 1; i >= 0; i--) { if (validResponsesBotomToTopList[i].totalResponse == 0) { validResponsesBotomToTopList.RemoveAt(i); } } }
void CalculateSumResponseAtAllPixels(ImageBuffer imageBuffer, int totalResponseThreshold) { validResponsesBotomToTopList.Clear(); if (imageBuffer.GetBytesBetweenPixelsInclusive() != 1) { throw new NotImplementedException("We only process gray scale images that are packed"); } int width = imageBuffer.Width; int height = imageBuffer.Height; byte[] buffer = imageBuffer.GetBuffer(); for (int y = trimPixels; y < height - trimPixels; y++) { int byteOffset = imageBuffer.GetBufferOffsetXY(trimPixels, y); ValidResponseData[] totalResponseRow = allResponsesGrid.GetRow(y); for (int x = trimPixels; x < width - trimPixels; x++) { int sumResponse = 0; for (int angleToCheckIndex = 0; angleToCheckIndex < 4; angleToCheckIndex++) { int sum = (buffer[byteOffset + byteOffsetToPixel[angleToCheckIndex]] + buffer[byteOffset + byteOffsetToPixel[angleToCheckIndex + 8]]) - (buffer[byteOffset + byteOffsetToPixel[angleToCheckIndex + 4]] + buffer[byteOffset + byteOffsetToPixel[angleToCheckIndex + 12]]); int absSum = Math.Abs(sum); sumResponse += absSum; } int neighborMeanTotal = 0; int diffResponse = 0; for (int diffCheck = 0; diffCheck < 8; diffCheck++) { int testValue = buffer[byteOffset + byteOffsetToPixel[diffCheck]]; int oppositeValue = buffer[byteOffset + byteOffsetToPixel[diffCheck + 8]]; diffResponse += Math.Abs(testValue - oppositeValue); neighborMeanTotal += testValue + oppositeValue; } int neighborMean = (neighborMeanTotal + 8) / 16; int centerMeanTotal = buffer[byteOffset - 1] + buffer[byteOffset + 1] + buffer[byteOffset - width] + buffer[byteOffset - width]; int centerMean = (centerMeanTotal + 2) / 4; int absMeanResponse = Math.Abs(neighborMean - centerMean); ValidResponseData newResponse = new ValidResponseData(); int totalResponse = sumResponse - diffResponse - absMeanResponse; if (totalResponse >= totalResponseThreshold) { newResponse.totalResponse = totalResponse; newResponse.position = new Vector2(x, y); newResponse.originalIndex = validResponsesBotomToTopList.Count; // we are scanning pixels bottom to top so they go in the list bottom to top validResponsesBotomToTopList.Add(newResponse); } totalResponseRow[x] = newResponse; byteOffset++; } } }