简化频域数据,图2-1 实时频谱

说明

  本文为小编较早时候公布的稿子,内容恐怕不周详或已不合时宜,近日会有改动。 style=”color: #888888;”>(二零一八年四月 注)

说明

  本文为小编较早时候公布的作品,内容大概不周到或已不合时宜,近期会有变动。 style=”color: #888888;”>(二〇一八年四月 注)

准备

  IDE:Visual Studio

  Language:VB.NET/C#

  GitHub:AutomaticDrawing

  程序完结自动画画,现在玩你画自身猜再也不用担心被吐槽啦~\(≧▽≦)/~。

准备

  IDE:Visual Studio

  安装Nuget包: SharpDx.XAudio2

  安装Nuget包: Win2D.UWP

  精晓学习:Win2D官方博客

  了然学习:Win2D合法示例

准备

  IDE:Visual Studio

  安装Nuget包: SharpDx.XAudio2

  安装Nuget包: Win2D.UWP

  精通学习:Win2D合法博客

  明白学习:Win2D合法示例

第一节 位图

  若要程序画画,首先得导入一张图片作为模板。

  图像格式

  大家挑选使用位图,它是由像素数据定义的图像格式

  WinForm下选择封装了GDI+位图的System.Drawing.Bitmap.aspx)对象

  UWP下能够应用CanvasBitmap对象(须求设置Win2D的Nuget包)

  导入格局

  本半夏件:

      显示器截图:

  • 先用搜索引擎搜图,然后径直截屏
  • System.Drawing.Graphics.aspx)对象提供从显示屏到Graphics的位块传输

  动态合成:

  • 譬如说合成文本恐怕图案到内定的图像上
  • System.Drawing.Graphics.aspx)对象提供一各类的GDI+绘图命令

图片 1图片 2

    ''' <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

图片 3图片 4

    ''' <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

图片 5图片 6

/// <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

图片 7图片 8

/// <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

第一节 波形

  获取实时时域数据。

图片 9图片 10

Imports SharpDX.Multimedia
Imports SharpDX.XAudio2
Public Class AudioPlayer
    Public Event WavePlaying(e As WavePlayingEventArgs)
    Public Property Device As XAudio2
    Public Property Voice As SourceVoice
    Private CurrentFormat As WaveFormat
    Private CurrentBuffer As AudioBuffer
    Private PacketsInfo As UInteger()
    Public Sub New()
        Device = New XAudio2()
        Device.StartEngine()
        Dim mv As New MasteringVoice(Device)
    End Sub
    Public Async Function LoadFile(fileName As String) As Task(Of Boolean)
        Try
            Voice = Await CreateVoiceFromFile(Device, fileName)
            LoadBuffer()
            Return True
        Catch
            Return False
        End Try
    End Function
    Public Sub Play(Optional volume As Single = 1.0F)
        Voice?.SetVolume(volume)
        Voice?.Start()
        ReadBuffer()
    End Sub
    Public Sub [Stop]()
        Voice?.Stop()
    End Sub
    Protected Async Function CreateVoiceFromFile(device As XAudio2, fileName As String) As Task(Of SourceVoice)
        Dim file = Await Package.Current.InstalledLocation.GetFileAsync(fileName)
        Dim streamWithContentType = Await file.OpenReadAsync()
        Dim st = streamWithContentType.AsStreamForRead()
        Using stream = New SoundStream(st)
            CurrentFormat = stream.Format
            CurrentBuffer = New AudioBuffer() With {
            .Stream = stream.ToDataStream(),
            .AudioBytes = CInt(stream.Length),
            .Flags = BufferFlags.EndOfStream
        }
            PacketsInfo = stream.DecodedPacketsInfo
        End Using
        Dim sourceVoice = New SourceVoice(device, CurrentFormat, True)
        Return sourceVoice
    End Function
    Protected Sub LoadBuffer()
        Voice?.FlushSourceBuffers()
        Voice?.SubmitSourceBuffer(CurrentBuffer, PacketsInfo)
    End Sub
    ''' <summary>
    ''' 从流中读取当前播放的数据
    ''' </summary>
    Private Async Sub ReadBuffer()
        Try
            Dim count As Integer = CurrentFormat?.AverageBytesPerSecond / 10
            While Voice.State.BuffersQueued > 0
                If Voice.State.SamplesPlayed * CurrentFormat.BlockAlign > CurrentBuffer.Stream.Position + count Then
                    Dim byteArr(count - 1) As Byte
                    Await CurrentBuffer.Stream.ReadAsync(byteArr, 0, count)
                    RaiseEvent WavePlaying(New WavePlayingEventArgs(byteArr, CurrentFormat))
                Else
                    Await Task.Delay(10)
                End If
            End While
        Catch
            Return
        End Try
    End Sub
    Public Function Position() As Integer
        Return Voice.State.SamplesPlayed / CurrentFormat.SampleRate
    End Function
    Protected Overrides Sub Finalize()
        Try
            Dispose(False)
        Finally
            MyBase.Finalize()
        End Try
    End Sub
    Public Sub Dispose()
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    Private Sub Dispose(isDisposing As Boolean)
        If Not isDisposing Then
            Return
        End If
        Voice.DestroyVoice()
        Voice.Dispose()
        CurrentBuffer.Stream.Dispose()
    End Sub
End Class

VB.NET

图片 11图片 12

//由于在线转换工具对异步代码段支持不好,该处代码请参考VB.

C#

 

图片 13

图1-1 实时波谱

第一节 波形

  获取实时时域数据。

图片 14图片 15

Imports SharpDX.Multimedia
Imports SharpDX.XAudio2
Public Class AudioPlayer
    Public Event WavePlaying(e As WavePlayingEventArgs)
    Public Property Device As XAudio2
    Public Property Voice As SourceVoice
    Private CurrentFormat As WaveFormat
    Private CurrentBuffer As AudioBuffer
    Private PacketsInfo As UInteger()
    Public Sub New()
        Device = New XAudio2()
        Device.StartEngine()
        Dim mv As New MasteringVoice(Device)
    End Sub
    Public Async Function LoadFile(fileName As String) As Task(Of Boolean)
        Try
            Voice = Await CreateVoiceFromFile(Device, fileName)
            LoadBuffer()
            Return True
        Catch
            Return False
        End Try
    End Function
    Public Sub Play(Optional volume As Single = 1.0F)
        Voice?.SetVolume(volume)
        Voice?.Start()
        ReadBuffer()
    End Sub
    Public Sub [Stop]()
        Voice?.Stop()
    End Sub
    Protected Async Function CreateVoiceFromFile(device As XAudio2, fileName As String) As Task(Of SourceVoice)
        Dim file = Await Package.Current.InstalledLocation.GetFileAsync(fileName)
        Dim streamWithContentType = Await file.OpenReadAsync()
        Dim st = streamWithContentType.AsStreamForRead()
        Using stream = New SoundStream(st)
            CurrentFormat = stream.Format
            CurrentBuffer = New AudioBuffer() With {
            .Stream = stream.ToDataStream(),
            .AudioBytes = CInt(stream.Length),
            .Flags = BufferFlags.EndOfStream
        }
            PacketsInfo = stream.DecodedPacketsInfo
        End Using
        Dim sourceVoice = New SourceVoice(device, CurrentFormat, True)
        Return sourceVoice
    End Function
    Protected Sub LoadBuffer()
        Voice?.FlushSourceBuffers()
        Voice?.SubmitSourceBuffer(CurrentBuffer, PacketsInfo)
    End Sub
    ''' <summary>
    ''' 从流中读取当前播放的数据
    ''' </summary>
    Private Async Sub ReadBuffer()
        Try
            Dim count As Integer = CurrentFormat?.AverageBytesPerSecond / 10
            While Voice.State.BuffersQueued > 0
                If Voice.State.SamplesPlayed * CurrentFormat.BlockAlign > CurrentBuffer.Stream.Position + count Then
                    Dim byteArr(count - 1) As Byte
                    Await CurrentBuffer.Stream.ReadAsync(byteArr, 0, count)
                    RaiseEvent WavePlaying(New WavePlayingEventArgs(byteArr, CurrentFormat))
                Else
                    Await Task.Delay(10)
                End If
            End While
        Catch
            Return
        End Try
    End Sub
    Public Function Position() As Integer
        Return Voice.State.SamplesPlayed / CurrentFormat.SampleRate
    End Function
    Protected Overrides Sub Finalize()
        Try
            Dispose(False)
        Finally
            MyBase.Finalize()
        End Try
    End Sub
    Public Sub Dispose()
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    Private Sub Dispose(isDisposing As Boolean)
        If Not isDisposing Then
            Return
        End If
        Voice.DestroyVoice()
        Voice.Dispose()
        CurrentBuffer.Stream.Dispose()
    End Sub
End Class

VB.NET

图片 16图片 17

//由于在线转换工具对异步代码段支持不好,该处代码请参考VB.

C#

 

图片 18

图1-1 实时波谱

第二节 预处理

  接下来对模板图像实行拍卖,以便于下一步的轨迹寻找。

      二值化

  据悉三个阈值T,大于T的像素群设定为暗红,小于T的像素群设定为花青

  也正是将全体图像展现出明显的唯有黑和白的视觉效果

图片 19

图2-1 全局二值化

 

      细化

*  *将粗线条细化为细线条(线条宽度平时为一像素)

*  *细化算法是为着找出图像的轮廓,对区别图像的作用分化

图片 20

图2-2 轮廓化

 

图片 21图片 22

''' <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

图片 23图片 24

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

第二节 频谱

  通过火速傅里叶变换将时域信号转换为频域信号。

图片 25图片 26

    ''' <summary>
    ''' 快速傅里叶变换
    ''' </summary>
    ''' <param name="data">指定的数据</param>
    ''' <param name="count"></param>
    ''' <returns></returns>
    Public Shared Function FFT(ByVal data() As Single, ByVal count As Integer) As Single() '快速傅里叶变换
        Dim fftCount As Integer = count
        Dim j As Integer
        Dim k As Integer
        Dim NM1 As Integer
        Dim ND2 As Integer
        Dim M, L, LE, LE2, IP, JM1 As Integer
        Dim TR, TI, SR, SI, UR, UI As Double
        Dim IMX(fftCount - 1) As Double
        Dim REX(fftCount - 1) As Double
        Dim n As Integer = fftCount
        Array.Copy(data, REX, fftCount)
        NM1 = n - 1
        ND2 = n / 2
        M = CInt(Math.Log(n) / Math.Log(2))
        j = ND2

        For i = 1 To n - 2
            If i < j Then
                TR = REX(j)
                TI = IMX(j)
                REX(j) = REX(i)
                IMX(j) = IMX(i)
                REX(i) = TR
                IMX(i) = TI
            End If
            k = ND2
            While (k <= j)
                j = j - k
                k = k / 2
            End While
            j = j + k
        Next i

        For L = 1 To M
            LE = CInt(2 ^ L)
            LE2 = LE / 2
            UR = 1
            UI = 0
            SR = Math.Cos(Math.PI / LE2)
            SI = -Math.Sin(Math.PI / LE2)
            For j = 1 To LE2
                JM1 = j - 1
                For i = JM1 To NM1 Step LE
                    IP = i + LE2
                    TR = REX(IP) * UR - IMX(IP) * UI
                    TI = REX(IP) * UI + IMX(IP) * UR
                    REX(IP) = REX(i) - TR
                    IMX(IP) = IMX(i) - TI
                    REX(i) = REX(i) + TR
                    IMX(i) = IMX(i) + TI
                Next i
                TR = UR
                UR = TR * SR - UI * SI
                UI = TR * SI + UI * SR
            Next j
        Next L
        '
        Dim w() As Single
        ReDim w(fftCount / 2)    '取有效值
        ''公式:F=Kf/N F=频率;k=位置;f=取样频率;N=样本数;有效数据(N/2+1)个.
        For i = 0 To fftCount / 2
            w(i) = Math.Sqrt(REX(i) * REX(i) + IMX(i) * IMX(i))
        Next
        Return w
    End Function

VB.NET

图片 27图片 28

/// <summary>
/// 快速傅里叶变换
/// </summary>
/// <param name="data">指定的数据</param>
/// <param name="count"></param>
/// <returns></returns>
public static float[] FFT(float[] data, int count)
{
    //快速傅里叶变换
    int fftCount = count;
    int j = 0;
    int k = 0;
    int NM1 = 0;
    int ND2 = 0;
    int M = 0;
    int L = 0;
    int LE = 0;
    int LE2 = 0;
    int IP = 0;
    int JM1 = 0;
    double TR = 0;
    double TI = 0;
    double SR = 0;
    double SI = 0;
    double UR = 0;
    double UI = 0;
    double[] IMX = new double[fftCount];
    double[] REX = new double[fftCount];
    int n = fftCount;
    Array.Copy(data, REX, fftCount);
    NM1 = n - 1;
    ND2 = n / 2;
    M = Convert.ToInt32(Math.Log(n) / Math.Log(2));
    j = ND2;

    for (i = 1; i <= n - 2; i++) {
        if (i < j) {
            TR = REX[j];
            TI = IMX[j];
            REX[j] = REX[i];
            IMX[j] = IMX[i];
            REX[i] = TR;
            IMX[i] = TI;
        }
        k = ND2;
        while ((k <= j)) {
            j = j - k;
            k = k / 2;
        }
        j = j + k;
    }

    for (L = 1; L <= M; L++) {
        LE = Convert.ToInt32(Math.Pow(2, L));
        LE2 = LE / 2;
        UR = 1;
        UI = 0;
        SR = Math.Cos(Math.PI / LE2);
        SI = -Math.Sin(Math.PI / LE2);
        for (j = 1; j <= LE2; j++) {
            JM1 = j - 1;
            for (i = JM1; i <= NM1; i += LE) {
                IP = i + LE2;
                TR = REX[IP] * UR - IMX[IP] * UI;
                TI = REX[IP] * UI + IMX[IP] * UR;
                REX[IP] = REX[i] - TR;
                IMX[IP] = IMX[i] - TI;
                REX[i] = REX[i] + TR;
                IMX[i] = IMX[i] + TI;
            }
            TR = UR;
            UR = TR * SR - UI * SI;
            UI = TR * SI + UI * SR;
        }
    }
    //
    float[] w = null;
    w = new float[fftCount / 2 + 1];
    //取有效值
    //'公式:F=Kf/N F=频率;k=位置;f=取样频率;N=样本数;有效数据(N/2+1)个.
    for (i = 0; i <= fftCount / 2; i++) {
        w[i] = Math.Sqrt(REX[i] * REX[i] + IMX[i] * IMX[i]);
    }
    return w;
}

C#

 

图片 29

图2-1 实时频谱

第二节 频谱

  通过快速傅里叶变换将时域信号转换为频域信号。

图片 30图片 31

    ''' <summary>
    ''' 快速傅里叶变换
    ''' </summary>
    ''' <param name="data">指定的数据</param>
    ''' <param name="count"></param>
    ''' <returns></returns>
    Public Shared Function FFT(ByVal data() As Single, ByVal count As Integer) As Single() '快速傅里叶变换
        Dim fftCount As Integer = count
        Dim j As Integer
        Dim k As Integer
        Dim NM1 As Integer
        Dim ND2 As Integer
        Dim M, L, LE, LE2, IP, JM1 As Integer
        Dim TR, TI, SR, SI, UR, UI As Double
        Dim IMX(fftCount - 1) As Double
        Dim REX(fftCount - 1) As Double
        Dim n As Integer = fftCount
        Array.Copy(data, REX, fftCount)
        NM1 = n - 1
        ND2 = n / 2
        M = CInt(Math.Log(n) / Math.Log(2))
        j = ND2

        For i = 1 To n - 2
            If i < j Then
                TR = REX(j)
                TI = IMX(j)
                REX(j) = REX(i)
                IMX(j) = IMX(i)
                REX(i) = TR
                IMX(i) = TI
            End If
            k = ND2
            While (k <= j)
                j = j - k
                k = k / 2
            End While
            j = j + k
        Next i

        For L = 1 To M
            LE = CInt(2 ^ L)
            LE2 = LE / 2
            UR = 1
            UI = 0
            SR = Math.Cos(Math.PI / LE2)
            SI = -Math.Sin(Math.PI / LE2)
            For j = 1 To LE2
                JM1 = j - 1
                For i = JM1 To NM1 Step LE
                    IP = i + LE2
                    TR = REX(IP) * UR - IMX(IP) * UI
                    TI = REX(IP) * UI + IMX(IP) * UR
                    REX(IP) = REX(i) - TR
                    IMX(IP) = IMX(i) - TI
                    REX(i) = REX(i) + TR
                    IMX(i) = IMX(i) + TI
                Next i
                TR = UR
                UR = TR * SR - UI * SI
                UI = TR * SI + UI * SR
            Next j
        Next L
        '
        Dim w() As Single
        ReDim w(fftCount / 2)    '取有效值
        ''公式:F=Kf/N F=频率;k=位置;f=取样频率;N=样本数;有效数据(N/2+1)个.
        For i = 0 To fftCount / 2
            w(i) = Math.Sqrt(REX(i) * REX(i) + IMX(i) * IMX(i))
        Next
        Return w
    End Function

VB.NET

图片 32图片 33

/// <summary>
/// 快速傅里叶变换
/// </summary>
/// <param name="data">指定的数据</param>
/// <param name="count"></param>
/// <returns></returns>
public static float[] FFT(float[] data, int count)
{
    //快速傅里叶变换
    int fftCount = count;
    int j = 0;
    int k = 0;
    int NM1 = 0;
    int ND2 = 0;
    int M = 0;
    int L = 0;
    int LE = 0;
    int LE2 = 0;
    int IP = 0;
    int JM1 = 0;
    double TR = 0;
    double TI = 0;
    double SR = 0;
    double SI = 0;
    double UR = 0;
    double UI = 0;
    double[] IMX = new double[fftCount];
    double[] REX = new double[fftCount];
    int n = fftCount;
    Array.Copy(data, REX, fftCount);
    NM1 = n - 1;
    ND2 = n / 2;
    M = Convert.ToInt32(Math.Log(n) / Math.Log(2));
    j = ND2;

    for (i = 1; i <= n - 2; i++) {
        if (i < j) {
            TR = REX[j];
            TI = IMX[j];
            REX[j] = REX[i];
            IMX[j] = IMX[i];
            REX[i] = TR;
            IMX[i] = TI;
        }
        k = ND2;
        while ((k <= j)) {
            j = j - k;
            k = k / 2;
        }
        j = j + k;
    }

    for (L = 1; L <= M; L++) {
        LE = Convert.ToInt32(Math.Pow(2, L));
        LE2 = LE / 2;
        UR = 1;
        UI = 0;
        SR = Math.Cos(Math.PI / LE2);
        SI = -Math.Sin(Math.PI / LE2);
        for (j = 1; j <= LE2; j++) {
            JM1 = j - 1;
            for (i = JM1; i <= NM1; i += LE) {
                IP = i + LE2;
                TR = REX[IP] * UR - IMX[IP] * UI;
                TI = REX[IP] * UI + IMX[IP] * UR;
                REX[IP] = REX[i] - TR;
                IMX[IP] = IMX[i] - TI;
                REX[i] = REX[i] + TR;
                IMX[i] = IMX[i] + TI;
            }
            TR = UR;
            UR = TR * SR - UI * SI;
            UI = TR * SI + UI * SR;
        }
    }
    //
    float[] w = null;
    w = new float[fftCount / 2 + 1];
    //取有效值
    //'公式:F=Kf/N F=频率;k=位置;f=取样频率;N=样本数;有效数据(N/2+1)个.
    for (i = 0; i <= fftCount / 2; i++) {
        w[i] = Math.Sqrt(REX[i] * REX[i] + IMX[i] * IMX[i]);
    }
    return w;
}

C#

 

图片 34

图2-1 实时频谱

第三节 循迹

  从非黑即白的像素数量中总括出轨道。

      递归循迹

  首先将图像的二值化数据保存在2个二维数组里

  程序绘图时仅绘制值为1的因素所对应的岗位

  然后查找画笔开始位置,依次检查各类地点,当对应值为1时该点即为起源

  最终递归检查每八个邻居点,同步模拟鼠标操作

      中空轨迹

  只要某像素地点的上下左右任务均为1即认为该点在实体内部

  绘制时跳过该像素就足以兑现空心(首要用于空心字体的绘图)

图片 35图片 36

''' <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

图片 37图片 38

''' <summary>
''' 表示一条画图曲线的绘制序列
''' </summary>
Public Class PointSequence
    Public PointList As New List(Of PointF)
End Class

VB.NET-PointSequence

图片 39图片 40

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

图片 41图片 42

using System;
using System.Collections.Generic;
/// <summary>
/// 表示一条画图曲线的绘制序列
/// </summary>
public class PointSequence
{
    public List<PointF> PointList = new List<PointF>();
}

C#-PointSequence

第三节 简化

  简化频域数据,将紧邻的几何组值相加后取平均值。

  频谱也能够绘制成圆环状。

图片 43图片 44

    Public DataWave As ConcurrentQueue(Of Single)
    Public DataFFT() As Single
    Public DataFFTExtra() As Single
    Private Sub CalcFFT()
        Dim count As Integer = 2048 '最小时域数据的长度
        If DataWave.Count < count Then Return
        Dim tempD(count - 1) As Single
        For i = 0 To count - 1
            tempD(i) = DataWave(DataWave.Count - count + i)
        Next
        DataFFT = SignalMath.FFT(tempD, count) '原始频谱

        Dim extraCount As Integer = 64 '简化的长度
        Dim TempList As New List(Of Single)
        Dim sCount As Integer = DataFFT.Count / extraCount
        TempList.Add(0)
        For i = 1 To extraCount - 1
            Dim TempSingle As Single = 0
            For j = 0 To sCount - 1
                TempSingle += DataFFT(i * sCount + j)
            Next
            TempSingle = TempSingle / sCount / 10
            TempList.Add(TempSingle)
        Next
        DataFFTExtra = TempList.ToArray '简化后的频谱
        WaveSignal.Energy = DataFFTExtra.ToList.IndexOf(DataFFTExtra.Max) '不精确的基音位置
    End Sub

VB.NET

图片 45图片 46

public ConcurrentQueue<float> DataWave;
public float[] DataFFT;
public float[] DataFFTExtra;
private void CalcFFT()
{
    int count = 2048;
    //最小时域数据的长度
    if (DataWave.Count < count)
        return;
    float[] tempD = new float[count];
    for (i = 0; i <= count - 1; i++) {
        tempD[i] = DataWave(DataWave.Count - count + i);
    }
    DataFFT = SignalMath.FFT(tempD, count);
    //原始频谱

    int extraCount = 64;
    //简化的长度
    List<float> TempList = new List<float>();
    int sCount = DataFFT.Count / extraCount;
    TempList.Add(0);
    for (i = 1; i <= extraCount - 1; i++) {
        float TempSingle = 0;
        for (j = 0; j <= sCount - 1; j++) {
            TempSingle += DataFFT[i * sCount + j];
        }
        TempSingle = TempSingle / sCount / 10;
        TempList.Add(TempSingle);
    }
    DataFFTExtra = TempList.ToArray();//简化后的频谱
}

C#

 

图片 47

图3-1 频谱变形

第三节 简化

  简化频域数据,将附近的好多组值相加后取平均值。

  频谱也足以绘制成圆环状。

图片 48图片 49

    Public DataWave As ConcurrentQueue(Of Single)
    Public DataFFT() As Single
    Public DataFFTExtra() As Single
    Private Sub CalcFFT()
        Dim count As Integer = 2048 '最小时域数据的长度
        If DataWave.Count < count Then Return
        Dim tempD(count - 1) As Single
        For i = 0 To count - 1
            tempD(i) = DataWave(DataWave.Count - count + i)
        Next
        DataFFT = SignalMath.FFT(tempD, count) '原始频谱

        Dim extraCount As Integer = 64 '简化的长度
        Dim TempList As New List(Of Single)
        Dim sCount As Integer = DataFFT.Count / extraCount
        TempList.Add(0)
        For i = 1 To extraCount - 1
            Dim TempSingle As Single = 0
            For j = 0 To sCount - 1
                TempSingle += DataFFT(i * sCount + j)
            Next
            TempSingle = TempSingle / sCount / 10
            TempList.Add(TempSingle)
        Next
        DataFFTExtra = TempList.ToArray '简化后的频谱
        WaveSignal.Energy = DataFFTExtra.ToList.IndexOf(DataFFTExtra.Max) '不精确的基音位置
    End Sub

VB.NET

图片 50图片 51

public ConcurrentQueue<float> DataWave;
public float[] DataFFT;
public float[] DataFFTExtra;
private void CalcFFT()
{
    int count = 2048;
    //最小时域数据的长度
    if (DataWave.Count < count)
        return;
    float[] tempD = new float[count];
    for (i = 0; i <= count - 1; i++) {
        tempD[i] = DataWave(DataWave.Count - count + i);
    }
    DataFFT = SignalMath.FFT(tempD, count);
    //原始频谱

    int extraCount = 64;
    //简化的长度
    List<float> TempList = new List<float>();
    int sCount = DataFFT.Count / extraCount;
    TempList.Add(0);
    for (i = 1; i <= extraCount - 1; i++) {
        float TempSingle = 0;
        for (j = 0; j <= sCount - 1; j++) {
            TempSingle += DataFFT[i * sCount + j];
        }
        TempSingle = TempSingle / sCount / 10;
        TempList.Add(TempSingle);
    }
    DataFFTExtra = TempList.ToArray();//简化后的频谱
}

C#

 

图片 52

图3-1 频谱变形

第四节 绘图

  最终,控制光标在画板上挨家挨户画出线条系列即可。

  光标按键控制

*  *调用user32.dll库下的mouse_event(),它提供综合的光标击键和光标动作模拟

    光标指针移动

  System.Windows.Forms.Cursor.aspx)对象提供对系统光标的造访

  间接对Cursor.Position赋值就能操纵指针坐标

  也能够调用user32.dll库下的SetCursorPos()达成模拟光标移动

  Windows画板的局限性

  现今,你的主次已经足以透过决定光标在Windows画板上达成自动绘图

  但由于画板短期内不能够响应过多的音信,导致画图速度无法过快

  同时程序也很难控制画笔的思路大小与色彩

图片 53图片 54

     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

图片 55图片 56

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

第四节 场景

  粒子

  加入飞舞的粒子。粒子运动速度与实时音频的基音大小相关。

  若用贴图取代圆点,可生功能应逼真的云烟或然飞雪等景色。

图片 57图片 58

Imports System.Numerics
Imports Windows.UI
''' <summary>
''' 粒子类,表示一个拥有加速度、加速度和位置矢量的抽象粒子
''' </summary>
Public Class Partical
    Public Property Location As Vector2 '位置矢量
    Public Property Velocity As Vector2 '速度
    Public Property Acceleration As Vector2 '加速度
    Public Property Mass As Single = 10.0 '质量大小
    Public Property Age As Single = 0 '生命周期
    Public Property Alpha As Single = 255
    Public Property Size As Single = 1
    Public Property Radius As Single = 0
    Public Property RadiusX As Single = 0
    Public Property RadiusY As Single = 0
    Public Property ImageSize As Single = 1 '粒子图像的大小
    Public Property Color As Color '粒子颜色
    Public Shared Rnd As New Random
    ''' <summary>
    ''' 初始化一个粒子
    ''' </summary>
    Public Sub New(loc As Vector2)
        Location = loc
        Velocity = New Vector2(0, 0)
        Acceleration = New Vector2(0, 0)
    End Sub
    ''' <summary>
    ''' 指定的力作用于当前对象
    ''' </summary>
    ''' <param name="forceVec">指定的力</param>
    Public Sub ApplyForce(forceVec As Vector2)
        Acceleration = Acceleration + forceVec / Mass
    End Sub
    ''' <summary>
    ''' 更新粒子位置,重绘每帧图像前调用该方法
    ''' </summary>
    Public Sub Move()
        Velocity += Acceleration * WaveSignal.Energy
        'Velocity.LimitMag(20)
        Location += Velocity '更新位置
        Acceleration = Vector2.Zero
    End Sub
    Public Sub StartNew(Loc As Vector2)
        Location = Loc
        Velocity.SetMag(0)
    End Sub
End Class

VB.NET

图片 59图片 60

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Numerics;
using Windows.UI;
/// <summary>
/// 粒子类,表示一个拥有加速度、加速度和位置矢量的抽象粒子
/// </summary>
public class Partical
{
    public Vector2 Location { get; set; }
    //位置矢量
    public Vector2 Velocity { get; set; }
    //速度
    public Vector2 Acceleration { get; set; }
    //加速度
    public float Mass { get; set; }
    //质量大小
    public float Age { get; set; }
    //生命周期
    public float Alpha { get; set; }
    public float Size { get; set; }
    public float Radius { get; set; }
    public float RadiusX { get; set; }
    public float RadiusY { get; set; }
    public float ImageSize { get; set; }
    //粒子图像的大小
    public Color Color { get; set; }
    //粒子颜色
    public static Random Rnd = new Random();
    /// <summary>
    /// 初始化一个粒子
    /// </summary>
    public Partical(Vector2 loc)
    {
        Location = loc;
        Velocity = new Vector2(0, 0);
        Acceleration = new Vector2(0, 0);
    }
    /// <summary>
    /// 指定的力作用于当前对象
    /// </summary>
    /// <param name="forceVec">指定的力</param>
    public void ApplyForce(Vector2 forceVec)
    {
        Acceleration = Acceleration + forceVec / Mass;
    }
    /// <summary>
    /// 更新粒子位置,重绘每帧图像前调用该方法
    /// </summary>
    public void Move()
    {
        Velocity += Acceleration * WaveSignal.Energy;//与基音位置相关
        //Velocity.LimitMag(20)
        Location += Velocity;
        //更新位置
        Acceleration = Vector2.Zero;
    }
    public void StartNew(Vector2 Loc)
    {
        Location = Loc;
        Velocity.SetMag(0);
    }
}

C#

  背景

  到场背景图片。背景高斯模糊与实时音频的基音大小相关。

  也足以让背景随机抖动大概旋转。

图片 61图片 62

    Private Sub DrawBackGround(DrawingSession As CanvasDrawingSession)
        Using cmdList = New CanvasCommandList(DrawingSession)
            Using dl = cmdList.CreateDrawingSession
                dl.DrawImage(ImageManager.GetResource(ImageResourceID.back1))
            End Using
            Using blur1 = New Effects.GaussianBlurEffect With {.Source = cmdList, .BlurAmount = 1 + WaveSignal.Energy / 10}
                DrawingSession.DrawImage(blur1)
            End Using
        End Using
    End Sub

VB.NET

图片 63图片 64

private void DrawBackGround(CanvasDrawingSession DrawingSession)
{
    using (cmdList == new CanvasCommandList(DrawingSession)) {
        using (dl == cmdList.CreateDrawingSession) {
            dl.DrawImage(ImageManager.GetResource(ImageResourceID.back1));
        }
        using (blur1 == new Effects.GaussianBlurEffect {Source = cmdList,BlurAmount = 1 + WaveSignal.Energy / 10}) {
            DrawingSession.DrawImage(blur1);
        }
    }
}

C#

  文字

  参加歌曲名称新闻。

  具体的文字效果由你设置,请参考Win2D的Microsoft.Graphics.Canvas.Effects文档。

图片 65图片 66

Imports Microsoft.Graphics.Canvas
Imports Windows.UI
Public Class StaticStringView
    Inherits TypedGameView(Of StaticString)
    Public Sub New(Target As StaticString)
        MyBase.New(Target)
    End Sub
    Public Overrides Sub Draw(DrawingSession As CanvasDrawingSession)
        Using cmdList = New CanvasCommandList(DrawingSession)
            Using dl = cmdList.CreateDrawingSession
                DrawText(dl)
            End Using
            Using blur1 = New Effects.GaussianBlurEffect With {.Source = cmdList, .BlurAmount = 3}
                DrawingSession.DrawImage(blur1)
                DrawingSession.DrawImage(cmdList)
            End Using
        End Using
    End Sub
    Dim TextFormat = New Text.CanvasTextFormat() With {.FontFamily = "微软雅黑",
                                              .FontSize = 12,
                                              .HorizontalAlignment = Microsoft.Graphics.Canvas.Text.CanvasHorizontalAlignment.Center,
                                              .VerticalAlignment = Microsoft.Graphics.Canvas.Text.CanvasVerticalAlignment.Center}
    Public Sub DrawText(Dl As CanvasDrawingSession)
        Dl.DrawText(Target.Str, Target.Location, Colors.White, TextFormat)
    End Sub
End Class

VB.NET

图片 67图片 68

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using Microsoft.Graphics.Canvas;
using Windows.UI;
public class StaticStringView : TypedGameView<StaticString>
{
    public StaticStringView(StaticString Target) : base(Target)
    {
    }
    public override void Draw(CanvasDrawingSession DrawingSession)
    {
        using (cmdList == new CanvasCommandList(DrawingSession)) {
            using (dl == cmdList.CreateDrawingSession) {
                DrawText(dl);
            }
            using (blur1 == new Effects.GaussianBlurEffect {Source = cmdList,BlurAmount = 3}) {
                DrawingSession.DrawImage(blur1);
                DrawingSession.DrawImage(cmdList);
            }
        }
    }
     TextFormat = new Text.CanvasTextFormat {
        FontFamily = "微软雅黑",
        FontSize = 12,
        HorizontalAlignment = Microsoft.Graphics.Canvas.Text.CanvasHorizontalAlignment.Center,
        VerticalAlignment = Microsoft.Graphics.Canvas.Text.CanvasVerticalAlignment.Center
    };
    public void DrawText(CanvasDrawingSession Dl)
    {
        Dl.DrawText(Target.Str, Target.Location, Colors.White, TextFormat);
    }
}

C#

图片 69

图4-1 最后效果

 

第四节 场景

  粒子

  加入飞舞的粒子。粒子运动速度与实时音频的基音大小相关。

  若用贴图取代圆点,可生效能果逼真的云烟或许飞雪等境况。

图片 70图片 71

Imports System.Numerics
Imports Windows.UI
''' <summary>
''' 粒子类,表示一个拥有加速度、加速度和位置矢量的抽象粒子
''' </summary>
Public Class Partical
    Public Property Location As Vector2 '位置矢量
    Public Property Velocity As Vector2 '速度
    Public Property Acceleration As Vector2 '加速度
    Public Property Mass As Single = 10.0 '质量大小
    Public Property Age As Single = 0 '生命周期
    Public Property Alpha As Single = 255
    Public Property Size As Single = 1
    Public Property Radius As Single = 0
    Public Property RadiusX As Single = 0
    Public Property RadiusY As Single = 0
    Public Property ImageSize As Single = 1 '粒子图像的大小
    Public Property Color As Color '粒子颜色
    Public Shared Rnd As New Random
    ''' <summary>
    ''' 初始化一个粒子
    ''' </summary>
    Public Sub New(loc As Vector2)
        Location = loc
        Velocity = New Vector2(0, 0)
        Acceleration = New Vector2(0, 0)
    End Sub
    ''' <summary>
    ''' 指定的力作用于当前对象
    ''' </summary>
    ''' <param name="forceVec">指定的力</param>
    Public Sub ApplyForce(forceVec As Vector2)
        Acceleration = Acceleration + forceVec / Mass
    End Sub
    ''' <summary>
    ''' 更新粒子位置,重绘每帧图像前调用该方法
    ''' </summary>
    Public Sub Move()
        Velocity += Acceleration * WaveSignal.Energy
        'Velocity.LimitMag(20)
        Location += Velocity '更新位置
        Acceleration = Vector2.Zero
    End Sub
    Public Sub StartNew(Loc As Vector2)
        Location = Loc
        Velocity.SetMag(0)
    End Sub
End Class

VB.NET

图片 72图片 73

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Numerics;
using Windows.UI;
/// <summary>
/// 粒子类,表示一个拥有加速度、加速度和位置矢量的抽象粒子
/// </summary>
public class Partical
{
    public Vector2 Location { get; set; }
    //位置矢量
    public Vector2 Velocity { get; set; }
    //速度
    public Vector2 Acceleration { get; set; }
    //加速度
    public float Mass { get; set; }
    //质量大小
    public float Age { get; set; }
    //生命周期
    public float Alpha { get; set; }
    public float Size { get; set; }
    public float Radius { get; set; }
    public float RadiusX { get; set; }
    public float RadiusY { get; set; }
    public float ImageSize { get; set; }
    //粒子图像的大小
    public Color Color { get; set; }
    //粒子颜色
    public static Random Rnd = new Random();
    /// <summary>
    /// 初始化一个粒子
    /// </summary>
    public Partical(Vector2 loc)
    {
        Location = loc;
        Velocity = new Vector2(0, 0);
        Acceleration = new Vector2(0, 0);
    }
    /// <summary>
    /// 指定的力作用于当前对象
    /// </summary>
    /// <param name="forceVec">指定的力</param>
    public void ApplyForce(Vector2 forceVec)
    {
        Acceleration = Acceleration + forceVec / Mass;
    }
    /// <summary>
    /// 更新粒子位置,重绘每帧图像前调用该方法
    /// </summary>
    public void Move()
    {
        Velocity += Acceleration * WaveSignal.Energy;//与基音位置相关
        //Velocity.LimitMag(20)
        Location += Velocity;
        //更新位置
        Acceleration = Vector2.Zero;
    }
    public void StartNew(Vector2 Loc)
    {
        Location = Loc;
        Velocity.SetMag(0);
    }
}

C#

  背景

  出席背景图片。背景高斯模糊与实时音频的基音大小相关。

  也能够让背景随机抖动或然旋转。

图片 74图片 75

    Private Sub DrawBackGround(DrawingSession As CanvasDrawingSession)
        Using cmdList = New CanvasCommandList(DrawingSession)
            Using dl = cmdList.CreateDrawingSession
                dl.DrawImage(ImageManager.GetResource(ImageResourceID.back1))
            End Using
            Using blur1 = New Effects.GaussianBlurEffect With {.Source = cmdList, .BlurAmount = 1 + WaveSignal.Energy / 10}
                DrawingSession.DrawImage(blur1)
            End Using
        End Using
    End Sub

VB.NET

图片 76图片 77

private void DrawBackGround(CanvasDrawingSession DrawingSession)
{
    using (cmdList == new CanvasCommandList(DrawingSession)) {
        using (dl == cmdList.CreateDrawingSession) {
            dl.DrawImage(ImageManager.GetResource(ImageResourceID.back1));
        }
        using (blur1 == new Effects.GaussianBlurEffect {Source = cmdList,BlurAmount = 1 + WaveSignal.Energy / 10}) {
            DrawingSession.DrawImage(blur1);
        }
    }
}

C#

  文字

  参与歌曲名称音信。

  具体的文字效果由你设置,请参见Win2D的Microsoft.Graphics.Canvas.Effects文档。

图片 78图片 79

Imports Microsoft.Graphics.Canvas
Imports Windows.UI
Public Class StaticStringView
    Inherits TypedGameView(Of StaticString)
    Public Sub New(Target As StaticString)
        MyBase.New(Target)
    End Sub
    Public Overrides Sub Draw(DrawingSession As CanvasDrawingSession)
        Using cmdList = New CanvasCommandList(DrawingSession)
            Using dl = cmdList.CreateDrawingSession
                DrawText(dl)
            End Using
            Using blur1 = New Effects.GaussianBlurEffect With {.Source = cmdList, .BlurAmount = 3}
                DrawingSession.DrawImage(blur1)
                DrawingSession.DrawImage(cmdList)
            End Using
        End Using
    End Sub
    Dim TextFormat = New Text.CanvasTextFormat() With {.FontFamily = "微软雅黑",
                                              .FontSize = 12,
                                              .HorizontalAlignment = Microsoft.Graphics.Canvas.Text.CanvasHorizontalAlignment.Center,
                                              .VerticalAlignment = Microsoft.Graphics.Canvas.Text.CanvasVerticalAlignment.Center}
    Public Sub DrawText(Dl As CanvasDrawingSession)
        Dl.DrawText(Target.Str, Target.Location, Colors.White, TextFormat)
    End Sub
End Class

VB.NET

图片 80图片 81

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using Microsoft.Graphics.Canvas;
using Windows.UI;
public class StaticStringView : TypedGameView<StaticString>
{
    public StaticStringView(StaticString Target) : base(Target)
    {
    }
    public override void Draw(CanvasDrawingSession DrawingSession)
    {
        using (cmdList == new CanvasCommandList(DrawingSession)) {
            using (dl == cmdList.CreateDrawingSession) {
                DrawText(dl);
            }
            using (blur1 == new Effects.GaussianBlurEffect {Source = cmdList,BlurAmount = 3}) {
                DrawingSession.DrawImage(blur1);
                DrawingSession.DrawImage(cmdList);
            }
        }
    }
     TextFormat = new Text.CanvasTextFormat {
        FontFamily = "微软雅黑",
        FontSize = 12,
        HorizontalAlignment = Microsoft.Graphics.Canvas.Text.CanvasHorizontalAlignment.Center,
        VerticalAlignment = Microsoft.Graphics.Canvas.Text.CanvasVerticalAlignment.Center
    };
    public void DrawText(CanvasDrawingSession Dl)
    {
        Dl.DrawText(Target.Str, Target.Location, Colors.White, TextFormat);
    }
}

C#

图片 82

图4-1 最后效果

 

视频

  演示视频:黑白线条画  style=”color: #888888;”>(Bilibili)

  演示摄像:古典人物画  style=”color: #888888;”>(Bilibili)

附录

  开源: style=”text-decoration: line-through;”>MusicVideoGenerator

  相同类别的MV:

  Over The Horizon

  Tuesdays

  Supernova(Original Mix)

  Lovers

  Life

附录

  开源: style=”text-decoration: line-through;”>MusicVideoGenerator

  相同档次的MV:

  Over The Horizon

  Tuesdays

  Supernova(Original Mix)

  Lovers

  Life

附录

  后续小说:更美艳的自动绘图程序

  后续小说:小孩涂鸦遇上先后绘图

  后续小说:次第怎么样画动漫美少

相关文章