AR創意分享:兒童塗鴉遇上程序繪圖,ar創意
第一節 臨摹
小明經常臨摹同桌小美的畫作。
美術課上,老師表揚了小美的新作。
圖1.1 小美的作品《蒙娜·毛蟲的微笑》
臨,是照著原作畫;摹,是用薄紙張蒙在原作上面畫。
第二節 借畫
小明隨後借來了小美的畫。
但他覺得這樣摹著畫甚是無趣。
圖2.1 未完成的臨摹
一般地,臨摹耐心與紙張透明度成正比。
第三節 塗鴉
小明認為這只毛蟲太孤單了。
然後,他的塗鴉怪獸就蹦了出來。
圖3.1 《蒙娜·毛蟲與她的怪獸》
塗鴉,隨意地塗抹色彩與線條。
第四節 黑白
小美的哥哥和小明是好朋友,他叫大美。
大美有個AR程序,它可以計算圖像的黑與白。
圖4.1 黑白版《蒙娜·毛蟲的微笑》
黑白阈值劃分可以基於RGB顏色空間也可以基於HSV顏色空間。

![]()
Public Class ImageProcessClass
''' <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="gX"></param>
''' <param name="gY"></param>
''' <param name="gWidth"></param>
''' <param name="gHeight"></param>
''' <returns></returns>
Public Function GetScreenImage(ByVal gX As Integer, ByVal gY As Integer, ByVal gWidth As Integer, ByVal gHeight As Integer) As Bitmap
Dim ResultBitmap As New Bitmap(gWidth, gHeight)
Using pg As Graphics = Graphics.FromImage(ResultBitmap)
pg.CopyFromScreen(gX, gY, 0, 0, New Size(gWidth, gHeight))
End Using
Return ResultBitmap
End Function
''' <summary>
''' 返回指定文字生成的位圖
''' </summary>
''' <param name="gString"></param>
''' <param name="gFont"></param>
''' <param name="gWidth"></param>
''' <param name="gHeight"></param>
''' <returns></returns>
Public Function GetTextImage(ByVal gString As String, ByVal gFont As Font, ByVal gWidth As Integer, ByVal gHeight As Integer) As Bitmap
Dim ResultBitmap As New Bitmap(gWidth, gHeight)
Using pg = Graphics.FromImage(ResultBitmap)
pg.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias '抗鋸齒
pg.DrawString(gString, gFont, Brushes.Black, 0, 0)
End Using
Return ResultBitmap
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

![]()
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class ImageProcessClass
{
/// <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="gX"></param>
/// <param name="gY"></param>
/// <param name="gWidth"></param>
/// <param name="gHeight"></param>
/// <returns></returns>
public Bitmap GetScreenImage(int gX, int gY, int gWidth, int gHeight)
{
Bitmap ResultBitmap = new Bitmap(gWidth, gHeight);
using (Graphics pg = Graphics.FromImage(ResultBitmap)) {
pg.CopyFromScreen(gX, gY, 0, 0, new Size(gWidth, gHeight));
}
return ResultBitmap;
}
/// <summary>
/// 返回指定文字生成的位圖
/// </summary>
/// <param name="gString"></param>
/// <param name="gFont"></param>
/// <param name="gWidth"></param>
/// <param name="gHeight"></param>
/// <returns></returns>
public Bitmap GetTextImage(string gString, Font gFont, int gWidth, int gHeight)
{
Bitmap ResultBitmap = new Bitmap(gWidth, gHeight);
using (pg == Graphics.FromImage(ResultBitmap)) {
pg.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias;
//抗鋸齒
pg.DrawString(gString, gFont, Brushes.Black, 0, 0);
}
return ResultBitmap;
}
/// <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#
第五節 線條
AR程序還可以計算圖像組成的線條。
參考線條序列,小明就不會不知道如何下筆了。
圖5.1 程序實現自動線條
定義一個SequenceManager類,它用以識別線條、並管理PointSequence類。

![]()
Public Class SequenceManagerClass
''' <summary>
''' 繪制序列的List
''' </summary>
Public SequenceList As List(Of PointSequenceClass)
Public Sub New(BolArr(,) As Integer)
SequenceList = New List(Of PointSequenceClass)
CalculateSequence(BolArr)
End Sub
Private Sub CreateNewSequence()
SequenceList.Add(New PointSequenceClass)
End Sub
Private Sub AddPoint(aPoint As PointF)
SequenceList.Last.PointList.Add(aPoint)
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
Private Sub CheckMove(ByRef BolArr(,) As Integer, ByVal x As Integer, ByVal y As Integer, ByVal StepNum As Integer)
Application.DoEvents()
If StepNum > 200 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
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
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
Public Class PointSequenceClass
Public PointList As New List(Of PointF)
End Class
VB.NET

![]()
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class SequenceManagerClass
{
/// <summary>
/// 繪制序列的List
/// </summary>
public List<PointSequenceClass> SequenceList;
public SequenceManagerClass(int[,] BolArr)
{
SequenceList = new List<PointSequenceClass>();
CalculateSequence(BolArr);
}
private void CreateNewSequence()
{
SequenceList.Add(new PointSequenceClass());
}
private void AddPoint(PointF aPoint)
{
SequenceList.Last.PointList.Add(aPoint);
}
int[] xArray = {
-1,
0,
1,
1,
1,
0,
-1,
-1
};
int[] yArray = {
-1,
-1,
-1,
0,
1,
1,
1,
0
};
bool NewStart;
private void CheckMove(ref int[,] BolArr, int x, int y, int StepNum)
{
Application.DoEvents();
if (StepNum > 200)
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;
}
}
}
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;
}
}
}
}
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;
}
}
public class PointSequenceClass
{
public List<PointF> PointList = new List<PointF>();
}
C#
第六節 投影
最後,AR程序將計算後的圖像投影到屏幕上。
圖像與現實影像真實鑲嵌,小明就可以照著屏幕臨摹。
圖6.1 未經PS的AR演示
事實上,小明若使用沉浸式AR眼鏡,他會得到更佳的體驗。
附錄
早期博客:程序實現自動繪圖
早期博客:更優秀的繪圖程序
開源鏈接:ExperDot.AutomaticDrawing