玩转你画我猜:程序实现自动绘图



程序实现自动画画,以后玩你画我猜再也不用担心被吐槽了.



1.原图来源

  程序绘图得有一张图片作为模板,然后按照模板绘制,所以首先需要导入原图

  1.导入本地图像

直接导入本地图像

        Dim NativeBitmap As New Bitmap("FileName As String")

  2.屏幕截图

利用搜索引擎搜图,然后直接截图,这样更便捷

        Dim NativeBitmap As Bitmap= GetScreen(0,0,100,100)
        Public Function GetScreen(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)
        Dim pg As Graphics = Graphics.FromImage(ResultBitmap)
        pg.CopyFromScreen(gX, gY, 0, 0, New Size(gWidth, gHeight))
        pg.Dispose()
        Return ResultBitmap
        End Function

 3.文字生成

下载TureType字体,随时生成好看的文字图片

 Dim NativeBitmap As Bitmap = GetTextImage("示例", "叶根友毛笔行书简体", 24,100,100)
 Public Function GetTextImage(ByVal gString As String, ByVal gFont As String, ByVal gSize As Int32, ByVal gWidth As Int32, ByVal gHeight As Int32) Dim ResultBitmap As New Bitmap(gWidth, gHeight)
    Dim pg As Graphics = Graphics.FromImage(ResultBitmap)
    Dim myfont As New Font(gFont, gSize, FontStyle.Regular)
    pg.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias ‘抗锯齿
    pg.DrawString(gString, myfont, Brushes.Black, 0, 0)
    pg.Dispose()
    Return ResultBitmap
 End Function


2.图像处理

  接下来就要对模板进行处理了,以便于下一步的轨迹寻找

1.二值化

        基于一个阈值T,大于T的像素群设定为白色,小于T的像素群设定为黑色,也就是将整个图像呈现出明显的只有黑和白的视觉效果

    ‘图像二值化
    Public Function GetThreshold(ByVal gBitmap As Bitmap, ByVal gSplitNum As Byte) As Bitmap
        Dim ResultBitmap As New Bitmap(gBitmap.Width, gBitmap.Width)
        Dim hHd As Integer
        For i = 0 To gBitmap.Width - 1
            For j = 0 To gBitmap.Height - 1
                hHd = gethHD(gBitmap.GetPixel(i, j))
                ResultBitmap.SetPixel(i, j, IIf(hHd < gSplitNum, Color.Black, Color.White))
            Next
        Next
        Return ResultBitmap
    End Function
    ‘ 获取颜色中值
    Public Function gethHD(ByVal color1 As Color)
        Dim hHD, r, g, b As Integer
        r = color1.R : g = color1.G : b = color1.B
        hHD = (r + g + b) / 3
        Return hHD
    End Function

      二次元例子:(全局二值化,不同阈值效果不同)

2.细化

   顾名思义,将粗线条细化为细线条(通常为宽度为一像素),参考过多个细化算法后发现效果均不理想,用自己写的轮廓算法和空心绘制等效代替

3.轮廓

   就是找出图像的轮廓

    ‘返回Btimap,图像轮廓线
    Public Function GetOutLine(ByVal gBitmap As Bitmap, ByVal gDistance As Byte) 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 Color1, Color2 As Color
        For i = 1 To gBitmap.Width - 2
            For j = 1 To gBitmap.Height - 2
                For p = 0 To 3
                    Color1 = gBitmap.GetPixel(i, j)
                    Color2 = gBitmap.GetPixel(i + xArray2(p), j + yArray2(p))
                    If CompareRGB(Color1, Color2, gDistance) = False And gethHD(Color1) - gethHD(Color2) > 0 Then
                        ResultBitmap.SetPixel(i, j, Color.Black)
                    End If
                Next
            Next
        Next
        Return ResultBitmap
    End Function
    ‘比较两个颜色的相似度
    Public Function CompareRGB(ByVal Color1 As Color, ByVal Color2 As Color, ByVal Distance As Byte) 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
    ‘获取颜色中值
    Public Function gethHD(ByVal color1 As Color)
        Dim hHD, r, g, b As Integer
        r = color1.R : g = color1.G : b = color1.B
        hHD = (r + g + b) / 3
        Return hHD
    End Function

        二次元例子:



3.循迹算法

1.递归循迹

‘‘‘ 首先将图像的二值化数据保存在一个二维数组里,程序绘图时仅绘制值为1的元素所对应的位置

    ‘返回图像的二值化数组,0表示白色,1表示黑色
    Public Function GetImageBol(ByVal gBitmap As Bitmap)
        Dim ResultArray(gBitmap.Width - 1, gBitmap.Height - 1) As Integer
        For i = 0 To gBitmap.Width - 1
            For j = 0 To gBitmap.Height - 1
                If gBitmap.GetPixel(i, j).Equals(Color.FromArgb(0, 0, 0)) = True Then
                    ResultArray(i, j) = 1
                Else
                    ResultArray(i, j) = 0
                End If
            Next
        Next
        Return ResultArray
    End Function

‘‘‘ 然后寻找画笔起点位置,依次检查每个元素,当对应值为1时该点即为起点

    Dim BitmapBol1(,) As Integer
    Dim BitmapBol2(,) As Integer=GetImageBol(CurrentBitmap)
    Private Sub StartPaint()
        ‘On Error Resume Next
        Dim BWidth As Integer = BitmapBol2.GetUpperBound(0) + 1
        Dim BHeight As Integer = BitmapBol2.GetUpperBound(1) + 1
        ReDim BitmapBol1(BWidth - 1, BHeight - 1)
        Array.Copy(BitmapBol2, BitmapBol1, BitmapBol1.Length)
        For i = 0 To BWidth - 1 Step 1
            For j = 0 To BHeight - 1 Step 1
                If BitmapBol1(i, j) = 1 Then
                    BitmapBol1(i, j) = 0
                    MMove(i, j)
                    MDownUp(0, 0, True)
                    CheckMove(i, j)
                    MDownUp(0, 0, False)
                End If
            Next
        Next
    End Sub

‘‘‘ 最后递归检查每一个点,同步模拟鼠标操作

    Dim xArray() As Short = {-1, 0, 1, 1, 1, 0, -1, -1}
    Dim yArray() As Short = {-1, -1, -1, 0, 1, 1, 1, 0}
    ‘检查移动
    Private Sub CheckMove(ByVal x As Integer, ByVal y As Integer)
        Dim dx, dy As Integer
        For i = 0 To 7
            dx = x + xArray(i) : dy = y + yArray(i)
            If Not (dx > 0 And dy > 0 And dx < BitmapBol2.GetUpperBound(0) And dy < BitmapBol2.GetUpperBound(1)) Then MDownUp(0, 0, False) : NewStart = True : Exit Sub
            If CheckCircle(dx, dy) = False Then
                If BitmapBol1(dx, dy) = 1 Then
                    BitmapBol1(dx, dy) = 0
                    MMove(dx, dy)
                    If NewStart = True Then MDownUp(0, 0, True) : NewStart = False
                    CheckMove(dx, dy)
                    MDownUp(0, 0, False)
                    NewStart = True
                End If
            Else
                BitmapBol1(dx, dy) = 0
            End If
        Next
    End Sub

2.空心轨迹

‘‘‘ 只要元素位置上下左右位置均为1即认为该点在实体内部,绘制时跳过该元素就可以实现空心(主要用于空心字体的绘制)

    ‘检查空心
    Private Function CheckCircle(ByVal x As Integer, ByVal y As Integer) As Boolean
        If Not (x > 0 And y > 0 And x < BitmapBol2.GetUpperBound(0) And y < BitmapBol2.GetUpperBound(1)) Then Return False
        If CheckBox1.Checked = True And BitmapBol2(x - 1, y) = 1 And BitmapBol2(x + 1, y) = 1 And BitmapBol2(x, y - 1) = 1 And BitmapBol2(x, y + 1) = 1 Then
            Return True ‘当前点为实体内部
        Else
            Return False ‘当前点为实体边缘
        End If
    End Function


4.鼠标模拟

1.左键按下\松开

  调用API实现

    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 Sub MDownUp(ByVal dx As Integer, ByVal dy As Integer, ByVal type As Boolean)
        If type = True Then
            mouse_event(&H2, 0, 0, 0, IntPtr.Zero)‘鼠标左键按下
        Else
            mouse_event(&H4, 0, 0, 0, IntPtr.Zero)‘鼠标左键松开
        End If
        System.Threading.Thread.Sleep(sleeptime)
    End Sub

  2.鼠标移动

    也可以调用SetCursorPos实现模拟鼠标移动

    Private Sub MMove(ByVal dx As Integer, ByVal dy As Integer)
        AbsX = Form2.PointToScreen(New Point(0, 0)).X
        AbsY = Form2.PointToScreen(New Point(0, 0)).Y
        Cursor.Position = New Point(AbsX + dx, AbsY + dy)
    End Sub


附录:

程序&源码网盘下载链接: http://pan.baidu.com/s/1gdy9ZfP

时间: 2024-08-25 09:32:55

玩转你画我猜:程序实现自动绘图的相关文章

Vue+WebSocket+ES6+Canvas 制作「你画我猜」小游戏

Vue+WebSocket+ES6+Canvas 制作「你画我猜」小游戏 转载 来源:jrainlau 链接:https://segmentfault.com/a/1190000005804860 项目地址:https://github.com/jrainlau/draw-something 下载 & 运行 git clone [email protected]:jrainlau/draw-something.git cd draw-something && npm install

玩转VC++系统托盘程序(WIN8)

 WINDOWS系统托盘是一个特殊区域,通常在桌面的右下角,也就是任务栏的右边.系统常驻在托盘的程序有时钟,音量控制,输入法,网络状态等.第三方应用如QQ程序也是一个典型的托盘程序,当最小化时企鹅会乖乖的待在屏幕右下角等待主人的呼唤. 系统托盘的方便之处在于,程序在暂时不用时,将它放到托盘里,随用随叫,不必将其关闭.而QQ在接收到消息后,也会在托盘中闪动提示,十分人性化. 那么如何用VC++来开发托盘程序呢?下面会用一个例子来玩转WINDOWS托盘程序. 首先,定义一下需要的功能.(需求确定

Node学习笔记(三):基于socket.io web版你画我猜(一)

经过惨淡的面试,也是知道了自己的不足,刚好最近在学习node,心中便有了做一个web版的你画我猜的想法 首先说下思路,在做准备工作的时候,有两个大概的思路: 1.规定一块div,捕捉鼠标事件,动态生成position absolute,长宽1px的红色小div,这样可以模拟出划线的轨迹,做一个long polling,不断获取DOM结构,推送到socket端口,然后再广播给所有客户端 2.利用canvas作图,将canvas的数据推送到socket端口,广播所有客户端 其实之所以有两种想法,无非

程小元像素画小程序,持续维护中..

最近无意之间,发现了一波非常精致的像素画作品.以至于自己有点沉迷其中,于是,索性用几天时间做一个出来. 下面先来欣赏一几张大师的作品: 目前像素画主要用于与一些复古的游戏场景和游戏角色,还有一个创意海报等等.像素化图,也是一种艺术形式,风靡至今. 好吧,废话不多说了. 我的微信小程序:程小元像素画 上面两张图,是目前的两个模块:1.像素画板 2.大师作品 简单的画几笔,就能生成自己的像素画作品.目前第一个版本,比较简单.后面抽时间继续完善.昨天第一天上线,收到了很多用户发来的作品图,还有下一个版

matlab画棋盘格程序

意义 在摄像机标定中常常需要打印黑白棋盘格,在投影仪标定当中也常常需要投射棋盘格. MATLAB源代码 close all; clear all; clc; width=1024 ; %pattern的宽 height=768 ; %pattern的高 img_final=zeros(height,width); reinforceconner=0 ;%是否加强角点 row=10; %pattern中棋盘格的行数 col=13 ; %pattern中棋盘格的列数 length=45; %patt

SDUT2465其实玩游戏也得学程序(BFS记录路径问题)

BFS记录路径第一炮 题目连接:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2465 思路:搜索找路径问题,DFS进行,调用     DFS(当前->当前点父节点)->起点,思想,以栈为储存结构,保存路径. 和以往BFS不一样的是地图储存在结构体里...注意 在DFS时候,BLF0是当前点的父节点,BLF1是其子节点,因为初始时cost是无限大,每次进出队列的过程都保证当前的cost是较小

团队作业之二

用户反馈总结: 我们这次调研采用的方法是“深入采访”,深入采访的对象是我们大三的一名同学,我们在他的寝室进行了一次短的采访.在采访的过程中我们了解了用户的需求是什么,也了解了用户在什么方面希望我们的你画我猜游戏做的好一些.一个同学的感想并不是太全面,所以我们又对其他几位同学进行了采访,他们的回答也基本相同,所以就只录了一个同学的视频.结果,大多数玩过游戏的同学都玩''过你画我猜''游戏,认为这个游戏不仅能提高玩家的想象力,还可以培养玩家之间的默契,它的趣味性很强,非常适合小朋友玩,在家就可以提高

HTML5移动开发之路(10)——在线画板

本文为 兄弟连IT教育 机构官方 HTML5培训 教程,主要介绍:HTML5移动开发之路(10)--在线画板 在这一篇文章中我们用HTML5来实现一个在线的画板,玩过你画我猜的朋友今天也可以做一个简单的你画我猜小游戏啦,效果如下图所示: 过程很简单直接上代码了: [html] view plain copy print? <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.

微信小程序源码下载(200多个)

微信小程序源码下载汇总,点击标题进入对应的微信小程序下载页面. 最新 demo源码(点击标题进入帖子下载) 描述 1 微信小程序 会议室预定小程序 微信小程序 会议室预定小程序**** 本内容被作者隐藏 **** 2 微信小程序-双人五子棋小游戏 微信小程序-双人五子棋小游戏**** 本内容被作者隐藏 **** 3 打卡签到小程序 用微信小程序实现的一个简单的打卡签到的小程序拒绝 4 微信小程序---左滑删除 微信小程序---左滑删除**** 本内容被作者隐藏 **** 5 一个借钱的记事本的微