/// <summary> /// Returns the LOCATION of each ItemAlt (midpoint, relative: 0 to 1) /// </summary> public static PointF[,] RotateAndCrop(Test test, ref byte[,] image, ref byte[] barCodeBytes, float resize, int searchSize) { var ansList = new PointF[test.Paper.Blocks.X, test.Paper.Blocks.Y]; image = Processing.Resize(image, resize); List <PointF> calibrationPointsRotate = Rotate(test, ref image, searchSize); if (calibrationPointsRotate.Count == test.Paper.CalibrationCircles.X + test.Paper.CalibrationCircles.Y - 1) { byte[,] imgBarCode = new byte[0, 0]; List <PointF> calibrationPointsCrop = Crop(test, ref image, ref imgBarCode, searchSize); if (calibrationPointsCrop.Count == test.Paper.CalibrationCircles.X + test.Paper.CalibrationCircles.Y - 1) { barCodeBytes = BarCode.Read(imgBarCode); // Calculate the answerpoints var xList = new List <float>(); for (int i = 0; i < test.Paper.CalibrationCircles.X - 1; i++) { float obsW = calibrationPointsCrop[i + 1].X - calibrationPointsCrop[i].X; int blocksLeft = 7; float pixelsPerBlockW = obsW / blocksLeft; if (i == test.Paper.CalibrationCircles.X - 2) { blocksLeft = test.Paper.Blocks.X - ((test.Paper.CalibrationCircles.X - 2) * 7); pixelsPerBlockW = obsW / (blocksLeft + .5f); } for (int j = 0; j < blocksLeft; j++) { xList.Add(calibrationPointsCrop[i].X + (j * pixelsPerBlockW)); } } for (int i = calibrationPointsCrop.Count - 1; i >= test.Paper.CalibrationCircles.X; i--) { float obsH = calibrationPointsCrop[i - 1].Y - calibrationPointsCrop[i].Y; int blocksLeft = 7; float pixelsPerBlockH = obsH / blocksLeft; if (i <= test.Paper.CalibrationCircles.X) { blocksLeft = test.Paper.Blocks.Y - ((test.Paper.CalibrationCircles.Y - 2) * 7); pixelsPerBlockH = obsH / (blocksLeft + 1); } int i2 = (calibrationPointsCrop.Count - i - 1) * 7; for (int ii = 0; ii < blocksLeft; ii++) { float yVal = calibrationPointsCrop[i].Y + (ii * pixelsPerBlockH); for (int j = 0; j < xList.Count; j++) { ansList[j, i2 + ii] = new PointF(xList[j] / image.GetLength(0), yVal / image.GetLength(1)); } } } } } return(ansList); }
// Persumed to be rotated correctly (but not yet cropped) public static byte[] Read(byte[,] imageData) { byte[,] array = new byte[19, 4]; if (imageData != null) { if (imageData.GetLength(0) > 0 && imageData.GetLength(1) > 0) { imageData = Processing.FloatToByte(Processing.Gaussian(imageData)); imageData = Processing.Binarize(imageData, 200); int minBlack = Math.Min(4, Math.Min(imageData.GetLength(0) / 19, imageData.GetLength(1) / 4)); Point p1 = new Point(-1, -1); Point p2 = new Point(-1, -1); for (int i = 0; i < (imageData.GetLength(0) / 2); i++) { int sum1 = 0; int sum2 = 0; for (int j = 0; j < imageData.GetLength(1); j++) { sum1 += imageData[i, j] > 0 ? 0 : 1; sum2 += imageData[imageData.GetLength(0) - i - 1, j] > 0 ? 0 : 1; } if (p1.X == -1 && sum1 >= minBlack) { p1.X = i; } if (p2.X == -1 && sum2 >= minBlack) { p2.X = imageData.GetLength(0) - i - 1; } if (p1.X != -1 && p2.X != -1) { break; } } for (int j = 0; j < (imageData.GetLength(1) / 2); j++) { int sum1 = 0; int sum2 = 0; for (int i = 0; i < imageData.GetLength(0); i++) { sum1 += imageData[i, j] > 0 ? 0 : 1; sum2 += imageData[i, imageData.GetLength(1) - j - 1] > 0 ? 0 : 1; } if (p1.Y == -1 && sum1 >= minBlack) { p1.Y = j; } if (p2.Y == -1 && sum2 >= minBlack) { p2.Y = imageData.GetLength(1) - j - 1; } if (p1.Y != -1 && p2.Y != -1) { break; } } if (p1.X != -1 && p1.Y != -1 && p2.X != -1 && p2.Y != -1) { imageData = Processing.Crop(imageData, new Rectangle(p1.X, p1.Y, p2.X - p1.X + 1, p2.Y - p1.Y + 1)); int blockWidth = (int)Math.Floor((double)imageData.GetLength(0) / 19); int blockHeight = (int)Math.Floor((double)imageData.GetLength(1) / 4); int newWidth = blockWidth * 19; int newHeight = blockHeight * 4; imageData = Processing.Resize(imageData, newWidth, newHeight); int threshold = (blockWidth * blockHeight) / 2; for (int j = 0; j < 4; j++) { for (int i = 0; i < 19; i++) { double sum = 0; for (int k = 0; k < blockHeight; k++) { for (int l = 0; l < blockWidth; l++) { sum += (int)imageData[(i * blockWidth) + l, (j * blockHeight) + k] > 1 ? 1 : 0; } } array[i, j] = sum < threshold ? (byte)0 : (byte)1; } } } else { Logger.LogLow("Could not crop barcode."); } } } return(ReadFrom2DArray(array)); }