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

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

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

      自動繪圖AI:程序如何畫出動漫美少女

      說明

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

      準備

        全新的圖形引擎與 AI 算法,高效流暢地繪出任何一副美麗的圖像。

        IDE:VisualStudio

        Language:VB.NET / C#

        Graphics:AutoPaint.NET

      第一節 背景

        背景是圖畫里襯托主體事物的景象。

      圖1-1 先畫個藍藍的天空

        藍天、白云和大地,程序最擅長這種色調單一的涂抹了。

      第二節 輪廓

        輪廓是物體的外周或圖形的外框。

      圖2-2 勾勒人物和衣飾輪廓

        現在 AI 要控制筆觸大小和顏色,讓圖像的主體顯現出來。

      第三節 光影

        光影是物體在光的照射下呈現出明與暗的關系。

      圖3-1 光影提升畫面質感

        AI 可不懂什么是光影,在上一步的基礎上優化細節即可。

      第四節 潤色

        潤色是增加物體本身及其周圍的色彩。

      圖4-1 畫面潤色

        這是關鍵一步,AI需要將丟失的顏色細節補缺回來。

      第五節 成型

        大功告成!前面所有的步驟都是為這一步鋪墊。

      圖5-1 人物已經栩栩如生啦

        事實上 AI 只進行這一步也可以畫出完整的圖像,但沒有過渡會顯得生硬。

      第六節 算法

        算法思路很簡單,計算畫筆軌跡后一遍遍重繪,感覺上是人類畫手的效果。 

        不再是二值化

        因為現在要繪制全彩圖像,將圖像劃分為只有黑和白的效果已經沒有什么意義,二值化不再適用

        適用的方法是將 RGB 顏色空間劃分為若干個顏色子空間,然后逐個處理一幅圖像中屬于某個子空間的區域

        自動循跡

        循跡算法沒有大的變動,仍是早前博客里貼出的代碼

        彩色圖像線條較短,可以不再計算點周圍的權值用來中斷軌跡

        重繪

        程序先選擇筆觸較大、顏色淡的畫筆繪制一遍,然后在這基礎上逐步減小筆觸并加深色彩

        直接按照標準筆觸可以一遍成型,但會顯得突兀和生硬,畢竟這個AI不是真的在思考如何畫一幅圖像

      Imports System.Numerics
      ''' <summary>
      ''' 表示自動循跡并生成繪制序列的AI
      ''' </summary>
      Public Class SequenceAI
          ''' <summary>
          ''' 線條序列List
          ''' </summary>
          ''' <returns></returns>
          Public Property Sequences As List(Of PointSequence)
          ''' <summary>
          ''' 掃描方式
          ''' </summary>
          Public Property ScanMode As ScanMode = ScanMode.Rect
          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>
          ''' 創建并初始化一個可自動生成繪制序列AI的實例
          ''' </summary>
          Public Sub New(BolArr(,) As Integer)
              Sequences = New List(Of PointSequence)
              CalculateSequence(BolArr)
              For Each SubItem In Sequences
                  SubItem.CalcSize()
              Next
          End Sub
          ''' <summary>
          ''' 新增一個序列
          ''' </summary>
          Private Sub CreateNewSequence()
              Sequences.Add(New PointSequence)
          End Sub
          ''' <summary>
          ''' 在序列List末尾項新增一個點
          ''' </summary>
          Private Sub AddPoint(point As Vector2)
              Sequences.Last.Points.Add(point)
          End Sub
          ''' <summary>
          ''' 計算序列
          ''' </summary>
          Private Sub CalculateSequence(BolArr(,) As Integer)
              If ScanMode = ScanMode.Rect Then
                  ScanRect(BolArr)
              Else
                  ScanCircle(BolArr)
              End If
          End Sub
          ''' <summary>
          ''' 圓形掃描
          ''' </summary>
          ''' <param name="BolArr"></param>
          Private Sub ScanCircle(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 = CInt(CP.X + R * Math.Cos(Theat))
                      Dim dy As Integer = CInt(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 Vector2(dx, dy))
                          CheckMove(BolArr, dx, dy, 0)
                          NewStart = True
                      End If
                  Next
              Next
          End Sub
          ''' <summary>
          ''' 矩形掃描
          ''' </summary>
          ''' <param name="BolArr"></param>
          Private Sub ScanRect(BolArr(,) As Integer)
              Dim xCount As Integer = BolArr.GetUpperBound(0)
              Dim yCount As Integer = BolArr.GetUpperBound(1)
              For i = 0 To xCount - 1
                  For j = 0 To yCount - 1
                      Dim dx As Integer = i
                      Dim dy As Integer = j
                      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 Vector2(dx, dy))
                          CheckMove(BolArr, dx, dy, 0)
                          NewStart = True
                      End If
                  Next
              Next
          End Sub
          ''' <summary>
          ''' 遞歸循跡算法
          ''' </summary>
          Private Sub CheckMove(ByRef bolArr(,) As Integer, ByVal x As Integer, ByVal y As Integer, ByVal StepNum As Integer)
              If StepNum > 1000 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 Vector2(dx, dy))
                          NewStart = False
                      Else
                          Me.AddPoint(New Vector2(dx, dy))
                      End If
                      CheckMove(bolArr, dx, dy, StepNum + 1)
                      NewStart = True
                  End If
              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
      
      ''' <summary>
      ''' 線條掃描方式
      ''' </summary>
      Public Enum ScanMode
          ''' <summary>
          ''' 矩形掃描
          ''' </summary>
          Rect
          ''' <summary>
          ''' 圓形掃描
          ''' </summary>
          Circle
      End Enum
      VB.NET-SequenceAI
      Imports System.Numerics
      ''' <summary>
      ''' 表示由一系列點向量組成的線條
      ''' </summary>
      Public Class PointSequence
          Public Property Points As New List(Of Vector2)
          Public Property Sizes As Single()
          ''' <summary>
          ''' 計算畫筆大小
          ''' </summary>
          Public Sub CalcSize()
              If Points.Count < 1 Then Exit Sub
              Static Mid, PenSize As Single
              ReDim Sizes(Points.Count - 1)
              For i = 0 To Points.Count - 1
                  Mid = CSng(Math.Abs(i - Points.Count / 2))
                  PenSize = 1 - Mid / Points.Count * 2
                  Sizes(i) = PenSize
              Next
          End Sub
      End Class
      VB.NET-PointSequence
      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.Data;
      using System.Diagnostics;
      using System.Numerics;
      /// <summary>
      /// 表示自動循跡并生成繪制序列的AI
      /// </summary>
      public class SequenceAI
      {
          /// <summary>
          /// 線條序列List
          /// </summary>
          /// <returns></returns>
          public List<PointSequence> Sequences { get; set; }
          /// <summary>
          /// 掃描方式
          /// </summary>
          public ScanMode ScanMode { get; set; }
          int[] xArray = {
              -1,
              0,
              1,
              1,
              1,
              0,
              -1,
              -1
          };
          int[] yArray = {
              -1,
              -1,
              -1,
              0,
              1,
              1,
              1,
              0
          };
          bool NewStart;
          /// <summary>
          /// 創建并初始化一個可自動生成繪制序列AI的實例
          /// </summary>
          public SequenceAI(int[,] BolArr)
          {
              Sequences = new List<PointSequence>();
              CalculateSequence(BolArr);
              foreach (object SubItem_loopVariable in Sequences) {
                  SubItem = SubItem_loopVariable;
                  SubItem.CalcSize();
              }
          }
          /// <summary>
          /// 新增一個序列
          /// </summary>
          private void CreateNewSequence()
          {
              Sequences.Add(new PointSequence());
          }
          /// <summary>
          /// 在序列List末尾項新增一個點
          /// </summary>
          private void AddPoint(Vector2 point)
          {
              Sequences.Last.Points.Add(point);
          }
          /// <summary>
          /// 計算序列
          /// </summary>
          private void CalculateSequence(int[,] BolArr)
          {
              if (ScanMode == ScanMode.Rect) {
                  ScanRect(BolArr);
              } else {
                  ScanCircle(BolArr);
              }
          }
          /// <summary>
          /// 圓形掃描
          /// </summary>
          /// <param name="BolArr"></param>
          private void ScanCircle(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 = Convert.ToInt32(CP.X + R * Math.Cos(Theat));
                      int dy = Convert.ToInt32(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 Vector2(dx, dy));
                          CheckMove(ref BolArr, dx, dy, 0);
                          NewStart = true;
                      }
                  }
              }
          }
          /// <summary>
          /// 矩形掃描
          /// </summary>
          /// <param name="BolArr"></param>
          private void ScanRect(int[,] BolArr)
          {
              int xCount = BolArr.GetUpperBound(0);
              int yCount = BolArr.GetUpperBound(1);
              for (i = 0; i <= xCount - 1; i++) {
                  for (j = 0; j <= yCount - 1; j++) {
                      int dx = i;
                      int dy = j;
                      if (!(dx > 0 & dy > 0 & dx < xCount & dy < yCount))
                          continue;
                      if (BolArr[dx, dy] == 1) {
                          BolArr[dx, dy] = 0;
                          this.CreateNewSequence();
                          this.AddPoint(new Vector2(dx, dy));
                          CheckMove(ref BolArr, dx, dy, 0);
                          NewStart = true;
                      }
                  }
              }
          }
          /// <summary>
          /// 遞歸循跡算法
          /// </summary>
          private void CheckMove(ref int[,] bolArr, int x, int y, int StepNum)
          {
              if (StepNum > 1000)
                  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 AndAlso AroundValue < 8 Then
              //Return
              //End If
              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 Vector2(dx, dy));
                          NewStart = false;
                      } else {
                          this.AddPoint(new Vector2(dx, dy));
                      }
                      CheckMove(ref bolArr, dx, dy, StepNum + 1);
                      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;
          }
      }
      
      /// <summary>
      /// 線條掃描方式
      /// </summary>
      public enum ScanMode
      {
          /// <summary>
          /// 矩形掃描
          /// </summary>
          Rect,
          /// <summary>
          /// 圓形掃描
          /// </summary>
          Circle
      }
      C#-SequenceAI
      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.Data;
      using System.Diagnostics;
      using System.Numerics;
      /// <summary>
      /// 表示由一系列點向量組成的線條
      /// </summary>
      public class PointSequence
      {
          public List<Vector2> Points { get; set; }
          public float[] Sizes { get; set; }
          float static_CalcSize_Mid;
          /// <summary>
          /// 計算畫筆大小
          /// </summary>
          float static_CalcSize_PenSize;
          public void CalcSize()
          {
              if (Points.Count < 1)
                  return;
              Sizes = new float[Points.Count];
              for (i = 0; i <= Points.Count - 1; i++) {
                  static_CalcSize_Mid = Convert.ToSingle(Math.Abs(i - Points.Count / 2));
                  static_CalcSize_PenSize = 1 - static_CalcSize_Mid / Points.Count * 2;
                  Sizes[i] = static_CalcSize_PenSize;
              }
          }
      }
      C#-PointSequence

      視頻

      附錄

        GitHub:EDGameEngine.AutoDraw

        早期博客:程序如何實現自動繪圖 

        早期博客:更優秀的自動繪圖程序

        創意分享:兒童涂鴉遇上程序繪圖 

      posted @ 2016-09-26 22:13  ExperDot  閱讀(13264)  評論(12)    收藏  舉報
      主站蜘蛛池模板: 欧美性白人极品hd| 国产精品无码a∨麻豆| 无码精品人妻一区二区三区中| 甘南县| 国产精品无码无片在线观看3d| 天天爽天天摸天天碰| 换着玩人妻中文字幕| 色欲精品国产一区二区三区av| 海门市| 亚洲av第一区二区三区| 亚洲欧洲av一区二区久久| 无码国产69精品久久久久网站| 阜宁县| 欧洲亚洲成av人片天堂网| 亚洲成色精品一二三区| 亚洲av专区一区| 亚洲日韩性欧美中文字幕| 亚洲aⅴ男人的天堂在线观看| 国产二区三区不卡免费| 麻豆国产成人av高清在线| 国产中文99视频在线观看| 色吊丝免费av一区二区| 国产99久久无码精品| 99久久无码私人网站| 久久久无码精品亚洲日韩蜜桃| 日韩激情一区二区三区| 视频一区视频二区视频三| 最近中文国语字幕在线播放| 亚洲国产精品毛片av不卡在线| 人妻影音先锋啪啪AV资源| 特黄特色的大片观看免费视频| 日韩人妻少妇一区二区三区 | 一级片一区二区中文字幕| 天美传媒mv免费观看完整| 日韩在线观看精品亚洲| 在线观看美女网站大全免费| 亚洲AV永久无码精品秋霞电影影院| 少妇无码一区二区三区免费| 四虎在线永久免费看精品| 九九热这里只有精品在线| 国产欧美日韩精品丝袜高跟鞋|