动态窗口(机械运动监测)上有一数字栏,如何识别如上图数字(0到60)?(小弟对建模对比数字,不是很了解)如果动态窗口的这个某个区域上出现黑色圆点快速经过(经过这个区域的位置不一定),如何判断使i=i+1,
是否需要建立坐标数组,将这个区域的所有的绝对坐标(相对坐标)扫描一遍if getpixel()=RBG(0,0,0) then-.......elseendif希望专家能指点编程一二..先行谢过...

解决方案 »

  1.   

    数字大小为 7*9,你要先准备好10个这样大小带有数字 0~9 的图片,假定已经载入到控件数组 Picture2(0)~Picture2(9)
    要监测的图片大小为 65*37 (连列数字出现在 x=11,20 处),假定已经载入到控件 Picture1 中
    所有 PictureBox 的 ScaleMode 都设为 3 - Pixel。
    Option ExplicitPrivate Const DIGIT_WIDTH As Long = 7
    Private Const DIGIT_HEIGHT As Long = 9Private Function IsMatch(ByVal x As Long, ByVal y As Long, ByVal n As Byte) As Boolean
        Dim iX As Long, iY As Long
            
        For iX = 0 To DIGIT_WIDTH - 1
            For iY = 0 To DIGIT_HEIGHT - 1
                If Picture1.Point(x + iX, y + iY) <> Picture2(n).Point(iX, iY) Then
                    Exit Function
                End If
            Next
        Next
        
        IsMatch = True
    End FunctionPrivate Function GetDigit(ByVal x As Long, ByVal y As Long, ByRef n As Byte) As Boolean
        For n = 0 To 9
            If IsMatch(x, y, n) Then
                GetDigit = True
                Exit Function
            End If
        Next
        
        n = 0
    End FunctionPrivate Sub Command1_Click()
        Dim n1 As Byte, n2 As Byte
        Dim y As Long
        
        For y = 0 To 37 - DIGIT_HEIGHT
            If GetDigit(20, y, n2) Then
                Call GetDigit(11, y, n1)
                Debug.Print n1 * 10 + n2
            End If
        Next
    End Sub
      

  2.   

    Tiger Zhao 老师,谢谢你再次指点,如图的数字10中的1并没有占用7个宽度,是不是也要截取出这么大?
    背景的黑色要用你所说的方法去色吗?如果要判断数字的颜色应该如何处理?
    在动态背景(没有白色)下如果出现白色应该怎样判断呢?我试过用if getpixel(hdc,pt.t[i],pt.t[j])=RBG(0,0,0) then.......
    ......
    else
    ......
    endif 执行的效率非常慢,不知道有没有什么更好的解决方式?
      

  3.   

    刚才那段代码点击command调试的时候,提示类型不配配.
    有点没有看懂...
      

  4.   

    没错,因为字符的打印宽度还是7。
    其实你只要分辨某个点是否是黄色(锐化后)来判断是字还是背景;按照这种规则,很容易将一个图片转化为一个两维的 Boolean 数组。
    提高效率的方案如下:
    初始化时,将数字 0~9 的图片转化为 Boolean 数组。
    判断时将整个图片转化为 Boolean 数组,这样就是数组和数组之间的匹配,比反复取像素要快很多。
      

  5.   


    我已经将picture2按数组方式loading,但是picture1是实时监控的区域timer1中使用如下代码
    Cls
    StretchBlt Picture1.hdc, 2, 2, 901 - 851, 119 - 105, GetDC(0), 851, 105, 901 - 851, 119 - 105, Srccopy1
    form1中使用Timer1.Interval = 5 控制.
    能不能再详细用代码解释一下,谢谢.
      

  6.   

    替换一下,其它函数不变
    Private Type DigitImage
        a() As Boolean
    End TypePrivate m_Digits(9) As DigitImage
    Private m_CheckImage() As BooleanPrivate Function IsMatch(ByVal x As Long, ByVal y As Long, ByVal n As Byte) As Boolean
        Dim iX As Long, iY As Long
            
        For iX = 0 To DIGIT_WIDTH - 1
            For iY = 0 To DIGIT_HEIGHT - 1
                If m_CheckImage(x + iX, y + iY) <> m_Digits(n).a(iX, iY) Then
                    Exit Function
                End If
            Next
        Next
        
        IsMatch = True
    End FunctionPrivate Function ImageIdentify(ByVal pb As PictureBox, ByVal Width As Long, ByVal Height As Long) As Boolean()
        Dim a() As Boolean, x As Long, y As Long
        ReDim a(Width - 1, Height - 1)
        For x = 0 To Width - 1
            For y = 0 To Height - 1
                a(x, y) = (ColorSharpening(pb.Point(x, y)) = &HFFFF&)
            Next
        Next
    End FunctionPrivate Sub Command1_Click()
        Dim n1 As Byte, n2 As Byte
        Dim y As Long
        
        m_CheckImage = ImageIdentify(Picture1, 65, 37)
        
        For y = 0 To 37 - DIGIT_HEIGHT
            If GetDigit(20, y, n2) Then
                Call GetDigit(11, y, n1)
                Debug.Print n1 * 10 + n2
            End If
        Next
    End SubPrivate Sub Form_Load()
        Dim i As Long
        For i = 0 To 9
            m_Digits(i).a = ImageIdentify(Picture2(i), DIGIT_WIDTH, DIGIT_HEIGHT)
        Next
    End Sub
      

  7.   

    Tiger Zhao老师,程序还是不能调试通过,能不能给我一个你的邮箱,我将这部分的vbp代码给你发送过去,看是那个部分的整合出现问题了.新手上路,请多多指点...
      

  8.   

    StretchBlt 的最后一个参数,常量 Srccopy1 定义了没有,应该是 SRCCOPY 吧。
    所有 PictureBox 的 ScaleMode 都设为 3 - Pixel。 
      

  9.   

    SRCCOPY已经定义了,调试通过.
    ScaleMode也都已经设为3因为获取窗口的两个区域都是动态变化的,是不是跟载入picture的图像的方式有关?这里附上这个模块的代码:Private Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
    Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function SetWindowPos& Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long)
    Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
    Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long
    Const Srccopy1 = &HCC0020
    Const Srccopy2 = &HCC0020Private Sub Form_Load()Dim rtn
    rtn = SetWindowPos(Me.hwnd, -1, 0, 0, 0, 0, 3) 
    Timer1.Interval = 5End Sub
    Private Sub Timer1_Timer()
    Dim hdc As Long
    Dim i As Integer
    Dim ballr As Integer
    Cls
    StretchBlt Picture1.hdc, 2, 2, 901 - 851, 119 - 105, GetDC(0), 851, 105, 901 - 851, 119 - 105, Srccopy1
    StretchBlt Picture2.hdc, 4, 2, 256 - 243, 133 - 116, GetDC(0), 243, 116, 256 - 243, 133 - 116, Srccopy2End Sub
      

  10.   

    定时频率太高了,屏幕显示的内容总是给人看的,不可能这么高的更新率,每秒2次扫描都估计够了。
    你先不用定时器,用点击 CommandButton 的方式将单次的功能调试成功了再说。
      

  11.   

    因为要监控到一个即时运转的圆柱体,它的平面上有一个圆形的凹陷,1到3秒钟一圈,因为要统计转得圈数,使用了窗口部分区域监控,是否有变化,要怕截取不到画面变化,所以设定的高了一些.还是说要另外开一个form?另外,我载入到picture1数组的图片,Picture1(i).Visible = True为何不能显示图片呢?Option Explicit
       
      Private Sub Form_Load()
      Dim i  As Integer
      Dim path As String
      path="C:\Documents and Settings\Administrator\桌面\figure\79\"
              For i = 1 To 6
                      Load Picture1(i)
                      Picture1(i).Top = Picture1(0).Top + 200 * i
                      Picture1(i).Visible = True
                      Picture1(i).Picture = ( path & i & ".bmp")
              Next
      End Sub
      

  12.   

    使用这个也无法显示.
    Picture1(i).Picture =laodpicture ( path & i & ".bmp") 
      

  13.   

    凹陷和其它区域应该很容易区分吧,那么在高频监测中只要选取一个合理的点,它的与上次监测的对比情况只能是:
    背景->背景
    背景->凹陷
    凹陷->凹陷
    凹陷->背景
    那么只有变化时(比如选取 背景->凹陷)就是转了一圈。
      

  14.   

    Set Picture1(i).Picture =LOADpicture(path & i & ".bmp")