public static AnalyzedImage CombineImages(AnalyzedImage lhs, AnalyzedImage rhs, MatchType matchType) { if (matchType == MatchType.LRUpsideDown || matchType == MatchType.RLUpsideDown) { //flip the rhs image upside down Bitmap flippedRhsBitmap = new Bitmap(rhs.bitmap.Width, rhs.bitmap.Height); Bitmap flippedBlackAndWhiteRhsBitmap = new Bitmap(rhs.BlackAndWhiteBitmap.Width, rhs.BlackAndWhiteBitmap.Height); for (int i = 0; i < flippedRhsBitmap.Width; i++) { for (int j = 0; j < flippedRhsBitmap.Height; j++) { flippedRhsBitmap.SetPixel(flippedRhsBitmap.Width - i - 1, flippedRhsBitmap.Height - j - 1, rhs.bitmap.GetPixel(i, j)); flippedBlackAndWhiteRhsBitmap.SetPixel( flippedBlackAndWhiteRhsBitmap.Width - i - 1, flippedBlackAndWhiteRhsBitmap.Height - j - 1, rhs.BlackAndWhiteBitmap.GetPixel(i, j)); } } rhs.bitmap = flippedRhsBitmap; rhs.BlackAndWhiteBitmap = flippedBlackAndWhiteRhsBitmap; //flip and switch the Line Lists List<Line> newLeftLineList = GetReversedLineList(rhs.RightHandSideLineList); List<Line> newRightLineList = GetReversedLineList(rhs.LeftHandSideLineList); rhs.LeftHandSideLineList = newLeftLineList; rhs.RightHandSideLineList = newRightLineList; } if (matchType == MatchType.LR || matchType == MatchType.LRUpsideDown) { lhs.Name = lhs.Name + "-" + rhs.Name; lhs.RightHandSideLineList = rhs.RightHandSideLineList; lhs.TopRight = new Point(rhs.TopRight.x + lhs.bitmap.Width, rhs.TopRight.y); lhs.BottomRight = new Point(rhs.BottomRight.x + lhs.bitmap.Width, rhs.BottomRight.y); Bitmap newBitmap = new Bitmap(lhs.bitmap.Width + rhs.bitmap.Width, Math.Max(lhs.bitmap.Height, rhs.bitmap.Height)); Bitmap newBlackAndWhiteBitmap = new Bitmap(lhs.bitmap.Width + rhs.bitmap.Width, Math.Max(lhs.bitmap.Height, rhs.bitmap.Height)); for (int i = 0; i < newBitmap.Width; i++) { for (int j = 0; j < newBitmap.Height; j++) { Color pixelColor = Color.Black; Color BlackAndWhitePixelColor = Color.Black; if (i < lhs.bitmap.Width) { if (lhs.InBitmapRangeY(j)) { pixelColor = lhs.bitmap.GetPixel(i, j); BlackAndWhitePixelColor = lhs.BlackAndWhiteBitmap.GetPixel(i, j); } } else { if (rhs.InBitmapRangeY(j)) { pixelColor = rhs.bitmap.GetPixel(i - lhs.bitmap.Width, j); BlackAndWhitePixelColor = rhs.BlackAndWhiteBitmap.GetPixel(i - lhs.BlackAndWhiteBitmap.Width, j); } } newBitmap.SetPixel(i, j, pixelColor); newBlackAndWhiteBitmap.SetPixel(i, j, BlackAndWhitePixelColor); } } lhs.bitmap = newBitmap; lhs.BlackAndWhiteBitmap = newBlackAndWhiteBitmap; } else if (matchType == MatchType.RL || matchType == MatchType.RLUpsideDown) { lhs.Name = rhs.Name + "-" + lhs.Name; lhs.LeftHandSideLineList = rhs.LeftHandSideLineList; lhs.TopLeft = rhs.TopLeft; lhs.TopRight = new Point(lhs.TopRight.x + rhs.bitmap.Width, lhs.TopRight.y); lhs.BottomLeft = rhs.BottomLeft; lhs.BottomRight = new Point(lhs.BottomRight.x + rhs.bitmap.Width, lhs.BottomRight.y); Bitmap newBitmap = new Bitmap(lhs.bitmap.Width + rhs.bitmap.Width, Math.Max(lhs.bitmap.Height, rhs.bitmap.Height)); Bitmap newBlackAndWhiteBitmap = new Bitmap(lhs.bitmap.Width + rhs.bitmap.Width, Math.Max(lhs.bitmap.Height, rhs.bitmap.Height)); for (int i = 0; i < newBitmap.Width; i++) { for (int j = 0; j < newBitmap.Height; j++) { Color pixelColor = Color.Black; Color BlackAndWhitePixelColor = Color.Black; if (i < rhs.bitmap.Width) { if (rhs.InBitmapRangeY(j)) { pixelColor = rhs.bitmap.GetPixel(i, j); BlackAndWhitePixelColor = rhs.BlackAndWhiteBitmap.GetPixel(i, j); } } else { if (lhs.InBitmapRangeY(j)) { pixelColor = lhs.bitmap.GetPixel(i - rhs.bitmap.Width, j); BlackAndWhitePixelColor = lhs.BlackAndWhiteBitmap.GetPixel(i - rhs.bitmap.Width, j); } } newBitmap.SetPixel(i, j, pixelColor); newBlackAndWhiteBitmap.SetPixel(i, j, BlackAndWhitePixelColor); } } lhs.bitmap = newBitmap; lhs.BlackAndWhiteBitmap = newBlackAndWhiteBitmap; } return lhs; //should combine the bitmaps, the Black and White bitmaps, and select the correct upper right/lowerleft ect. points }
public static void Synthesize(AnalyzedImage[] AnalyzedImageArray) { for (int i = 0; i < AnalyzedImageArray.Length; i++) { if (AnalyzedImageArray[i] == null) { continue; } float MaxScore = 0.0f; int MaxScoreImageIndex = 0; MatchType MaxScoreMatchType = MatchType.LR; for (int j = 0; j < AnalyzedImageArray.Length; j++) { if(i != j && AnalyzedImageArray[j] != null) { MatchType matchType; float score = CompareAnalyzedImages(AnalyzedImageArray[i], AnalyzedImageArray[j], out matchType); if (score > MinScoreThreshold && score > MaxScore) { MaxScore = score; MaxScoreImageIndex = j; MaxScoreMatchType = matchType; } } } if (MaxScore > MinScoreThreshold) { AnalyzedImageArray[i] = CombineImages(AnalyzedImageArray[i], AnalyzedImageArray[MaxScoreImageIndex], MaxScoreMatchType); AnalyzedImageArray[MaxScoreImageIndex] = null; i--; } } List<AnalyzedImage> result = new List<AnalyzedImage>(); for (int i = 0; i < AnalyzedImageArray.Length; i++) { if(AnalyzedImageArray[i] != null) result.Add(AnalyzedImageArray[i]); } Loader.OutputSynthesizedBitmaps(result); }
public static List<AnalyzedImage> Analyze(List<Bitmap> Images, List<Color> BackgroundColors, List<Color> PaperColors) { /* * implementation ideas: * * Track boundary-crossing lines (pen strokes that go across shredding lines) * Describe lines with polynomial equations, then use deviation from those equations when synthesizing (might work better with cursive than printing...) * */ int Index = 1; List<AnalyzedImage> result = new List<AnalyzedImage>(); foreach (Bitmap b in Images) { AnalyzedImage bAnalyzedImage = new AnalyzedImage(b, String.Format("{0}", Index)); Index++; bool[][] MatchesBackground = new bool[b.Width][]; bool[][] MatchesPaper = new bool[b.Width][]; for (int i = 0; i < b.Width; i++) { MatchesBackground[i] = new bool[b.Height]; MatchesPaper[i] = new bool[b.Height]; } for (int i = 0; i < b.Width; i++) { for (int j = 0; j < b.Height; j++) { Color PixelColor = b.GetPixel(i, j); foreach(Color c in BackgroundColors) { if (Utilities.SameColor(PixelColor, c)) { MatchesBackground[i][j] = true; } } foreach (Color c in PaperColors) { if (Utilities.SameColor(PixelColor, c)) { MatchesPaper[i][j] = true; } } if (MatchesBackground[i][j]) { bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j, Color.Black); } else if (MatchesPaper[i][j]) { //color dark red bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j, bAnalyzedImage.BlackAndWhitePaperColor); //Mark upper left, right, bottom, top if (i + j < bAnalyzedImage.TopLeft.Value(0, 0)) { bAnalyzedImage.TopLeft.x = i; bAnalyzedImage.TopLeft.y = j; } if ((bAnalyzedImage.bitmap.Width - i) + j < bAnalyzedImage.TopRight.Value(bAnalyzedImage.bitmap.Width, 0)) { bAnalyzedImage.TopRight.x = i; bAnalyzedImage.TopRight.y = j; } if (i + (bAnalyzedImage.bitmap.Height - j) < bAnalyzedImage.BottomLeft.Value(0, bAnalyzedImage.bitmap.Height)) { bAnalyzedImage.BottomLeft.x = i; bAnalyzedImage.BottomLeft.y = j; } if ((bAnalyzedImage.bitmap.Width - i) + (bAnalyzedImage.bitmap.Height - j) < bAnalyzedImage.BottomRight.Value(bAnalyzedImage.bitmap.Width, bAnalyzedImage.bitmap.Height)) { bAnalyzedImage.BottomRight.x = i; bAnalyzedImage.BottomRight.y = j; } } } } for (int i = 0; i < b.Width; i++) { for (int j = 0; j < b.Height; j++) { if(!MatchesPaper[i][j] && !MatchesBackground[i][j]) { bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j, bAnalyzedImage.BlackAndWhiteLineColor); if(SmoothLines) { if (i >= bAnalyzedImage.BlackAndWhiteBitmap.Width - 2 || i <= 1 || j >= bAnalyzedImage.BlackAndWhiteBitmap.Height - 2 || j <= 1) { //Do nothing if we're on the edge of the image } else { bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i + 1, j + 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i + 1, j - 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i - 1, j + 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i - 1, j - 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i + 1, j, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j + 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j - 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i - 1, j, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i + 2, j, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i - 2, j, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j + 2, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j - 2, bAnalyzedImage.BlackAndWhiteLineColor); } } } } } //Now scan the sides of image looking for lines FindLines(bAnalyzedImage); //do debug printing. This isn't necessary, but it's helpful for us to verify bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(bAnalyzedImage.TopLeft.x, bAnalyzedImage.TopLeft.y, Color.GreenYellow); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(bAnalyzedImage.TopRight.x, bAnalyzedImage.TopRight.y, Color.GreenYellow); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(bAnalyzedImage.BottomRight.x, bAnalyzedImage.BottomRight.y, Color.GreenYellow); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(bAnalyzedImage.BottomLeft.x, bAnalyzedImage.BottomLeft.y, Color.GreenYellow); int ExpectedEdgeLocation = (bAnalyzedImage.TopRight.x + bAnalyzedImage.BottomRight.x) / 2; foreach (Line l in bAnalyzedImage.RightHandSideLineList) { bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(ExpectedEdgeLocation, l.y, Color.Blue); } ExpectedEdgeLocation = (bAnalyzedImage.TopLeft.x + bAnalyzedImage.BottomLeft.x) / 2; foreach (Line l in bAnalyzedImage.LeftHandSideLineList) { bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(ExpectedEdgeLocation, l.y, Color.Blue); } result.Add(bAnalyzedImage); } Loader.OutputAnalyzedBitmaps(result); return result; }
public static float CompareAnalyzedImages(AnalyzedImage lhs, AnalyzedImage rhs, out MatchType matchType) { /* * Algorithm: * check that both hieghts are close * foreach of the 4 positions: * compare edges of paper- check for distance between lines crossing edges, line widths, line counts, etc. * assign score between 0 and 1 * * assumptions: * Pieces are rectangular, and long sides match up with other long sides */ matchType = MatchType.LR; // [L] [R] // [H] [H] // [S] [S] float LR = (ScoreLineSets(lhs.RightHandSideLineList, rhs.LeftHandSideLineList) + ScoreLineSets(rhs.LeftHandSideLineList, lhs.RightHandSideLineList)) / 2.0f; // [R] [L] // [H] [H] // [S] [S] float RL = (ScoreLineSets(rhs.RightHandSideLineList, lhs.LeftHandSideLineList) + ScoreLineSets(lhs.LeftHandSideLineList, rhs.RightHandSideLineList)) / 2.0f; // [L] [S] // [H] [H] // [S] [R] float LRUpsideDown = (ScoreLineSets(lhs.RightHandSideLineList, GetReversedLineList(rhs.RightHandSideLineList)) + ScoreLineSets(GetReversedLineList(rhs.RightHandSideLineList), lhs.RightHandSideLineList)) / 2.0f; // [S] [L] // [H] [H] // [R] [S] float RLUpsideDown = (ScoreLineSets(lhs.LeftHandSideLineList, GetReversedLineList(rhs.LeftHandSideLineList)) + ScoreLineSets(GetReversedLineList(rhs.LeftHandSideLineList), lhs.LeftHandSideLineList)) / 2.0f; float MaxScore = Math.Max(Math.Max(RL, LR), Math.Max(LRUpsideDown, RLUpsideDown)); Console.WriteLine(String.Format("{0} <--> {1} Max Score: {2}", lhs.Name, rhs.Name, MaxScore)); if (MaxScore == RL) { Console.WriteLine(string.Format("Matched RL with confidence: {0}", MaxScore)); matchType = MatchType.RL; } else if (MaxScore == LR) { Console.WriteLine(string.Format("Matched LR with confidence: {0}", MaxScore)); matchType = MatchType.LR; } else if (MaxScore == RLUpsideDown) { Console.WriteLine(string.Format("Matched RLUpsideDown with confidence: {0}", MaxScore)); matchType = MatchType.RLUpsideDown; } else if (MaxScore == LRUpsideDown) { Console.WriteLine(string.Format("Matched LRUpsideDown with confidence: {0}", MaxScore)); matchType = MatchType.LRUpsideDown; } return MaxScore; }
public static void FindLines(AnalyzedImage bAnalyzedImage) { //scan down until we find a line //look at the edge pixel, and pixels PixelOffset away from the edge //keep going until we find the end of the line //create the line, add to Line list, move to next pixel PixelOffsetArray = new int[PIXEL_OFFSET_ARRAY_SIZE]; PixelOffsetArray[0] = 0; PixelOffsetArray[1] = 3; PixelOffsetArray[2] = -3; int ExpectedEdgeLocation = 0; // = (bAnalyzedImage.TopRight.x + bAnalyzedImage.BottomRight.x) / 2; int ConsecutiveLineValues = 0; for (int j = bAnalyzedImage.TopRight.y; j < bAnalyzedImage.BottomRight.y; j++) { bool MiddleOfLine = false; for (int i = 0; i < PIXEL_OFFSET_ARRAY_SIZE; i++) { if (!MiddleOfLine) { //find ExpectedEdgeLocation (if not already tracking a line) for (int k = 0; k < 30; k++) { if (bAnalyzedImage.IsPaper(bAnalyzedImage.BlackAndWhiteBitmap.Width - k - 1, j) || bAnalyzedImage.IsLine(bAnalyzedImage.BlackAndWhiteBitmap.Width - k - 1, j)) { ExpectedEdgeLocation = bAnalyzedImage.BlackAndWhiteBitmap.Width - k - 1; break; } } } if (bAnalyzedImage.InBitmapRangeX(ExpectedEdgeLocation + PixelOffsetArray[i])) { if (bAnalyzedImage.IsLine(ExpectedEdgeLocation + PixelOffsetArray[i], j)) { if (!MiddleOfLine) { MiddleOfLine = true; ConsecutiveLineValues++; } } } } if (!MiddleOfLine || j == bAnalyzedImage.BottomRight.y - 1) { //we've reached the end of the line (or end of scan). add to the list if (ConsecutiveLineValues > 3) //ignore spurious small lines { Line l = new Line(ConsecutiveLineValues, j - (ConsecutiveLineValues / 2), bAnalyzedImage.bitmap.Height - 1); bAnalyzedImage.RightHandSideLineList.Add(l); } ConsecutiveLineValues = 0; } } ExpectedEdgeLocation = (bAnalyzedImage.TopLeft.x + bAnalyzedImage.BottomLeft.x) / 2; ConsecutiveLineValues = 0; for (int j = bAnalyzedImage.TopLeft.y; j < bAnalyzedImage.BottomLeft.y; j++) { bool MiddleOfLine = false; for (int i = 0; i < PIXEL_OFFSET_ARRAY_SIZE; i++) { if (!MiddleOfLine) { //find ExpectedEdgeLocation (if not already tracking a line) for (int k = 0; k < 30; k++) { if (bAnalyzedImage.IsPaper(k, j) || bAnalyzedImage.IsLine(k, j)) { ExpectedEdgeLocation = k; break; } } } if (bAnalyzedImage.InBitmapRangeX(ExpectedEdgeLocation + PixelOffsetArray[i])) { if (bAnalyzedImage.IsLine(ExpectedEdgeLocation + PixelOffsetArray[i], j)) { if (!MiddleOfLine) { MiddleOfLine = true; ConsecutiveLineValues++; } } } } if (!MiddleOfLine || j == bAnalyzedImage.BottomLeft.y - 1) { //we've reached the end of the line (or end of our scan). add to the list if (ConsecutiveLineValues > 3) //ignore spurious small lines { Line l = new Line(ConsecutiveLineValues, j - (ConsecutiveLineValues / 2), bAnalyzedImage.bitmap.Height - 1); bAnalyzedImage.LeftHandSideLineList.Add(l); } ConsecutiveLineValues = 0; } } }
public static float CompareAnalyzedImages(AnalyzedImage lhs, AnalyzedImage rhs, out MatchType matchType) { /* * Algorithm: * check that both hieghts are close * foreach of the 4 positions: * compare edges of paper- check for distance between lines crossing edges, line widths, line counts, etc. * assign score between 0 and 1 * * assumptions: * Pieces are rectangular, and long sides match up with other long sides */ matchType = MatchType.LR; // [L] [R] // [H] [H] // [S] [S] float LR = (ScoreLineSets(lhs.RightHandSideLineList, rhs.LeftHandSideLineList) + ScoreLineSets(rhs.LeftHandSideLineList, lhs.RightHandSideLineList)) / 2.0f; // [R] [L] // [H] [H] // [S] [S] float RL = (ScoreLineSets(rhs.RightHandSideLineList, lhs.LeftHandSideLineList) + ScoreLineSets(lhs.LeftHandSideLineList, rhs.RightHandSideLineList)) / 2.0f; // [L] [S] // [H] [H] // [S] [R] float LRUpsideDown = (ScoreLineSets(lhs.RightHandSideLineList, GetReversedLineList(rhs.RightHandSideLineList)) + ScoreLineSets(GetReversedLineList(rhs.RightHandSideLineList), lhs.RightHandSideLineList)) / 2.0f; // [S] [L] // [H] [H] // [R] [S] float RLUpsideDown = (ScoreLineSets(lhs.LeftHandSideLineList, GetReversedLineList(rhs.LeftHandSideLineList)) + ScoreLineSets(GetReversedLineList(rhs.LeftHandSideLineList), lhs.LeftHandSideLineList)) / 2.0f; float MaxScore = Math.Max(Math.Max(RL, LR), Math.Max(LRUpsideDown, RLUpsideDown)); Console.WriteLine(String.Format("{0} <--> {1} Max Score: {2}", lhs.Name, rhs.Name, MaxScore)); if (MaxScore == RL) { Console.WriteLine(string.Format("Matched RL with confidence: {0}", MaxScore)); matchType = MatchType.RL; } else if (MaxScore == LR) { Console.WriteLine(string.Format("Matched LR with confidence: {0}", MaxScore)); matchType = MatchType.LR; } else if (MaxScore == RLUpsideDown) { Console.WriteLine(string.Format("Matched RLUpsideDown with confidence: {0}", MaxScore)); matchType = MatchType.RLUpsideDown; } else if (MaxScore == LRUpsideDown) { Console.WriteLine(string.Format("Matched LRUpsideDown with confidence: {0}", MaxScore)); matchType = MatchType.LRUpsideDown; } return(MaxScore); }
public static AnalyzedImage CombineImages(AnalyzedImage lhs, AnalyzedImage rhs, MatchType matchType) { if (matchType == MatchType.LRUpsideDown || matchType == MatchType.RLUpsideDown) { //flip the rhs image upside down Bitmap flippedRhsBitmap = new Bitmap(rhs.bitmap.Width, rhs.bitmap.Height); Bitmap flippedBlackAndWhiteRhsBitmap = new Bitmap(rhs.BlackAndWhiteBitmap.Width, rhs.BlackAndWhiteBitmap.Height); for (int i = 0; i < flippedRhsBitmap.Width; i++) { for (int j = 0; j < flippedRhsBitmap.Height; j++) { flippedRhsBitmap.SetPixel(flippedRhsBitmap.Width - i - 1, flippedRhsBitmap.Height - j - 1, rhs.bitmap.GetPixel(i, j)); flippedBlackAndWhiteRhsBitmap.SetPixel(flippedBlackAndWhiteRhsBitmap.Width - i - 1, flippedBlackAndWhiteRhsBitmap.Height - j - 1, rhs.BlackAndWhiteBitmap.GetPixel(i, j)); } } rhs.bitmap = flippedRhsBitmap; rhs.BlackAndWhiteBitmap = flippedBlackAndWhiteRhsBitmap; //flip and switch the Line Lists List <Line> newLeftLineList = GetReversedLineList(rhs.RightHandSideLineList); List <Line> newRightLineList = GetReversedLineList(rhs.LeftHandSideLineList); rhs.LeftHandSideLineList = newLeftLineList; rhs.RightHandSideLineList = newRightLineList; } if (matchType == MatchType.LR || matchType == MatchType.LRUpsideDown) { lhs.Name = lhs.Name + "-" + rhs.Name; lhs.RightHandSideLineList = rhs.RightHandSideLineList; lhs.TopRight = new Point(rhs.TopRight.x + lhs.bitmap.Width, rhs.TopRight.y); lhs.BottomRight = new Point(rhs.BottomRight.x + lhs.bitmap.Width, rhs.BottomRight.y); Bitmap newBitmap = new Bitmap(lhs.bitmap.Width + rhs.bitmap.Width, Math.Max(lhs.bitmap.Height, rhs.bitmap.Height)); Bitmap newBlackAndWhiteBitmap = new Bitmap(lhs.bitmap.Width + rhs.bitmap.Width, Math.Max(lhs.bitmap.Height, rhs.bitmap.Height)); for (int i = 0; i < newBitmap.Width; i++) { for (int j = 0; j < newBitmap.Height; j++) { Color pixelColor = Color.Black; Color BlackAndWhitePixelColor = Color.Black; if (i < lhs.bitmap.Width) { if (lhs.InBitmapRangeY(j)) { pixelColor = lhs.bitmap.GetPixel(i, j); BlackAndWhitePixelColor = lhs.BlackAndWhiteBitmap.GetPixel(i, j); } } else { if (rhs.InBitmapRangeY(j)) { pixelColor = rhs.bitmap.GetPixel(i - lhs.bitmap.Width, j); BlackAndWhitePixelColor = rhs.BlackAndWhiteBitmap.GetPixel(i - lhs.BlackAndWhiteBitmap.Width, j); } } newBitmap.SetPixel(i, j, pixelColor); newBlackAndWhiteBitmap.SetPixel(i, j, BlackAndWhitePixelColor); } } lhs.bitmap = newBitmap; lhs.BlackAndWhiteBitmap = newBlackAndWhiteBitmap; } else if (matchType == MatchType.RL || matchType == MatchType.RLUpsideDown) { lhs.Name = rhs.Name + "-" + lhs.Name; lhs.LeftHandSideLineList = rhs.LeftHandSideLineList; lhs.TopLeft = rhs.TopLeft; lhs.TopRight = new Point(lhs.TopRight.x + rhs.bitmap.Width, lhs.TopRight.y); lhs.BottomLeft = rhs.BottomLeft; lhs.BottomRight = new Point(lhs.BottomRight.x + rhs.bitmap.Width, lhs.BottomRight.y); Bitmap newBitmap = new Bitmap(lhs.bitmap.Width + rhs.bitmap.Width, Math.Max(lhs.bitmap.Height, rhs.bitmap.Height)); Bitmap newBlackAndWhiteBitmap = new Bitmap(lhs.bitmap.Width + rhs.bitmap.Width, Math.Max(lhs.bitmap.Height, rhs.bitmap.Height)); for (int i = 0; i < newBitmap.Width; i++) { for (int j = 0; j < newBitmap.Height; j++) { Color pixelColor = Color.Black; Color BlackAndWhitePixelColor = Color.Black; if (i < rhs.bitmap.Width) { if (rhs.InBitmapRangeY(j)) { pixelColor = rhs.bitmap.GetPixel(i, j); BlackAndWhitePixelColor = rhs.BlackAndWhiteBitmap.GetPixel(i, j); } } else { if (lhs.InBitmapRangeY(j)) { pixelColor = lhs.bitmap.GetPixel(i - rhs.bitmap.Width, j); BlackAndWhitePixelColor = lhs.BlackAndWhiteBitmap.GetPixel(i - rhs.bitmap.Width, j); } } newBitmap.SetPixel(i, j, pixelColor); newBlackAndWhiteBitmap.SetPixel(i, j, BlackAndWhitePixelColor); } } lhs.bitmap = newBitmap; lhs.BlackAndWhiteBitmap = newBlackAndWhiteBitmap; } return(lhs); //should combine the bitmaps, the Black and White bitmaps, and select the correct upper right/lowerleft ect. points }
public static void FindLines(AnalyzedImage bAnalyzedImage) { //scan down until we find a line //look at the edge pixel, and pixels PixelOffset away from the edge //keep going until we find the end of the line //create the line, add to Line list, move to next pixel PixelOffsetArray = new int[PIXEL_OFFSET_ARRAY_SIZE]; PixelOffsetArray[0] = 0; PixelOffsetArray[1] = 3; PixelOffsetArray[2] = -3; int ExpectedEdgeLocation = 0; // = (bAnalyzedImage.TopRight.x + bAnalyzedImage.BottomRight.x) / 2; int ConsecutiveLineValues = 0; for (int j = bAnalyzedImage.TopRight.y; j < bAnalyzedImage.BottomRight.y; j++) { bool MiddleOfLine = false; for (int i = 0; i < PIXEL_OFFSET_ARRAY_SIZE; i++) { if (!MiddleOfLine) { //find ExpectedEdgeLocation (if not already tracking a line) for (int k = 0; k < 30; k++) { if (bAnalyzedImage.IsPaper(bAnalyzedImage.BlackAndWhiteBitmap.Width - k - 1, j) || bAnalyzedImage.IsLine(bAnalyzedImage.BlackAndWhiteBitmap.Width - k - 1, j)) { ExpectedEdgeLocation = bAnalyzedImage.BlackAndWhiteBitmap.Width - k - 1; break; } } } if (bAnalyzedImage.InBitmapRangeX(ExpectedEdgeLocation + PixelOffsetArray[i])) { if (bAnalyzedImage.IsLine(ExpectedEdgeLocation + PixelOffsetArray[i], j)) { if (!MiddleOfLine) { MiddleOfLine = true; ConsecutiveLineValues++; } } } } if (!MiddleOfLine || j == bAnalyzedImage.BottomRight.y - 1) { //we've reached the end of the line (or end of scan). add to the list if (ConsecutiveLineValues > 3) //ignore spurious small lines { Line l = new Line(ConsecutiveLineValues, j - (ConsecutiveLineValues / 2), bAnalyzedImage.bitmap.Height - 1); bAnalyzedImage.RightHandSideLineList.Add(l); } ConsecutiveLineValues = 0; } } ExpectedEdgeLocation = (bAnalyzedImage.TopLeft.x + bAnalyzedImage.BottomLeft.x) / 2; ConsecutiveLineValues = 0; for (int j = bAnalyzedImage.TopLeft.y; j < bAnalyzedImage.BottomLeft.y; j++) { bool MiddleOfLine = false; for (int i = 0; i < PIXEL_OFFSET_ARRAY_SIZE; i++) { if (!MiddleOfLine) { //find ExpectedEdgeLocation (if not already tracking a line) for (int k = 0; k < 30; k++) { if (bAnalyzedImage.IsPaper(k, j) || bAnalyzedImage.IsLine(k, j)) { ExpectedEdgeLocation = k; break; } } } if (bAnalyzedImage.InBitmapRangeX(ExpectedEdgeLocation + PixelOffsetArray[i])) { if (bAnalyzedImage.IsLine(ExpectedEdgeLocation + PixelOffsetArray[i], j)) { if (!MiddleOfLine) { MiddleOfLine = true; ConsecutiveLineValues++; } } } } if (!MiddleOfLine || j == bAnalyzedImage.BottomLeft.y - 1) { //we've reached the end of the line (or end of our scan). add to the list if (ConsecutiveLineValues > 3) //ignore spurious small lines { Line l = new Line(ConsecutiveLineValues, j - (ConsecutiveLineValues / 2), bAnalyzedImage.bitmap.Height - 1); bAnalyzedImage.LeftHandSideLineList.Add(l); } ConsecutiveLineValues = 0; } } }
public static List <AnalyzedImage> Analyze(List <Bitmap> Images, List <Color> BackgroundColors, List <Color> PaperColors) { /* * implementation ideas: * * Track boundary-crossing lines (pen strokes that go across shredding lines) * Describe lines with polynomial equations, then use deviation from those equations when synthesizing (might work better with cursive than printing...) * */ int Index = 1; List <AnalyzedImage> result = new List <AnalyzedImage>(); foreach (Bitmap b in Images) { AnalyzedImage bAnalyzedImage = new AnalyzedImage(b, String.Format("{0}", Index)); Index++; bool[][] MatchesBackground = new bool[b.Width][]; bool[][] MatchesPaper = new bool[b.Width][]; for (int i = 0; i < b.Width; i++) { MatchesBackground[i] = new bool[b.Height]; MatchesPaper[i] = new bool[b.Height]; } for (int i = 0; i < b.Width; i++) { for (int j = 0; j < b.Height; j++) { Color PixelColor = b.GetPixel(i, j); foreach (Color c in BackgroundColors) { if (Utilities.SameColor(PixelColor, c)) { MatchesBackground[i][j] = true; } } foreach (Color c in PaperColors) { if (Utilities.SameColor(PixelColor, c)) { MatchesPaper[i][j] = true; } } if (MatchesBackground[i][j]) { bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j, Color.Black); } else if (MatchesPaper[i][j]) { //color dark red bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j, bAnalyzedImage.BlackAndWhitePaperColor); //Mark upper left, right, bottom, top if (i + j < bAnalyzedImage.TopLeft.Value(0, 0)) { bAnalyzedImage.TopLeft.x = i; bAnalyzedImage.TopLeft.y = j; } if ((bAnalyzedImage.bitmap.Width - i) + j < bAnalyzedImage.TopRight.Value(bAnalyzedImage.bitmap.Width, 0)) { bAnalyzedImage.TopRight.x = i; bAnalyzedImage.TopRight.y = j; } if (i + (bAnalyzedImage.bitmap.Height - j) < bAnalyzedImage.BottomLeft.Value(0, bAnalyzedImage.bitmap.Height)) { bAnalyzedImage.BottomLeft.x = i; bAnalyzedImage.BottomLeft.y = j; } if ((bAnalyzedImage.bitmap.Width - i) + (bAnalyzedImage.bitmap.Height - j) < bAnalyzedImage.BottomRight.Value(bAnalyzedImage.bitmap.Width, bAnalyzedImage.bitmap.Height)) { bAnalyzedImage.BottomRight.x = i; bAnalyzedImage.BottomRight.y = j; } } } } for (int i = 0; i < b.Width; i++) { for (int j = 0; j < b.Height; j++) { if (!MatchesPaper[i][j] && !MatchesBackground[i][j]) { bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j, bAnalyzedImage.BlackAndWhiteLineColor); if (SmoothLines) { if (i >= bAnalyzedImage.BlackAndWhiteBitmap.Width - 2 || i <= 1 || j >= bAnalyzedImage.BlackAndWhiteBitmap.Height - 2 || j <= 1) { //Do nothing if we're on the edge of the image } else { bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i + 1, j + 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i + 1, j - 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i - 1, j + 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i - 1, j - 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i + 1, j, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j + 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j - 1, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i - 1, j, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i + 2, j, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i - 2, j, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j + 2, bAnalyzedImage.BlackAndWhiteLineColor); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(i, j - 2, bAnalyzedImage.BlackAndWhiteLineColor); } } } } } //Now scan the sides of image looking for lines FindLines(bAnalyzedImage); //do debug printing. This isn't necessary, but it's helpful for us to verify bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(bAnalyzedImage.TopLeft.x, bAnalyzedImage.TopLeft.y, Color.GreenYellow); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(bAnalyzedImage.TopRight.x, bAnalyzedImage.TopRight.y, Color.GreenYellow); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(bAnalyzedImage.BottomRight.x, bAnalyzedImage.BottomRight.y, Color.GreenYellow); bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(bAnalyzedImage.BottomLeft.x, bAnalyzedImage.BottomLeft.y, Color.GreenYellow); int ExpectedEdgeLocation = (bAnalyzedImage.TopRight.x + bAnalyzedImage.BottomRight.x) / 2; foreach (Line l in bAnalyzedImage.RightHandSideLineList) { bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(ExpectedEdgeLocation, l.y, Color.Blue); } ExpectedEdgeLocation = (bAnalyzedImage.TopLeft.x + bAnalyzedImage.BottomLeft.x) / 2; foreach (Line l in bAnalyzedImage.LeftHandSideLineList) { bAnalyzedImage.BlackAndWhiteBitmap.SetPixel(ExpectedEdgeLocation, l.y, Color.Blue); } result.Add(bAnalyzedImage); } Loader.OutputAnalyzedBitmaps(result); return(result); }