OCR für QWidget-Controls

  • Da es Programme gibt, bei denen man mit ControlGetText keine Erfolge erzielt (hauptsächlich Programme mit QWidget-Controls die nicht kompatibel zur Windows-API sind), gibt es nur die Möglichkeit, die benötigten Daten über OCR auszulesen. Durch diesen diesen Artikel von Andy wurde ich auf die Programme djpeg und gocr aufmerksam. Es sind Komandozeilentools um aus einem Bild Text auszulesen. djpeg wandelt das jpg-Bild in ein Graustufenbild um, damit gocr besser den Text finden kann.

    _ReadControl_OCR funktioniert es mit allen Controls und nicht nur mit QWidgets
    Mit _ReadGuiArea_OCR kann ein Bereich eines Fensters ausgewählt werden.

    djpeg.exe
    gocr.exe
    Diese Dateien habe ich im Beispiel im Ordner @ScriptDir&'\App liegen.

    Funktionen mit Beispiel
    [autoit]

    #include <ScreenCapture.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Local $pid = Run('notepad.exe')
    WinWait('[Class:Notepad]')
    WinActivate('[Class:Notepad]')
    WinWaitActive('[Class:Notepad]')
    Send('Das wird über OCR ausgelesen!')

    [/autoit] [autoit][/autoit] [autoit]

    Local $text = _ReadControl_OCR("[Class:Notepad]", "", "Edit1", 2, 2, @ScriptDir&'\App')
    If @error Then
    MsgBox(16, "Fehler", @error)
    Else
    MsgBox(64, "Ergebnis", $text)
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    Local $text = _ReadGuiArea_OCR("[Class:Notepad]", "", 3, 2, 350, 18, @ScriptDir&'\App')
    If @error Then
    MsgBox(16, "Fehler", @error)
    Else
    MsgBox(64, "Ergebnis", $text)
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ProcessClose($pid)

    [/autoit] [autoit][/autoit] [autoit]

    Func _ReadControl_OCR($hWnd, $sText, $hCtrl, $iBorderX = 0, $iBorderY = 0, $AppDir = @ScriptDir)
    ;funkey
    WinActivate($hWnd)
    Local $Timeout = WinWaitActive($hWnd, $sText, 1)
    If Not $Timeout Then Return SetError(1, 0, "")
    Local $WinPos = WinGetPos($hWnd, $sText)
    Local $ControlPos = ControlGetPos($hWnd, $sText, $hCtrl)
    If @error Then Return SetError(2, 0, "")
    Local $aClientSize = WinGetClientSize($hWnd, $sText)
    If @error Then Return SetError(3, 0, "")
    Local $Rahmen = ($WinPos[2] - $aClientSize[0]) / 2
    Local $iOffsetx = $WinPos[2] - $aClientSize[0] - $Rahmen
    Local $iOffsety = $WinPos[3] - $aClientSize[1] - $Rahmen
    Local $Wert = ""
    _ScreenCapture_Capture(@ScriptDir & '\TextControl.jpg', _
    $WinPos[0] + $ControlPos[0] + $iOffsetx + $iBorderX, _
    $WinPos[1] + $ControlPos[1] + $iOffsety + $iBorderY, _
    $WinPos[0] + $ControlPos[0] + $ControlPos[2] + $iOffsetx - $iBorderX, _
    $WinPos[1] + $ControlPos[1] + $ControlPos[3] + $iOffsety - $iBorderY, False)
    RunWait($AppDir & '\djpeg -greyscale -dither none TextControl.jpg TextControl.pnm', @ScriptDir, @SW_HIDE)
    Local $App = Run($AppDir & '\gocr -i TextControl.pnm', @ScriptDir, @SW_HIDE, 0x2)
    While 1
    $Wert &= StdoutRead($App)
    If @error Then ExitLoop
    WEnd
    FileDelete(@ScriptDir & '\TextControl.jpg')
    FileDelete(@ScriptDir & '\TextControl.pnm')
    Return $Wert
    EndFunc ;==>_ReadQWidget

    [/autoit] [autoit][/autoit] [autoit]

    Func _ReadGuiArea_OCR($hWnd, $sText, $x1, $y1, $x2, $y2, $AppDir = @ScriptDir)
    ;funkey
    WinActivate($hWnd)
    Local $Timeout = WinWaitActive($hWnd, $sText, 1)
    If Not $Timeout Then Return SetError(1, 0, "")
    Local $WinPos = WinGetPos($hWnd, $sText)
    Local $aClientSize = WinGetClientSize($hWnd, $sText)
    If @error Then Return SetError(2, 0, "")
    Local $Rahmen = ($WinPos[2] - $aClientSize[0]) / 2
    Local $iOffsetx = $WinPos[2] - $aClientSize[0] - $Rahmen
    Local $iOffsety = $WinPos[3] - $aClientSize[1] - $Rahmen
    Local $Wert = ""
    _ScreenCapture_Capture(@ScriptDir & '\TextArea.jpg', _
    $WinPos[0] + $x1 + $iOffsetx, _
    $WinPos[1] + $y1 + $iOffsety, _
    $WinPos[0] + $x2 + $iOffsetx, _
    $WinPos[1] + $y2 + $iOffsety, False)
    RunWait($AppDir & '\djpeg -greyscale -dither none TextArea.jpg TextArea.pnm', @ScriptDir, @SW_HIDE)
    Local $App = Run($AppDir & '\gocr -i TextArea.pnm', @ScriptDir, @SW_HIDE, 0x2)
    While 1
    $Wert &= StdoutRead($App)
    If @error Then ExitLoop
    WEnd
    FileDelete(@ScriptDir & '\TextArea.jpg')
    FileDelete(@ScriptDir & '\TextArea.pnm')
    Return $Wert
    EndFunc ;==>_ReadQWidget

    [/autoit]

    Kommentare sind herzlich willkommen ;)

  • Hey, das ist doch mal richtig hamma :D
    mit dem Ergebnis (vista):
    "Das wird uber ocR ausge_esen"
    kann man leben :)
    Vielen Dank für das Beispiel, ich werds sicherlich noch öfters benutzen :thumbup:

    Wer immer nur das tut, was er bereits kann - wird auch immer nur das bleiben, was er bereits ist!