В ожидании изменений шрифтов в EVE задался вопросом, как бы улучшить используемый мною алгоритм декодирования, этих самых шрифтов.
Учитывая, что после введения ССР новых "некапсовых" шрифтов, всё равно придется обновлять таблицы их распознавания, обращаюсь за помощью в вопросе приведения той "халтуры", что у меня есть к более правильному виду.
Что не нравится:
[list type=decimal]
[*]Алгоритм делает два прохода по одному месту (для не пробельных символов), что как-то расточительно.
[*]Хотя точность распознавания при нормально подобранном пороге очень высока, но напрягает сам подбор порога в ручную.
[*]В дополнение ко второму пункту, хотелось бы уменьшить привязку к элементам на которых мы распознаем (SI, оверью и т.п.), чтобы не использовать отдельные таблицы для каждого элемента (хотя стоит ли это делать вопрос философский )
[*]Может как попроще сделать?
[/list]
В листингах указана известная на форуме функция определения цвета точки через яркость, в реальности задействована естественна не она, а несколько более быстрая, поэтому предлагать оптимизировать скорость определения цвета не стоит.
Функции кодирования и декодирования
Функции несколько "засорены" излишним кодом, потому что выдраны из ZoomInfo v0.44 http://autoit-script.ru/index.php/topic,3636.0.html.
Учитывая, что после введения ССР новых "некапсовых" шрифтов, всё равно придется обновлять таблицы их распознавания, обращаюсь за помощью в вопросе приведения той "халтуры", что у меня есть к более правильному виду.
Что не нравится:
[list type=decimal]
[*]Алгоритм делает два прохода по одному месту (для не пробельных символов), что как-то расточительно.
[*]Хотя точность распознавания при нормально подобранном пороге очень высока, но напрягает сам подбор порога в ручную.
[*]В дополнение ко второму пункту, хотелось бы уменьшить привязку к элементам на которых мы распознаем (SI, оверью и т.п.), чтобы не использовать отдельные таблицы для каждого элемента (хотя стоит ли это делать вопрос философский )
[*]Может как попроще сделать?
[/list]
В листингах указана известная на форуме функция определения цвета точки через яркость, в реальности задействована естественна не она, а несколько более быстрая, поэтому предлагать оптимизировать скорость определения цвета не стоит.
Функции кодирования и декодирования
Код:
Func Decode_OCR()
Local $decodeTimer = TimerInit()
Local $sum = ''
Local $hPic = GUICtrlGetHandle($PicOCR)
Local $pos = WinGetPos($hPic)
Local $countChar = 0, $code = 0, $j = 0 ; j-счетчик непустоты столбца
Local $iEmpty = 0 ; счетчик пустых столбцов
Local $bI = True ; Если True, то разделитель первый, False = разделитель был и в предыдущем столбце
Local $Xp = $pos[0], $Yp = $pos[1], $Wp = $pos[2], $Hp = $pos[3]
Local $x1 = 0, $y1 = $Wp
For $x = 0 To $Wp
Local $codeY = 0
Local $i = 0 ; счетчик пройденности порога анализа
For $y = 0 To $Hp
Local $color = TBitsGetColorR($x, $y, $Wp)
If $color > $limit Then ; Порог анализа пройден
If $i = 0 Then $i = 1
$codeY += $i
If $y < $y1 Then $y1 = $y
EndIf
$i *= 2 ; Положение точки
Next
If $i == 0 And $bI And $code <> 0 Then ; Если это разделитель и он первый
$bI = False
If $iEmpty > 3 And $countChar > 0 Then ; ВНИМАНИЕ! Считаем, что четыре столбца следующие последовательно дают символ пробела
$sum &= ' '
EndIf
$iEmpty = 1
Local $YV = CodingV($x1, $y1, $x, $Hp, $Wp)
Local $value = IniRead('Code - 0x'& Hex($limit,2) &'.Txt', $code, $YV, '*')
$sum &= $value
$j = 0
$countChar += 1
$code = 0
$x1 = $x ; следуем за иксом пока нам попадаются разделители, чтобы потом знать на каком иксе они закончились
ContinueLoop
EndIf
If $i == 0 Then
$iEmpty += 1
$x1 = $x ; следуем за иксом пока нам попадаются разделители, чтобы потом знать на каком иксе они закончились
ContinueLoop
EndIf
$j += 1 ; Пройденный столбец был чем-то наполнен
$code += $codeY*$j
$bI = True
Next
If $code <> 0 Then ; На случай, если последним столбцом был не пустой (хотя и нежелательно)
ConsoleWrite('Код с последним столбцом: '& $code & @CR)
EndIf
ConsoleWrite('Строка = <'& $sum &'>' & @CR)
ConsoleWrite('Время выполнения: '& TimerDiff($decodeTimer) & @CR)
GUICtrlSetData($lbOCRDecodeString, '<'& $sum &'>')
Return $sum
EndFunc
Func Code_OCR()
; ============== Создаем красную рамочку для выделения кодируемого символа ==============
Local $GUI = GUICreate("", 0, 0, 1, 1, $WS_POPUP)
Local $Top = GUICreate("Top Line", 0, 0, 1, 1, $WS_POPUP, -1, $GUI)
GUISetBkColor(0xFF0000)
GUISetState()
Local $Left = GUICreate("Left Line", 0, 0, 1, 1, $WS_POPUP, -1, $GUI)
GUISetBkColor(0xFF0000)
GUISetState()
Local $Right = GUICreate("Right Line", 0, 0, 1, 1, $WS_POPUP, -1, $GUI)
GUISetBkColor(0xFF0000)
GUISetState()
Local $Bottom = GUICreate("Bottom Line", 0, 0, 1, 1, $WS_POPUP, -1, $GUI)
GUISetBkColor(0xFF0000)
GUISetState()
WinSetOnTop($Top,"",1)
WinSetOnTop($Left,"",1)
WinSetOnTop($Right,"",1)
WinSetOnTop($Bottom,"",1)
;============== Основной блок функции ==============
Local $decodeTimer = TimerInit()
Local $hPic = GUICtrlGetHandle($PicOCR)
Local $pos = WinGetPos($hPic)
Local $countChar = 0, $code = 0, $j = 0 ; j-счетчик непустоты столбца, jP - позиция со степенью 2
Local $bI = True ; Если True, то разделитель первый, False = разделитель был и в предыдущем столбце
Local $Xp = $pos[0], $Yp = $pos[1], $Wp = $pos[2], $Hp = $pos[3]
Local $x1 = 0, $y1 = $Wp
Local $xG = 0 ; координата x для рамочки
For $x = 0 To $Wp
Local $codeY = 0
Local $i = 0 ; счетчик пройденности порога анализа
For $y = 0 To $Hp
Local $color = TBitsGetColorR($x, $y, $Wp)
If $color > $limit Then ; Порог анализа пройден
If $i = 0 Then $i = 1
$codeY += $i
If $y < $y1 Then $y1 = $y
EndIf
$i *= 2 ; Положение точки
Next
If $i == 0 And $bI And $code <> 0 Then ; Если это разделитель и он первый
$bI = False
;============== Перемещаем рамочку вслед за кодируемым символом ==============
WinMove($Top, "", $Xp+$x-1-$j, $Yp-1, $j+1, 1)
WinMove($Left, "", $Xp+$x-1-$j, $Yp-1, 1, $Hp+1)
WinMove($Right, "", $Xp+$x, $Yp-1, 1, $Hp+1)
WinMove($Bottom, "", $Xp+$x-1-$j, $Yp+$Hp, $j+1, 1)
;============== Узнаем вертикальный код и запрашиваем ввод значения ==============
Local $YV = CodingV($x1+1, $y1, $x-1, $Hp, $Wp)
Local $valueRead = IniRead('Code - 0x'& Hex($limit,2) &'.Txt', $code, $YV, 'Символ не задан')
Local $value
Do
If $valueRead = 'Символ не задан' Then
$value = InputBox("Значение кода", "Введите символ, который означает код <"& $code &">:<"& $YV &">", "", "", -1, -1, 0, 0)
Else
$value = InputBox("Значение кода", "Подтвердите символ, который означает код <"& $code &">:<"& $YV &">"& @CR & "Значится символ: ["& $valueRead &"]", $valueRead, "", -1, -1, 0, 0)
If $value <> $valueRead Then MsgBox(16, 'Дубликат кода!', 'Перезаписан символ <'& $valueRead &'>')
EndIf
if @error Then
$code = 0
ExitLoop 2
EndIf
Until $value <> ''
ConsoleWrite('№'& $countChar &' Код: '& $code & ', YV='& $YV &', Значение: '& $value & @CR)
IniWrite('Code - 0x'& Hex($limit,2) &'.Txt', $code, $YV, $value) ; Записываем код в файл только в том случае, если его там еще не было
$j = 0
$countChar += 1
$code = 0
$x1 = $x
ContinueLoop
EndIf
If $i == 0 Then
$x1 = $x ; следуем за иксом пока нам попадаются разделители, чтобы потом знать на каком иксе они закончились
ContinueLoop
EndIf
$j += 1 ; Пройденный столбец был чем-то наполнен
$code += $codeY*$j
$bI = True
$xG += 2
Next
If $code <> 0 Then ; На случай, если последним столбцом был не пустой (хотя и нежелательно)
ConsoleWrite('Код с последним столбцом: '& $code & @CR)
EndIf
GUIDelete($Bottom)
GUIDelete($Right)
GUIDelete($Left)
GUIDelete($Top)
GUIDelete($GUI)
EndFunc
Func CodingV($x1, $y1, $x2, $y2, $width)
Local $code = 0
For $y = $y1 To $y2
Local $codeX = 0
Local $i = 0
For $x = $x1 To $x2
Local $color = TBitsGetColorR($x, $y, $width)
If $color > $limit Then
If $i = 0 Then $i = 1
$codeX += $i
EndIf
$i *= 2
Next
$code += ($y-$y1)*$codeX
Next
Return $code
EndFunc
; В оригинальной функции возвращалась красная компонента цвета
; Для более адекватной по времени работы функции необходимо вставить "правильное" определение цвета точки
Func TBitsGetColorR($x, $y, $width=1024)
$color = PixelGetColor($x, $y)
Return TrimColor($color)
EndFunc
Функции несколько "засорены" излишним кодом, потому что выдраны из ZoomInfo v0.44 http://autoit-script.ru/index.php/topic,3636.0.html.