public BoardInfo ProcessImage(BoardParameters bp, Pixels pix) { BoardInfo boardInfo = null; boardInfo = new BoardInfo(bp.FieldWidth, bp.FieldHeight); int halfSize = (int)(bp.BlockSize / 2) + 1; int[,] circleRadiusData = CalculateRadii((dx, dy) => (int)Math.Sqrt(dx * dx + dy * dy), halfSize); int[,] squareRadiusData = CalculateRadii((dx, dy) => (int)Math.Max(Math.Abs(dx), Math.Abs(dy)), halfSize); for (int y = 0; y < bp.FieldHeight; y++) for (int x = 0; x < bp.FieldWidth; x++) { int px = (int)Math.Round(bp.LinedBoardRect.Left + bp.BlockSize * x); int py = (int)Math.Round(bp.LinedBoardRect.Top + bp.BlockSize * y); RawColor[] circles = RadiusColor(pix, new Point(px, py), circleRadiusData, 2 * halfSize ); RawColor[] squares = RadiusColor(pix, new Point(px, py), squareRadiusData, 2 * halfSize ); PointInfo info = new PointInfo(); info.StoneColor = GetStoneColor(circles, bp.BlockSize); info.SmallStoneColor = GetSmallStoneColor(circles, bp.BlockSize); if (info.SmallStoneColor == info.StoneColor)//Small stone is part of the real stone info.SmallStoneColor = StoneColor.None; if (GetCircleMarker(circles, bp.BlockSize, info.StoneColor)) { if (info.SmallStoneColor != StoneColor.Black)//Can't distinguish circle from small stone info.Marker = Marker.Circle; } if (GetSquareMarker(squares, bp.BlockSize, info.StoneColor)) info.Marker = Marker.Square; boardInfo.Board[x, y] = info; } //MirrorBoardInfo(boardInfo); return boardInfo; }
public bool GetBoardParameters(Pixels pix, out BoardParameters bp) { bp = new BoardParameters(); bp.BoardRect = System.Drawing.Rectangle.Empty; bp.LinedBoardRect = System.Drawing.Rectangle.Empty; bp.FieldHeight = 0; bp.FieldWidth = 0; bp.BlockSize = 0; bp.BoardRect = FindBoard(pix); if (bp.BoardRect == System.Drawing.Rectangle.Empty) return false; float[] grayCols, grayRows; bp.LinedBoardRect = FindLinedBoard(pix, bp.BoardRect, out grayCols, out grayRows); double blockWidth, blockHeight; bool foundLines1 = CalculateFieldPosition(bp.LinedBoardRect.Left, bp.LinedBoardRect.Width, grayCols, out bp.FieldWidth, out blockWidth); bool foundLines2 = CalculateFieldPosition(bp.LinedBoardRect.Top, bp.LinedBoardRect.Height, grayRows, out bp.FieldHeight, out blockHeight); if (Math.Abs(blockHeight - blockWidth) > 1) return false; bp.BlockSize = (blockHeight + blockWidth) / 2; return foundLines1 && foundLines2; }
private Pixels BitmapToPixels(Bitmap bmp) { Pixels pix = new Pixels(pixelPool.Alloc(bmp.Width, bmp.Height)); pix.LoadFromBitmap(bmp); return pix; }
public void Release(Pixels pix) { if (pix.Data != null) pixelPool.Release(pix.Data); }
private void timer1_Tick(object sender, EventArgs e) { DateTime start0 = DateTime.UtcNow; if (this.Handle != ScreenCapture.GetForegroundWindow() && goRecorder == null) windowHandle = ScreenCapture.GetForegroundWindow(); if (windowHandle == IntPtr.Zero) return; Window window = new Window(windowHandle); WindowTitle.Text = window.Title; if (windowHandle != ScreenCapture.GetForegroundWindow())//Capturing background windows is buggy return; Pixels pix = capturer.Capture(windowHandle); //allocStats.Text = "Alloc:" + capturer.CacheMissAllocs + "/" + capturer.TotalAllocs; //bmp.Save("ScreenShot.bmp"); if (!Pixels.DataEquals(oldPixels, pix)) { frameCounter++; FrameCounterLabel.Text = frameCounter.ToString(); BoardInfo board = null; ImageToBoardInfo imageToBoardInfo = new ImageToBoardInfo(); if (!(found && pix.Width == size.Width && pix.Height == size.Height)) { found = imageToBoardInfo.GetBoardParameters(pix, out bp); size = pix.Size; } if (found) board = imageToBoardInfo.ProcessImage(bp, pix); if (board != null) { if (goRecorder != null) { goRecorder.Add(Duration, board); goRecorder.Replay.Save("Capture.GoVideo"); } GameState gameState = GoVideoToReplay.BoardToGameState(board); StateRenderer renderer = new StateRenderer(new GoClient.Drawing.GraphicsSystem()); renderer.BlockSize = 16; renderer.State = gameState; Preview.Image = ((GoClient.Drawing.Bitmap)renderer.Render()).InternalBitmap; } } ProcessingTime.Text = TS(DateTime.UtcNow - start0); timeLabel.Text = TimeSpan.FromSeconds(Math.Round(Duration.TotalSeconds)).ToString(); capturer.Release(oldPixels); oldPixels = pix; }
private void start_Click(object sender, EventArgs e) { AudioCheckBox.Enabled = false; RecordButton.Enabled = false; FinishButton.Enabled = true; goRecorder = new GoVideoRecorder(); RecordingStart = DateTime.UtcNow; timeLabel.Text = "Starting..."; frameCounter = 0; capturer.Release(oldPixels); oldPixels = Pixels.Null; if (AudioCheckBox.Checked) { audioRecorder = new Recorder(0.3f); audioRecorder.Paused = false; } }
public void Release(Pixels pix) { Release(pix.Data); }
public static Pixels CreateFromBitmap(Bitmap bmp) { Pixels pix = new Pixels(bmp.Width, bmp.Height); pix.LoadFromBitmap(bmp); return pix; }
public static bool DataEquals(Pixels pix1, Pixels pix2) { if (pix1.Width != pix2.Width || pix1.Height != pix2.Height) return false; if (pix1.Data == pix2.Data) return true; if (pix1.Data == null || pix2.Data == null) return false; int len = pix1.Width * pix1.Height; for (int i = 0; i < len; i++) if (pix1.Data[i] != pix2.Data[i]) return false; return true; }
RawColor[] RadiusColor(Pixels pix, Point center, int[,] radiusData, int maxRadius) { int[] counts = new int[maxRadius + 1]; int[] sumR = new int[maxRadius + 1]; int[] sumG = new int[maxRadius + 1]; int[] sumB = new int[maxRadius + 1]; RawColor[] result = new RawColor[maxRadius + 1]; int halfSize = (radiusData.GetLength(0) - 1) / 2; int dx = halfSize - center.X; int dy = halfSize - center.Y; int left = Math.Max(0, center.X - halfSize); int top = Math.Max(0, center.Y - halfSize); int right = Math.Min(pix.Width, center.X + halfSize + 1); int bottom = Math.Min(pix.Height, center.Y + halfSize + 1); for (int y = top; y < bottom; y++) for (int x = left; x < right; x++) { RawColor c = pix.Data[x, y]; int radius = radiusData[x + dx, y + dy]; counts[radius]++; sumR[radius] += c.R; sumG[radius] += c.G; sumB[radius] += c.B; } RawColor undefined = RawColor.Transparent; for (int i = 0; i < maxRadius + 1; i++) { if (counts[i] == 0) result[i] = undefined; else { result[i] = RawColor.FromRGB( (byte)(sumR[i] / counts[i]), (byte)(sumG[i] / counts[i]), (byte)(sumB[i] / counts[i])); } } return result; }
System.Drawing.Rectangle FindLinedBoard(Pixels pix, System.Drawing.Rectangle boardRect, out float[] grayCols, out float[] grayRows) { CountPixels(pix, boardRect, IsGray, out grayCols, out grayRows); float[] grayCols2 = grayCols; float[] grayRows2 = grayRows; int left = (int)grayCols.FirstIndex((f, i) => IsLine(grayCols2, i)); int right = (int)grayCols.LastIndex((f, i) => IsLine(grayCols2, i)) + 1; int top = (int)grayRows.FirstIndex((f, i) => IsLine(grayRows2, i)); int bottom = (int)grayRows.LastIndex((f, i) => IsLine(grayRows2, i)) + 1; return System.Drawing.Rectangle.FromLTRB(left, top, right, bottom); }
System.Drawing.Rectangle FindBoard(Pixels pix) { float[] boardCols, boardRows; CountPixels(pix, pix.Rect, IsBoard, out boardCols, out boardRows); float max = boardCols.Max(); if (max < 0.1) return System.Drawing.Rectangle.Empty; int left = (int)boardCols.FirstIndex(f => f >= 0.8f * max); int right = (int)boardCols.LastIndex(f => f >= 0.8f * max) + 1; CountPixels(pix, new System.Drawing.Rectangle(left, 0, right - left, pix.Height), IsBoard, out boardCols, out boardRows); max = boardRows.Max(); int top = (int)boardRows.FirstIndex(f => f >= 0.8f * max); int bottom = (int)boardRows.LastIndex(f => f >= 0.8f * max) + 1; return System.Drawing.Rectangle.FromLTRB(left, top, right, bottom); }
private void CountPixels(Pixels pix, System.Drawing.Rectangle rect, Predicate<RawColor> filter, out float[] cols, out float[] rows) { int[] colsI = new int[pix.Width]; int[] rowsI = new int[pix.Height]; for (int y = rect.Top; y < rect.Bottom; y++) { for (int x = rect.Left; x < rect.Right; x++) { RawColor c = pix.Data[x, y]; if (filter(c)) { colsI[x]++; rowsI[y]++; } } } cols = new float[pix.Width]; rows = new float[pix.Height]; for (int x = 0; x < cols.Length; x++) { if (x < rect.Left || x > rect.Right - 1) cols[x] = float.NaN; else cols[x] = (float)colsI[x] / rect.Height; } for (int y = 0; y < rows.Length; y++) { if (y < rect.Top || y > rect.Bottom - 1) rows[y] = float.NaN; else rows[y] = (float)rowsI[y] / rect.Width; } }