<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      玩轉你畫我猜(一):程序實現自動繪圖

      說明

        本文發布較早,查看 GitHub 項目了解最新動態。(2024 年 3 月 注)

      準備

        IDE:Visual Studio

        Language:VB.NET / C#

        GitHub:AutoPaint.NET

        通過編程實現自動畫畫,以后玩你畫我猜再也不用擔心被吐槽啦ヾ(???ゞ)

      第一節 導入圖片

        程序畫畫,首先得導入一張圖片作為模板。

        圖像格式

        我們選擇使用位圖,它是由像素數據定義的圖像格式

        WinForm 下使用封裝了 GDI+ 位圖的 System.Drawing.Bitmap 對象

        UWP 下可以使用 CanvasBitmap 對象(需要安裝 Win2D 的 Nuget 包)

        導入本地文件

        直接導入本地圖像資源

        詳情見 System.Drawing.Bitmap 構造函數

        使用屏幕截圖

        先用搜索引擎搜圖,然后直接截屏

        System.Drawing.Graphics 對象提供從屏幕到 Graphics 的位塊傳輸

        動態合成圖像

        比如合成文本或者圖案到指定的圖像上

        System.Drawing.Graphics 對象提供一系列的 GDI+ 繪圖命令

          ''' <summary>
          ''' 返回指定矩形區域的屏幕圖像
          ''' </summary>
          ''' <param name="rect">指定的矩形區域</param>
          ''' <returns></returns>
          Public Function GetScreenImage(ByVal rect As Rectangle) As Bitmap
              Dim resultBmp As New Bitmap(rect.Width, rect.Height)
              Using pg As Graphics = Graphics.FromImage(resultBmp)
                  pg.CopyFromScreen(rect.X, rect.Y, 0, 0, New Size(rect.Width, rect.Height))
              End Using
              Return resultBmp
          End Function
      VB.NET-GetScreenImage
          ''' <summary>
          ''' 返回指定文字生成的位圖
          ''' </summary>
          ''' <param name="text">文本</param>
          ''' <param name="font">字體</param>
          ''' <param name="width">位圖寬度</param>
          ''' <param name="height">位圖高度</param>
          ''' <returns></returns>
          Public Function GetTextImage(ByVal text As String, ByVal font As Font, ByVal width As Integer, ByVal height As Integer) As Bitmap
              Dim resultBmp As New Bitmap(width, height)
              Using pg = Graphics.FromImage(resultBmp)
                  pg.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias '抗鋸齒
                  pg.DrawString(text, font, Brushes.Black, 0, 0)
              End Using
              Return resultBmp
          End Function
      VB.NET-GetTextImage
      /// <summary>
      /// 返回指定矩形區域的屏幕圖像
      /// </summary>
      /// <param name="rect">指定的矩形區域</param>
      /// <returns></returns>
      public Bitmap GetScreenImage(Rectangle rect)
      {
          Bitmap resultBmp = new Bitmap(rect.Width, rect.Height);
          using (Graphics pg = Graphics.FromImage(resultBmp)) {
              pg.CopyFromScreen(rect.X, rect.Y, 0, 0, new Size(rect.Width, rect.Height));
          }
          return resultBmp;
      }
      C#-GetScreenImage
      /// <summary>
      /// 返回指定文字生成的位圖
      /// </summary>
      /// <param name="text">文本</param>
      /// <param name="font">字體</param>
      /// <param name="width">位圖寬度</param>
      /// <param name="height">位圖高度</param>
      /// <returns></returns>
      public Bitmap GetTextImage(string text, Font font, int width, int height)
      {
          Bitmap resultBmp = new Bitmap(width, height);
          using (pg == Graphics.FromImage(resultBmp)) {
              pg.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias;
              //抗鋸齒
              pg.DrawString(text, font, Brushes.Black, 0, 0);
          }
          return resultBmp;
      }
      C#-GetTextImage

      第二節 圖像處理

        接下來對模板圖像進行處理,以便于下一步的軌跡尋找。

            二值化

        基于一個閾值 T,大于 T 的像素群設定為白色,小于 T 的像素群設定為黑色

        也就是將整個圖像呈現出明顯的只有黑和白的視覺效果

      圖2-1 全局二值化

       

            細化

        將粗線條細化為細線條(線條寬度通常為一像素)

        細化算法是為了找出圖像的輪廓,對不同圖像的效果不同

      圖2-2 輪廓化

       

      ''' <summary>
      ''' 提供對位圖圖像和顏色的一系列操作的對象
      ''' </summary>
      Public Class ImageProcess
          ''' <summary> 
          ''' 基于RGB根據指定閾值判斷兩個顏色是否相近
          ''' </summary> 
          Public Function CompareRGB(ByVal Color1 As Color, ByVal Color2 As Color, ByVal Distance As Single) As Boolean
              Dim r As Integer = Int(Color1.R) - Int(Color2.R)
              Dim g As Integer = Int(Color1.G) - Int(Color2.G)
              Dim b As Integer = Int(Color1.B) - Int(Color2.B)
              Dim absDis As Integer = Math.Sqrt(r * r + g * g + b * b)
              If absDis < Distance Then
                  Return True
              Else
                  Return False
              End If
          End Function
          ''' <summary> 
          ''' 基于HSB根據指定閾值判斷兩個顏色是否相近
          ''' </summary> 
          Public Function CompareHSB(ByVal Color1 As Color, ByVal Color2 As Color, ByVal Distance As Single) As Boolean
              '向量距離
              'Dim h As Single = (Color1.GetHue - Color2.GetHue) / 360
              'Dim s As Single = Color1.GetSaturation - Color2.GetSaturation
              'Dim b As Single = Color1.GetBrightness - Color2.GetBrightness
              'Dim absDis As Single = Math.Sqrt(h * h + s * s + b * b)
              'If absDis < Distance Then
              '    Return True
              'Else
              '    Return False
              'End If
              '向量夾角
              Dim h1 As Single = Color1.GetHue / 360
              Dim s1 As Single = Color1.GetSaturation
              Dim b1 As Single = Color1.GetBrightness
              Dim h2 As Single = Color2.GetHue / 360
              Dim s2 As Single = Color2.GetSaturation
              Dim b2 As Single = Color2.GetBrightness
              Dim absDis As Single = (h1 * h2 + s1 * s2 + b1 * b2) / (Math.Sqrt(h1 * h1 + s1 * s1 + b1 * b1) * Math.Sqrt(h2 * h2 + s2 * s2 + b2 * b2))
              If absDis > Distance / 5 + 0.8 Then
                  Return True
              Else
                  Return False
              End If
          End Function
          ''' <summary> 
          ''' 返回指定顏色的中值
          ''' </summary> 
          Public Function gethHD(ByVal color1 As Color)
              Dim HD, r, g, b As Integer
              r = color1.R
              g = color1.G
              b = color1.B
              HD = (r + g + b) / 3
              Return HD
          End Function
          ''' <summary>
          ''' 返回指定位圖的顏色數組
          ''' </summary>
          ''' <param name="gBitmap"></param>
          ''' <returns></returns>
          Public Function GetColorArr(ByRef gBitmap As Bitmap) As Color(,)
              Dim TempArr(gBitmap.Width - 1, gBitmap.Height - 1) As Color
              For i = 0 To gBitmap.Width - 1
                  For j = 0 To gBitmap.Height - 1
                      TempArr(i, j) = gBitmap.GetPixel(i, j)
                  Next
              Next
              Return TempArr
          End Function
          ''' <summary>
          ''' 返回指定矩形區域的屏幕圖像
          ''' </summary>
          ''' <param name="rect">指定的矩形區域</param>
          ''' <returns></returns>
          Public Function GetScreenImage(ByVal rect As Rectangle) As Bitmap
              Dim resultBmp As New Bitmap(rect.Width, rect.Height)
              Using pg As Graphics = Graphics.FromImage(resultBmp)
                  pg.CopyFromScreen(rect.X, rect.Y, 0, 0, New Size(rect.Width, rect.Height))
              End Using
              Return resultBmp
          End Function
          ''' <summary>
          ''' 返回指定文字生成的位圖
          ''' </summary>
          ''' <param name="text">文本</param>
          ''' <param name="font">字體</param>
          ''' <param name="width">位圖寬度</param>
          ''' <param name="height">位圖高度</param>
          ''' <returns></returns>
          Public Function GetTextImage(ByVal text As String, ByVal font As Font, ByVal width As Integer, ByVal height As Integer) As Bitmap
              Dim resultBmp As New Bitmap(width, height)
              Using pg = Graphics.FromImage(resultBmp)
                  pg.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias '抗鋸齒
                  pg.DrawString(text, font, Brushes.Black, 0, 0)
              End Using
              Return resultBmp
          End Function
          ''' <summary>
          ''' 返回指定圖位圖的二值化圖像
          ''' </summary>
          ''' <param name="gBitmap"></param>
          ''' <param name="gSplitNum"></param>
          ''' <returns></returns>
          Public Function GetThresholdImage(ByVal gBitmap As Bitmap, ByVal gSplitNum As Single, Optional IsHSB As Boolean = False) As Bitmap
              Dim ResultBitmap As New Bitmap(gBitmap.Width, gBitmap.Height)
              Dim ColorArr(,) = GetColorArr(gBitmap)
              Dim TempHD As Integer
              Dim IsOverThreshold = Function(ByVal C1 As Color, ByVal gNum As Single)
                                        TempHD = gethHD(C1)
                                        Return (If(IsHSB, (C1.GetHue / 360 + C1.GetSaturation + C1.GetBrightness) / 3 < gNum,
                                        TempHD < gNum))
                                    End Function
              For i = 0 To gBitmap.Width - 1
                  For j = 0 To gBitmap.Height - 1
                      ResultBitmap.SetPixel(i, j, If(IsOverThreshold(ColorArr(i, j), gSplitNum), Color.Black, Color.White))
                  Next
              Next
      
              Return ResultBitmap
          End Function
          ''' <summary>
          ''' 返回指定位圖的輪廓圖像
          ''' </summary>
          ''' <param name="gBitmap"></param>
          ''' <param name="gDistance"></param>
          ''' <returns></returns>
          Public Function GetOutLineImage(ByVal gBitmap As Bitmap, ByVal gDistance As Single, Optional IsHSB As Boolean = False) As Bitmap
              Dim xArray2() As Short = {0, 1, 0, -1}
              Dim yArray2() As Short = {-1, 0, 1, 0}
              'Dim ResultBitmap As New Bitmap(gBitmap) '在原圖的基礎上繪圖
              Dim ResultBitmap As New Bitmap(gBitmap.Width, gBitmap.Height)
              Dim Color1, Color2 As Color
              Dim CompareColor = Function(ByVal C1 As Color, ByVal C2 As Color, ByVal Distance As Single)
                                     Return If(IsHSB,
                                     CompareHSB(Color1, Color2, Distance),
                                     CompareRGB(Color1, Color2, Distance))
                                 End Function
              Dim CompareColorExtra = Function(ByVal C1 As Color, ByVal C2 As Color)
                                          Return If(IsHSB,
                                          Color1.GetBrightness - Color2.GetBrightness > 0,
                                          gethHD(Color1) - gethHD(Color2) > 0)
                                      End Function
              Dim ColorArr(,) = GetColorArr(gBitmap)
              For i = 1 To gBitmap.Width - 2
                  For j = 1 To gBitmap.Height - 2
                      ResultBitmap.SetPixel(i, j, Color.White)
                      Color1 = ColorArr(i, j)
                      For p = 0 To 3
                          Color2 = ColorArr(i + xArray2(p), j + yArray2(p))
                          If Not CompareColor(Color1, Color2, gDistance) And CompareColorExtra(Color1, Color2) Then
                              ResultBitmap.SetPixel(i, j, Color.Black)
                              ' ResultBitmap.SetPixel(i, j, ColorArr(i, j))
                          End If
                      Next
                  Next
              Next
              Return ResultBitmap
          End Function
          ''' <summary>
          ''' 返回指定位圖的空心圖像
          ''' </summary>
          ''' <param name="gBitmap"></param>
          ''' <returns></returns>
          Public Function GetAroundImage(gBitmap As Bitmap)
              Dim ResultBitmap As New Bitmap(gBitmap.Width, gBitmap.Height)
              Dim ImageBolArr(,) As Integer = GetImageBol(gBitmap)
              For i = 0 To gBitmap.Width - 1
                  For j = 0 To gBitmap.Height - 1
                      If ImageBolArr(i, j) = 1 AndAlso CheckPointAround(ImageBolArr, i, j) = False Then
                          ResultBitmap.SetPixel(i, j, Color.Black)
                      Else
                          ResultBitmap.SetPixel(i, j, Color.White)
                      End If
                  Next
              Next
              Return ResultBitmap
          End Function
          ''' <summary>
          ''' 返回指定位圖的反相圖像
          ''' </summary>
          ''' <param name="gBitmap"></param>
          ''' <returns></returns>
          Public Function GetInvertImage(gBitmap As Bitmap)
              Dim ResultBitmap As New Bitmap(gBitmap.Width, gBitmap.Height)
              Dim ImageBolArr(,) As Integer = GetImageBol(gBitmap)
              For i = 0 To gBitmap.Width - 1
                  For j = 0 To gBitmap.Height - 1
                      If ImageBolArr(i, j) = 1 Then
                          ResultBitmap.SetPixel(i, j, Color.White)
                      Else
                          ResultBitmap.SetPixel(i, j, Color.Black)
                      End If
                  Next
              Next
              Return ResultBitmap
          End Function
          ''' <summary>
          ''' 返回指定位圖的色塊圖像
          ''' </summary>
          ''' <param name="gBitmap"></param>
          ''' <returns></returns>
          Public Function GetLumpImage(gBitmap As Bitmap, Optional Range As Integer = 10)
              Dim ResultBitmap As New Bitmap(gBitmap.Width, gBitmap.Height)
              Dim ColorArr(,) = GetColorArr(gBitmap)
              Dim R, G, B As Integer
              For i = 0 To gBitmap.Width - 1
                  For j = 0 To gBitmap.Height - 1
                      R = Int(ColorArr(i, j).R / Range) * Range
                      G = Int(ColorArr(i, j).G / Range) * Range
                      B = Int(ColorArr(i, j).B / Range) * Range
                      ResultBitmap.SetPixel(i, j, Color.FromArgb(R, G, B))
                  Next
              Next
              Return ResultBitmap
          End Function
          ''' <summary>
          ''' 返回指定位圖的二值化數據
          ''' </summary>
          ''' <param name="gBitmap"></param>
          ''' <returns></returns>
          Private Function GetImageBol(ByVal gBitmap As Bitmap) As Integer(,)
              Dim ResultArr(gBitmap.Width - 1, gBitmap.Height - 1) As Integer
              For i = 0 To gBitmap.Width - 1
                  For j = 0 To gBitmap.Height - 1
                      If Not gBitmap.GetPixel(i, j).Equals(Color.FromArgb(255, 255, 255)) Then
                          ResultArr(i, j) = 1
                      Else
                          ResultArr(i, j) = 0
                      End If
                  Next
              Next
              Return ResultArr
          End Function
          ''' <summary>
          ''' 檢查一個點是否被包圍
          ''' </summary>
          ''' <param name="BolArr"></param>
          ''' <param name="x"></param>
          ''' <param name="y"></param>
          ''' <returns></returns>
          Private Function CheckPointAround(BolArr As Integer(,), ByVal x As Integer, ByVal y As Integer) As Boolean
              If Not (x > 0 And y > 0 And x < BolArr.GetUpperBound(0) And y < BolArr.GetUpperBound(1)) Then Return True
              If BolArr(x - 1, y) = 1 And BolArr(x + 1, y) = 1 And BolArr(x, y - 1) = 1 And BolArr(x, y + 1) = 1 Then
                  Return True '當前點為實體內部
              Else
                  Return False '當前點為實體邊緣
              End If
          End Function
      End Class
      VB.NET-ImageProcess
      using System;
      using System.Drawing;
      using System.Collections;
      using System.Collections.Generic;
      using System.Data;
      using System.Diagnostics;
      /// <summary>
      /// 提供對位圖圖像和顏色的一系列操作的對象
      /// </summary>
      public class ImageProcess
      {
          /// <summary> 
          /// 基于RGB根據指定閾值判斷兩個顏色是否相近
          /// </summary> 
          public bool CompareRGB(Color Color1, Color Color2, float Distance)
          {
              int r = Conversion.Int(Color1.R) - Conversion.Int(Color2.R);
              int g = Conversion.Int(Color1.G) - Conversion.Int(Color2.G);
              int b = Conversion.Int(Color1.B) - Conversion.Int(Color2.B);
              int absDis = Math.Sqrt(r * r + g * g + b * b);
              if (absDis < Distance) {
                  return true;
              } else {
                  return false;
              }
          }
          /// <summary> 
          /// 基于HSB根據指定閾值判斷兩個顏色是否相近
          /// </summary> 
          public bool CompareHSB(Color Color1, Color Color2, float Distance)
          {
              //向量距離
              //Dim h As Single = (Color1.GetHue - Color2.GetHue) / 360
              //Dim s As Single = Color1.GetSaturation - Color2.GetSaturation
              //Dim b As Single = Color1.GetBrightness - Color2.GetBrightness
              //Dim absDis As Single = Math.Sqrt(h * h + s * s + b * b)
              //If absDis < Distance Then
              //    Return True
              //Else
              //    Return False
              //End If
              //向量夾角
              float h1 = Color1.GetHue / 360;
              float s1 = Color1.GetSaturation;
              float b1 = Color1.GetBrightness;
              float h2 = Color2.GetHue / 360;
              float s2 = Color2.GetSaturation;
              float b2 = Color2.GetBrightness;
              float absDis = (h1 * h2 + s1 * s2 + b1 * b2) / (Math.Sqrt(h1 * h1 + s1 * s1 + b1 * b1) * Math.Sqrt(h2 * h2 + s2 * s2 + b2 * b2));
              if (absDis > Distance / 5 + 0.8) {
                  return true;
              } else {
                  return false;
              }
          }
          /// <summary> 
          /// 返回指定顏色的中值
          /// </summary> 
          public object gethHD(Color color1)
          {
              int HD = 0;
              int r = 0;
              int g = 0;
              int b = 0;
              r = color1.R;
              g = color1.G;
              b = color1.B;
              HD = (r + g + b) / 3;
              return HD;
          }
          /// <summary>
          /// 返回指定位圖的顏色數組
          /// </summary>
          /// <param name="gBitmap"></param>
          /// <returns></returns>
          public Color[,] GetColorArr(ref Bitmap gBitmap)
          {
              Color[,] TempArr = new Color[gBitmap.Width, gBitmap.Height];
              for (i = 0; i <= gBitmap.Width - 1; i++) {
                  for (j = 0; j <= gBitmap.Height - 1; j++) {
                      TempArr(i, j) = gBitmap.GetPixel(i, j);
                  }
              }
              return TempArr;
          }
          /// <summary>
          /// 返回指定矩形區域的屏幕圖像
          /// </summary>
          /// <param name="rect">指定的矩形區域</param>
          /// <returns></returns>
          public Bitmap GetScreenImage(Rectangle rect)
          {
              Bitmap resultBmp = new Bitmap(rect.Width, rect.Height);
              using (Graphics pg = Graphics.FromImage(resultBmp)) {
                  pg.CopyFromScreen(rect.X, rect.Y, 0, 0, new Size(rect.Width, rect.Height));
              }
              return resultBmp;
          }
          /// <summary>
          /// 返回指定文字生成的位圖
          /// </summary>
          /// <param name="text">文本</param>
          /// <param name="font">字體</param>
          /// <param name="width">位圖寬度</param>
          /// <param name="height">位圖高度</param>
          /// <returns></returns>
          public Bitmap GetTextImage(string text, Font font, int width, int height)
          {
              Bitmap resultBmp = new Bitmap(width, height);
              using (pg == Graphics.FromImage(resultBmp)) {
                  pg.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias;
                  //抗鋸齒
                  pg.DrawString(text, font, Brushes.Black, 0, 0);
              }
              return resultBmp;
          }
          /// <summary>
          /// 返回指定圖位圖的二值化圖像
          /// </summary>
          /// <param name="gBitmap"></param>
          /// <param name="gSplitNum"></param>
          /// <returns></returns>
          public Bitmap GetThresholdImage(Bitmap gBitmap, float gSplitNum, bool IsHSB = false)
          {
              Bitmap ResultBitmap = new Bitmap(gBitmap.Width, gBitmap.Height);
              [,] ColorArr = GetColorArr(ref gBitmap);
              int TempHD = 0;
              dynamic IsOverThreshold = (Color C1, float gNum) =>
              {
                  TempHD = gethHD(C1);
                  return (IsHSB ? (C1.GetHue / 360 + C1.GetSaturation + C1.GetBrightness) / 3 < gNum : TempHD < gNum);
              };
              for (i = 0; i <= gBitmap.Width - 1; i++) {
                  for (j = 0; j <= gBitmap.Height - 1; j++) {
                      ResultBitmap.SetPixel(i, j, IsOverThreshold(ColorArr(i, j), gSplitNum) ? Color.Black : Color.White);
                  }
              }
      
              return ResultBitmap;
          }
          /// <summary>
          /// 返回指定位圖的輪廓圖像
          /// </summary>
          /// <param name="gBitmap"></param>
          /// <param name="gDistance"></param>
          /// <returns></returns>
          public Bitmap GetOutLineImage(Bitmap gBitmap, float gDistance, bool IsHSB = false)
          {
              short[] xArray2 = {
                  0,
                  1,
                  0,
                  -1
              };
              short[] yArray2 = {
                  -1,
                  0,
                  1,
                  0
              };
              //Dim ResultBitmap As New Bitmap(gBitmap) '在原圖的基礎上繪圖
              Bitmap ResultBitmap = new Bitmap(gBitmap.Width, gBitmap.Height);
              Color Color1 = default(Color);
              Color Color2 = default(Color);
              dynamic CompareColor = (Color C1, Color C2, float Distance) => { return IsHSB ? CompareHSB(Color1, Color2, Distance) : CompareRGB(Color1, Color2, Distance); };
              dynamic CompareColorExtra = (Color C1, Color C2) => { return IsHSB ? Color1.GetBrightness - Color2.GetBrightness > 0 : gethHD(Color1) - gethHD(Color2) > 0; };
              [,] ColorArr = GetColorArr(ref gBitmap);
              for (i = 1; i <= gBitmap.Width - 2; i++) {
                  for (j = 1; j <= gBitmap.Height - 2; j++) {
                      ResultBitmap.SetPixel(i, j, Color.White);
                      Color1 = ColorArr(i, j);
                      for (p = 0; p <= 3; p++) {
                          Color2 = ColorArr(i + xArray2[p], j + yArray2[p]);
                          if (!CompareColor(Color1, Color2, gDistance) & CompareColorExtra(Color1, Color2)) {
                              ResultBitmap.SetPixel(i, j, Color.Black);
                              // ResultBitmap.SetPixel(i, j, ColorArr(i, j))
                          }
                      }
                  }
              }
              return ResultBitmap;
          }
          /// <summary>
          /// 返回指定位圖的空心圖像
          /// </summary>
          /// <param name="gBitmap"></param>
          /// <returns></returns>
          public object GetAroundImage(Bitmap gBitmap)
          {
              Bitmap ResultBitmap = new Bitmap(gBitmap.Width, gBitmap.Height);
              int[,] ImageBolArr = GetImageBol(gBitmap);
              for (i = 0; i <= gBitmap.Width - 1; i++) {
                  for (j = 0; j <= gBitmap.Height - 1; j++) {
                      if (ImageBolArr[i, j] == 1 && CheckPointAround(ImageBolArr, i, j) == false) {
                          ResultBitmap.SetPixel(i, j, Color.Black);
                      } else {
                          ResultBitmap.SetPixel(i, j, Color.White);
                      }
                  }
              }
              return ResultBitmap;
          }
          /// <summary>
          /// 返回指定位圖的反相圖像
          /// </summary>
          /// <param name="gBitmap"></param>
          /// <returns></returns>
          public object GetInvertImage(Bitmap gBitmap)
          {
              Bitmap ResultBitmap = new Bitmap(gBitmap.Width, gBitmap.Height);
              int[,] ImageBolArr = GetImageBol(gBitmap);
              for (i = 0; i <= gBitmap.Width - 1; i++) {
                  for (j = 0; j <= gBitmap.Height - 1; j++) {
                      if (ImageBolArr[i, j] == 1) {
                          ResultBitmap.SetPixel(i, j, Color.White);
                      } else {
                          ResultBitmap.SetPixel(i, j, Color.Black);
                      }
                  }
              }
              return ResultBitmap;
          }
          /// <summary>
          /// 返回指定位圖的色塊圖像
          /// </summary>
          /// <param name="gBitmap"></param>
          /// <returns></returns>
          public object GetLumpImage(Bitmap gBitmap, int Range = 10)
          {
              Bitmap ResultBitmap = new Bitmap(gBitmap.Width, gBitmap.Height);
              [,] ColorArr = GetColorArr(ref gBitmap);
              int R = 0;
              int G = 0;
              int B = 0;
              for (i = 0; i <= gBitmap.Width - 1; i++) {
                  for (j = 0; j <= gBitmap.Height - 1; j++) {
                      R = Conversion.Int(ColorArr(i, j).R / Range) * Range;
                      G = Conversion.Int(ColorArr(i, j).G / Range) * Range;
                      B = Conversion.Int(ColorArr(i, j).B / Range) * Range;
                      ResultBitmap.SetPixel(i, j, Color.FromArgb(R, G, B));
                  }
              }
              return ResultBitmap;
          }
          /// <summary>
          /// 返回指定位圖的二值化數據
          /// </summary>
          /// <param name="gBitmap"></param>
          /// <returns></returns>
          private int[,] GetImageBol(Bitmap gBitmap)
          {
              int[,] ResultArr = new int[gBitmap.Width, gBitmap.Height];
              for (i = 0; i <= gBitmap.Width - 1; i++) {
                  for (j = 0; j <= gBitmap.Height - 1; j++) {
                      if (!gBitmap.GetPixel(i, j).Equals(Color.FromArgb(255, 255, 255))) {
                          ResultArr[i, j] = 1;
                      } else {
                          ResultArr[i, j] = 0;
                      }
                  }
              }
              return ResultArr;
          }
          /// <summary>
          /// 檢查一個點是否被包圍
          /// </summary>
          /// <param name="BolArr"></param>
          /// <param name="x"></param>
          /// <param name="y"></param>
          /// <returns></returns>
          private bool CheckPointAround(int[,] BolArr, int x, int y)
          {
              if (!(x > 0 & y > 0 & x < BolArr.GetUpperBound(0) & y < BolArr.GetUpperBound(1)))
                  return true;
              if (BolArr[x - 1, y] == 1 & BolArr[x + 1, y] == 1 & BolArr[x, y - 1] == 1 & BolArr[x, y + 1] == 1) {
                  return true;
                  //當前點為實體內部
              } else {
                  return false;
                  //當前點為實體邊緣
              }
          }
      }
      C#-ImageProcess

      第三節 畫筆軌跡

        從非黑即白的像素數據中計算出軌跡。

            遞歸循跡

        首先將圖像的二值化數據保存在一個二維數組里

        程序繪圖時僅繪制值為 1 的元素所對應的位置

        然后尋找畫筆起始位置,依次檢查每個位置,當對應值為1時該點即為起點

        最后遞歸檢查每一個鄰居點,同步模擬鼠標操作

            空心軌跡

        只要某像素位置的上下左右位置均為 1 即認為該點在實體內部

        繪制時跳過該像素就可以實現空心(主要用于空心字體的繪制)

      ''' <summary>
      ''' 提供由圖像循跡生成繪圖序列的對象
      ''' </summary>
      Public Class SequenceManager
          ''' <summary>
          ''' 繪制序列的集合
          ''' </summary>
          Public SequenceList As List(Of PointSequence)
      
          Public Sub New(BolArr(,) As Integer)
              SequenceList = New List(Of PointSequence)
              CalculateSequence(BolArr)
          End Sub
          ''' <summary>
          ''' 創建新的序列
          ''' </summary>
          Private Sub CreateNewSequence()
              SequenceList.Add(New PointSequence)
          End Sub
          ''' <summary>
          ''' 添加新的位置
          ''' </summary>
          Private Sub AddPoint(point As PointF)
              SequenceList.Last.PointList.Add(point)
          End Sub
          Dim xArray() As Integer = {-1, 0, 1, 1, 1, 0, -1, -1}
          Dim yArray() As Integer = {-1, -1, -1, 0, 1, 1, 1, 0}
          Dim NewStart As Boolean
          ''' <summary>
          ''' 遞歸循跡
          ''' </summary>
          Private Sub CheckMove(ByRef BolArr(,) As Integer, ByVal x As Integer, ByVal y As Integer, ByVal StepNum As Integer)
              Application.DoEvents() '處理主線程消息
              If StepNum > 10000 Then Return
              Dim xBound As Integer = BolArr.GetUpperBound(0)
              Dim yBound As Integer = BolArr.GetUpperBound(1)
              Dim dx, dy As Integer
              Dim AroundValue As Integer = GetAroundValue(BolArr, x, y)
              If AroundValue > 2 AndAlso AroundValue < 8 Then
                  Return
              End If
              For i = 0 To 7
                  dx = x + xArray(i)
                  dy = y + yArray(i)
                  If Not (dx > 0 And dy > 0 And dx < xBound And dy < yBound) Then
                      Return
                  ElseIf BolArr(dx, dy) = 1 Then
                      BolArr(dx, dy) = 0
                      If NewStart = True Then
                          Me.CreateNewSequence()
                          Me.AddPoint(New PointF(dx, dy))
                          NewStart = False
                      Else
                          Me.AddPoint(New PointF(dx, dy))
                      End If
                      CheckMove(BolArr, dx, dy, StepNum + 1)
                      NewStart = True
                  End If
              Next
          End Sub
          ''' <summary>
          ''' 計算序列
          ''' </summary>
          Private Sub CalculateSequence(BolArr(,) As Integer)
              Dim xCount As Integer = BolArr.GetUpperBound(0)
              Dim yCount As Integer = BolArr.GetUpperBound(1)
              Dim CP As New Point(xCount / 2, yCount / 2)
              Dim R As Integer = 0
              For R = 0 To If(xCount > yCount, xCount, yCount)
                  For Theat = 0 To Math.PI * 2 Step 1 / R
                      Dim dx As Integer = CP.X + R * Math.Cos(Theat)
                      Dim dy As Integer = CP.Y + R * Math.Sin(Theat)
                      If Not (dx > 0 And dy > 0 And dx < xCount And dy < yCount) Then Continue For
                      If BolArr(dx, dy) = 1 Then
                          BolArr(dx, dy) = 0
                          Me.CreateNewSequence()
                          Me.AddPoint(New PointF(dx, dy))
                          CheckMove(BolArr, dx, dy, 0)
                          NewStart = True
                      End If
                  Next
              Next
          End Sub
          ''' <summary>
          ''' 返回指定像素位置的權值
          ''' </summary>
          Private Function GetAroundValue(ByRef BolArr(,) As Integer, ByVal x As Integer, ByVal y As Integer) As Integer
              Dim dx, dy, ResultValue As Integer
              Dim xBound As Integer = BolArr.GetUpperBound(0)
              Dim yBound As Integer = BolArr.GetUpperBound(1)
              For i = 0 To 7
                  dx = x + xArray(i)
                  dy = y + yArray(i)
                  If dx > 0 And dy > 0 And dx < xBound And dy < yBound Then
                      If BolArr(dx, dy) = 1 Then
                          ResultValue += 1
                      End If
                  End If
              Next
              Return ResultValue
          End Function
      End Class
      VB.NET-SequenceManager
      ''' <summary>
      ''' 表示一條畫圖曲線的繪制序列
      ''' </summary>
      Public Class PointSequence
          Public PointList As New List(Of PointF)
      End Class
      VB.NET-PointSequence
      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.Data;
      using System.Diagnostics;
      /// <summary>
      /// 提供由圖像循跡生成繪圖序列的對象
      /// </summary>
      public class SequenceManager
      {
          /// <summary>
          /// 繪制序列的集合
          /// </summary>
      
          public List<PointSequence> SequenceList;
          public SequenceManager(int[,] BolArr)
          {
              SequenceList = new List<PointSequence>();
              CalculateSequence(BolArr);
          }
          /// <summary>
          /// 創建新的序列
          /// </summary>
          private void CreateNewSequence()
          {
              SequenceList.Add(new PointSequence());
          }
          /// <summary>
          /// 添加新的位置
          /// </summary>
          private void AddPoint(PointF point)
          {
              SequenceList.Last.PointList.Add(point);
          }
          int[] xArray = {
              -1,
              0,
              1,
              1,
              1,
              0,
              -1,
              -1
          };
          int[] yArray = {
              -1,
              -1,
              -1,
              0,
              1,
              1,
              1,
              0
          };
          bool NewStart;
          /// <summary>
          /// 遞歸循跡
          /// </summary>
          private void CheckMove(ref int[,] BolArr, int x, int y, int StepNum)
          {
              Application.DoEvents();
              //處理主線程消息
              if (StepNum > 10000)
                  return;
              int xBound = BolArr.GetUpperBound(0);
              int yBound = BolArr.GetUpperBound(1);
              int dx = 0;
              int dy = 0;
              int AroundValue = GetAroundValue(ref BolArr, x, y);
              if (AroundValue > 2 && AroundValue < 8) {
                  return;
              }
              for (i = 0; i <= 7; i++) {
                  dx = x + xArray[i];
                  dy = y + yArray[i];
                  if (!(dx > 0 & dy > 0 & dx < xBound & dy < yBound)) {
                      return;
                  } else if (BolArr[dx, dy] == 1) {
                      BolArr[dx, dy] = 0;
                      if (NewStart == true) {
                          this.CreateNewSequence();
                          this.AddPoint(new PointF(dx, dy));
                          NewStart = false;
                      } else {
                          this.AddPoint(new PointF(dx, dy));
                      }
                      CheckMove(ref BolArr, dx, dy, StepNum + 1);
                      NewStart = true;
                  }
              }
          }
          /// <summary>
          /// 計算序列
          /// </summary>
          private void CalculateSequence(int[,] BolArr)
          {
              int xCount = BolArr.GetUpperBound(0);
              int yCount = BolArr.GetUpperBound(1);
              Point CP = new Point(xCount / 2, yCount / 2);
              int R = 0;
              for (R = 0; R <= xCount > yCount ? xCount : yCount; R++) {
                  for (Theat = 0; Theat <= Math.PI * 2; Theat += 1 / R) {
                      int dx = CP.X + R * Math.Cos(Theat);
                      int dy = CP.Y + R * Math.Sin(Theat);
                      if (!(dx > 0 & dy > 0 & dx < xCount & dy < yCount))
                          continue;
                      if (BolArr[dx, dy] == 1) {
                          BolArr[dx, dy] = 0;
                          this.CreateNewSequence();
                          this.AddPoint(new PointF(dx, dy));
                          CheckMove(ref BolArr, dx, dy, 0);
                          NewStart = true;
                      }
                  }
              }
          }
          /// <summary>
          /// 返回指定像素位置的權值
          /// </summary>
          private int GetAroundValue(ref int[,] BolArr, int x, int y)
          {
              int dx = 0;
              int dy = 0;
              int ResultValue = 0;
              int xBound = BolArr.GetUpperBound(0);
              int yBound = BolArr.GetUpperBound(1);
              for (i = 0; i <= 7; i++) {
                  dx = x + xArray[i];
                  dy = y + yArray[i];
                  if (dx > 0 & dy > 0 & dx < xBound & dy < yBound) {
                      if (BolArr[dx, dy] == 1) {
                          ResultValue += 1;
                      }
                  }
              }
              return ResultValue;
          }
      }
      C#-SequenceManager
      using System;
      using System.Collections.Generic;
      /// <summary>
      /// 表示一條畫圖曲線的繪制序列
      /// </summary>
      public class PointSequence
      {
          public List<PointF> PointList = new List<PointF>();
      }
      C#-PointSequence

      第四節 繪圖

        最后,控制鼠標在畫板上依次畫出線條序列即可。

        光標按鍵控制

        調用 user32.dll 庫下的 mouse_event() ,它提供綜合的光標擊鍵和光標動作模擬

          光標指針移動

        System.Windows.Forms.Cursor 對象提供對系統光標的訪問

        直接對 Cursor.Position 賦值就能控制指針坐標

        也可以調用 user32.dll 庫下的 SetCursorPos() 實現模擬光標移動

        Windows畫板的局限性

        至此,我們的程序已經可以通過控制光標在 Windows 畫板上實現自動繪圖

        但由于畫板短時間內不能響應過多的 Windows 消息,導致畫圖速度不能過快

        同時程序也很難控制畫筆的筆觸大小與色彩

           Private Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Int32, ByVal dx As Int32, ByVal dy As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32)
          Private Declare Function SetCursorPos Lib "user32" (ByVal x As Integer, ByVal y As Integer) As Integer
          ''' <summary>
          ''' 模擬鼠標左鍵按下或彈起
          ''' </summary>
          ''' <param name="dx"></param>
          ''' <param name="dy"></param>
          ''' <param name="type"></param>
          Private Sub MouseDownUp(ByVal dx As Integer, ByVal dy As Integer, ByVal type As Boolean)
              If type Then '按下
                  mouse_event(&H2, 0, 0, 0, IntPtr.Zero)
              Else '彈起
                  mouse_event(&H4, 0, 0, 0, IntPtr.Zero)
              End If
          End Sub
          ''' <summary>
          ''' 模擬鼠標移動
          ''' </summary>
          ''' <param name="dx"></param>
          ''' <param name="dy"></param>
          Private Sub MouseMove(ByVal dx As Integer, ByVal dy As Integer)
              Cursor.Position = New Point(dx, dy)
          End Sub
      VB.NET-MouseControl
      using System.Runtime.InteropServices;
              [DllImport("user32")]
              public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
      private void MouseDownUp(int dx, int dy, bool type)
      {
          //按下
          if (type) {
              mouse_event(0x2, 0, 0, 0, IntPtr.Zero);
          //彈起
          } else {
              mouse_event(0x4, 0, 0, 0, IntPtr.Zero);
          }
      }
      /// <summary>
      /// 模擬鼠標移動
      /// </summary>
      /// <param name="dx"></param>
      /// <param name="dy"></param>
      private void MouseMove(int dx, int dy)
      {
          Cursor.Position = new Point(dx, dy);
      }
      C#-MouseControl

      視頻

      附錄

        后續文章:更優秀的自動繪圖程序

        后續文章:兒童涂鴉遇上程序繪圖

        后續文章:程序如何畫動漫美少

      posted @ 2015-05-12 22:36  ExperDot  閱讀(16999)  評論(7)    收藏  舉報
      主站蜘蛛池模板: 99热门精品一区二区三区无码| 在线观看精品视频网站| 四虎成人在线观看免费| 蜜臀av在线观看| 久久久久久久久久久久中文字幕| 国产精品国产精品国产精品| 99久久亚洲综合精品成人网| 男女啪啪免费观看网站| 久久亚洲精品无码播放| 国产精品成人av在线观看春天| 亚洲综合色网一区二区三区| 国产精品中文字幕日韩| 国产伦精品一区二区三区妓女下载| 九九热在线视频免费观看| 精品免费看国产一区二区| 野花社区www视频日本| 伊人欧美在线| 黄频在线播放观看免费| 国产中文字幕在线一区| 久久国产精品乱子乱精品| 99在线视频免费观看| 日韩精品av一区二区三区| 日韩精品无遮挡在线观看| 国产福利精品一区二区| 99久久无色码中文字幕| 超碰自拍成人在线观看| 久久99久国产精品66| 日本亲近相奷中文字幕| 久久99国产精品尤物| 无遮高潮国产免费观看| 人妻放荡乱h文| 国产在线中文字幕精品| 国产精品国产三级国产试看| 性欧美vr高清极品| 最近中文字幕国产精品| 国产综合视频一区二区三区| 国产高跟黑色丝袜在线| 精品尤物国产尤物在线看| 国产网友愉拍精品视频手机| 定襄县| 加勒比色综合久久久久久久久|