- 小学一年级
- 9439662
- 8
- 0
- 15 朵
- 36 个
- 21 个
- 0
- 2025-04-28
|
1#
t
T
发表于 2025-05-11 14:21
|
|只看楼主
本论坛的帖子 按键精灵调用Umi识别文字(本地无需做字库) _ 综合讨论 - 按键精灵论坛给出了本地建立服务器识别文字的方法。但我们要获取文字的同时还需要获取文字坐标,原帖子的方案就不行了。 原来想直接用按键精灵写个将图片在memory转码为base64的函数,但这个按键精灵的字节操作实在是乱,尝试了很久不行。后来用VB6直接做了个截屏转码的插件,解决了这个问题。 插件有2个函数 Plugin.SCTOBASE64.CaptureScreenRegionToBase64(x1, y1, x2, y2) 参数为目标区域相对屏幕的左上右下坐标,返回BASE64码 Plugin.SCTOBASE64.CaptureBackgroundWindowToBase64(hwd,x1, y1, x2, y2) 参数1为窗口句柄,记得是父窗口的句柄,这个在windows8以下不一定能返回正确图像,如果返回大量A,则找不到图像。 插件链接 通过网盘分享的文件:SCTOBASE64.zip 链接: https://pan.baidu.com/s/1CM7qL_On5LjbTe0EA40R6Q?pwd=qsqv 提取码: qsqv 以下的代码要下载论坛的免费神梦HTTP插件支持 - 返回文字
- Function 找字(x1, y1, x2, y2)
- Dim txt
- txt=""
- Dim URL,JsonData,json,username,password,base64
- URL = "http://127.0.0.1:1224/api/ocr"
- Base64 = Plugin.SCTOBASE64.CaptureScreenRegionToBase64(x1, y1, x2, y2)
- JsonData = SmHTTP.JsonData( _
- "base64",base64 , _
- "options", SmHTTP.JsonData( _
- "tbpu.parser","single_none",_
- "data.format","text"_
- ),_
- "Content-Type", "application/json" _
- )
- json = SmHTTP.HTTP_POST(URL, JsonData)
- If SmHTTP.GetStatus() = 200 Then
- If SmHTTP.GetJSON(json, "code") = 100 Then
- txt = SmHTTP.GetJSON(json, "data")
- If IsNull(txt) Then
- txt=""
- End If
- End If
- End If
- 找字=txt
- End Function
- Function 后台找字(hwd,x1, y1, x2, y2)
- Dim txt
- txt=""
- Dim URL,JsonData,json,username,password,base64
- URL = "http://127.0.0.1:1224/api/ocr"
- Base64 = Plugin.SCTOBASE64.CaptureBackgroundWindowToBase64(hwd,x1, y1, x2, y2)
- JsonData = SmHTTP.JsonData( _
- "base64",base64 , _
- "options", SmHTTP.JsonData( _
- "tbpu.parser","single_none",_
- "data.format","text"_
- ),_
- "Content-Type", "application/json" _
- )
- json = SmHTTP.HTTP_POST(URL, JsonData)
- If SmHTTP.GetStatus() = 200 Then
- If SmHTTP.GetJSON(json, "code") = 100 Then
- txt = SmHTTP.GetJSON(json, "data")
- If IsNull(txt) Then
- txt=""
- End If
- End If
- End If
- 后台找字=txt
- End Function
- //未找到 b(0,0)返回null,返回一个二维数组,第一维大小为5,b(0,0)文字内容,b(1,0)\b(2,0)\b(3,0)\b(4,0)文字相对的左上右下坐标。第二维为返回字符串数量
- Function 区域找字坐标(x1,y1,x2,y2)
- Redim findt(4, 0)
- findt(0, 0)=null
- Dim URL,JsonData,json,username,password,base64,counts
- URL = "http://127.0.0.1:1224/api/ocr"
- Base64 = Plugin.SCTOBASE64.CaptureScreenRegionToBase64(x1, y1, x2, y2)
- JsonData = SmHTTP.JsonData( _
- "base64",base64 , _
- "Content-Type", "application/json" _
- )
- json = SmHTTP.HTTP_POST(URL, JsonData)
- counts=字符串数量(json)
- TracePrint counts & json
- If SmHTTP.GetStatus() = 200 Then
- If SmHTTP.GetJSON(json, "code") = 100 Then
- Dim xx,i
- xx = null
- i=0
- xx =SmHTTP.GetJSON(json, "data[0]['text']")
- Do Until i>counts-1
- xx=null
- xx = SmHTTP.GetJSON(json, "data[" & i & "]['text']")
- If not IsNull(xx) and not IsEmpty(SmHTTP.GetJSON(json, "data["& i &"]['box'][0][0]")) and not IsNull(SmHTTP.GetJSON(json, "data["& i &"]['box'][0][0]")) Then
- If i > 0 Then
- Redim Preserve findt(4, i)
- End If
- findt(0,i) = SmHTTP.GetJSON(json, "data[" & i & "]['text']")
- findt(1,i)=SmHTTP.GetJSON(json, "data["& i &"]['box'][0][0]")
- findt(2,i)=SmHTTP.GetJSON(json, "data["& i &"]['box'][0][1]")
- findt(3,i)=SmHTTP.GetJSON(json, "data["& i &"]['box'][2][0]")
- findt(4, i) = SmHTTP.GetJSON(json, "data[" & i & "]['box'][2][1]")
- End If
- i=i+1
- loop
- Else
- findt(1, 0)=-1
- End If
- Else
- findt(1, 0)=-2
- End If
- 区域找字坐标=findt
- End Function
复制代码插件的VB6代码 - '--------------------------------------------------------------------------
- ' 您可以在这里添加自己的插件函数,插件的制作和使用方法如下:
- ' 第一步:在下面添加插件函数,一个插件可以添加多个函数。
- ' 第二步:请修改下面的Get_Plugin_Description函数,加入插件和插件函数的说明信息,帮助信息会显示在按键精灵里方便使用
- ' 第三步:请修改Class Module(类模块)的名字,尽量用一些独特的名字避免和别人的插件名字冲突(默认是MyPluginName)
- ' 第四步:生成插件DLL!将DLL文件放到按键精灵的PLUGIN目录下,然后启动按键精灵测试您制作的插件功能是否正常
- ' 对插件有任何问题请发邮件给我们: [email]hi@vrbrothers.com[/email]
- '--------------------------------------------------------------------------
- Option Explicit
- ' API声明
- Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
- Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
- Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
- Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
- Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC 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 dwRop As Long) As Long
- Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
- Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
- Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
- Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As Any, ByVal wUsage As Long) As Long
- Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
- Private Declare Function CryptBinaryToString Lib "crypt32.dll" Alias "CryptBinaryToStringA" (ByVal pbBinary As Long, ByVal cbBinary As Long, ByVal dwFlags As Long, ByVal pszString As String, ByRef pcchString As Long) As Long
- Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
- ' API声明
- Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
- Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As rect) As Long
- Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As rect) As Long
- Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
- Private Declare Function PrintWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal hdcBlt As Long, ByVal nFlags As Long) As Long
- '''''
- ' 结构体和常量
- Private Type rect
- Left As Long
- Top As Long
- Right As Long
- Bottom As Long
- End Type
- ' 常量定义
- Private Const CRYPT_STRING_BASE64 As Long = 1
- Private Const BI_RGB As Long = 0
- Private Const DIB_RGB_COLORS As Long = 0
- Private Const PW_RENDERFULLCONTENT As Long = 2 ' Windows 8+ 支持捕获完整内容
- ' 结构体定义
- Private Type BITMAP
- bmType As Long
- bmWidth As Long
- bmHeight As Long
- bmWidthBytes As Long
- bmPlanes As Integer
- bmBitsPixel As Integer
- bmBits As Long
- End Type
- Private Type BITMAPINFOHEADER
- biSize As Long
- biWidth As Long
- biHeight As Long
- biPlanes As Integer
- biBitCount As Integer
- biCompression As Long
- biSizeImage As Long
- biXPelsPerMeter As Long
- biYPelsPerMeter As Long
- biClrUsed As Long
- biClrImportant As Long
- End Type
- Private Type BITMAPFILEHEADER
- bfType As Integer
- bfSize As Long
- bfReserved1 As Integer
- bfReserved2 As Integer
- bfOffBits As Long
- End Type
- ' 截取后台窗口区域并转化为base64
- Public Function CaptureBackgroundWindowToBase64(hWndx As Long, ByVal x1 As Long, ByVal y1 As Long, ByVal x2 As Long, ByVal y2 As Long) As String
- Dim hwnd As Long, hdcWindow As Long, hdcMem As Long, hBitmap As Long, hOldBmp As Long
- Dim hdcMem2 As Long, hBitmap2 As Long, hOldBmp2 As Long
- Dim rect As rect, clientRect As rect, bmpInfo As BITMAPINFOHEADER, bmpFileHeader As BITMAPFILEHEADER
- Dim pixelBytes() As Byte, bytes() As Byte
- Dim bufferSize As Long, retVal As Long
- Dim tempStr As String
-
- Dim Width As Long: Width = x2 - x1 ' 截取宽度
- Dim Height As Long: Height = y2 - y1 ' 截取高度
- Dim srcX As Long: srcX = x1 ' 截取起始X坐标(相对窗口左上角)
- Dim srcY As Long: srcY = y1 ' 截取起始Y坐标(相对窗口左上角)
- ' 通过窗口标题获取句柄
- hwnd = hWndx
- If hwnd = 0 Then
- Exit Function
- End If
-
- ' 获取窗口位置(仅用于区域定位,实际截图用PrintWindow)
- GetWindowRect hwnd, rect
- GetClientRect hwnd, clientRect
-
- Debug.Print rect.Left & " " & rect.Top & " " & rect.Right&; " " & rect.Bottom
- Debug.Print clientRect.Left & " " & clientRect.Top & " " & clientRect.Right&; " " & clientRect.Bottom
- Dim winWidth As Long: winWidth = rect.Right - rect.Left
- Dim winHeight As Long: winHeight = rect.Bottom - rect.Top
- Dim offX As Long: offX = clientRect.Left - rect.Left '客户区相对于母窗口的偏移
- Dim offY As Long: offY = clientRect.Top - rect.Top
- ' 检查截取区域是否在窗口范围内
- If srcX + Width + offX > winWidth Or srcY + Height + offY > winHeight Then
- Exit Function
- End If
-
- ' 创建兼容DC和位图
- hdcWindow = GetDC(hwnd)
- hdcMem = CreateCompatibleDC(hdcWindow)
- hBitmap = CreateCompatibleBitmap(hdcWindow, winWidth, winHeight) ' 截取目标区域
- hOldBmp = SelectObject(hdcMem, hBitmap)
- Debug.Print hwnd
- ' 使用PrintWindow捕获后台窗口(PW_RENDERFULLCONTENT需Windows 8+),win8以下这里设为0,但不一定能正常获取图像
- If PrintWindow(hwnd, hdcMem, PW_RENDERFULLCONTENT) = 0 Then
- GoTo Cleanup
- End If
-
- ' 创建第二个memoryDC和位图(用于截取目标区域)
- hdcMem2 = CreateCompatibleDC(hdcWindow)
- hBitmap2 = CreateCompatibleBitmap(hdcWindow, Width, Height)
- hOldBmp2 = SelectObject(hdcMem2, hBitmap2)
-
- ' 从原memoryDC的(srcX, srcY)位置复制目标区域到新位图
- If BitBlt(hdcMem2, 0, 0, Width, Height, hdcMem, srcX + offX, srcY + offY, vbSrcCopy) = 0 Then
- GoTo Cleanup
- End If
-
-
- ' 获取位图信息
- With bmpInfo
- .biSize = Len(bmpInfo)
- .biWidth = Width
- .biHeight = -Height ' 顶部到底部
- .biPlanes = 1
- .biBitCount = 24 ' 24位色
- .biCompression = BI_RGB
- .biSizeImage = ((Width * 3 + 3) \ 4) * 4 * Height ' 计算图像大小
- End With
-
- ' 获取像素数据
- ReDim pixelBytes(0 To bmpInfo.biSizeImage - 1)
- If GetDIBits(hdcMem2, hBitmap2, 0, Height, pixelBytes(0), bmpInfo, DIB_RGB_COLORS) = 0 Then
- ' MsgBox "获取像素数据失败!", vbExclamation
- GoTo Cleanup
- End If
-
- ' 构造BMP文件头
- With bmpFileHeader
- .bfType = &H4D42 ' "BM"
- .bfSize = Len(bmpFileHeader) + Len(bmpInfo) + bmpInfo.biSizeImage
- .bfOffBits = Len(bmpFileHeader) + Len(bmpInfo)
- End With
-
- ' 合并为完整BMP数据
- ReDim bytes(0 To bmpFileHeader.bfSize - 1)
- ' 1. bfType (2字节)
- bytes(0) = &H42 ' "B"
- bytes(1) = &H4D ' "M"
- ' 2. bfSize (4字节,小端序)
- CopyMemory bytes(2), bmpFileHeader.bfSize, 4
- ' 3. bfReserved1/2 (4字节)
- bytes(6) = 0: bytes(7) = 0: bytes(8) = 0: bytes(9) = 0
- ' 4. bfOffBits (4字节,小端序)
- CopyMemory bytes(10), bmpFileHeader.bfOffBits, 4
-
- CopyMemory bytes(Len(bmpFileHeader)), bmpInfo, Len(bmpInfo)
- CopyMemory bytes(Len(bmpFileHeader) + Len(bmpInfo)), pixelBytes(0), bmpInfo.biSizeImage
-
- ' 保存为BMP文件,此段注释掉,为检查代码能否正常运行设置
-
- 'Dim FileNum As Integer
- 'Dim FilePath As String
- ' FilePath = "d:\test2.bmp"
- ' FileNum = FreeFile()
- ' Open FilePath For Binary Access Write As #FileNum
- ' Put #FileNum, 1, bytes()
- ' Close #FileNum
-
-
-
- ' 转换为Base64
- bufferSize = 0
- CryptBinaryToString VarPtr(bytes(0)), UBound(bytes) + 1, CRYPT_STRING_BASE64, vbNullString, bufferSize
- tempStr = Space$(bufferSize)
- retVal = CryptBinaryToString(VarPtr(bytes(0)), UBound(bytes) + 1, CRYPT_STRING_BASE64, tempStr, bufferSize)
- If retVal Then
- tempStr = Left$(tempStr, bufferSize - 1)
- tempStr = Replace$(tempStr, vbCrLf, "") ' 先处理Windows换行符
- tempStr = Replace$(tempStr, vbCr, "") ' 再处理Mac旧换行符
- tempStr = Replace$(tempStr, vbLf, "") ' 最后处理Unix换行符
- CaptureBackgroundWindowToBase64 = Left$(tempStr, bufferSize - 1)
- End If
- Cleanup:
- ' 清理资源
- If hdcMem2 <> 0 Then
- SelectObject hdcMem2, hOldBmp2
- DeleteObject hBitmap2
- DeleteDC hdcMem2
- End If
- If hdcMem <> 0 Then
- SelectObject hdcMem, hOldBmp
- DeleteObject hBitmap
- DeleteDC hdcMem
- End If
- If hdcWindow <> 0 Then ReleaseDC hwnd, hdcWindow
- End Function
- ' 截取屏幕区域并返回Base64编码
- Public Function CaptureScreenRegionToBase64(ByVal x As Long, ByVal y As Long, ByVal x1 As Long, ByVal y1 As Long) As String
- Dim hScreenDC As Long, hMemDC As Long, hBitmap As Long, hOldBitmap As Long
- Dim bmp As BITMAP, bmpInfo As BITMAPINFOHEADER, bmpFileHeader As BITMAPFILEHEADER
- Dim pixelBytes() As Byte, bytes() As Byte
- Dim result As Long, bufferSize As Long, retVal As Long
- Dim tempStr As String
- Dim Width As Long, Height As Long
- Width = x1 - x
- Height = y1 - y
- ' 获取屏幕设备上下文
- hScreenDC = GetDC(0)
- If hScreenDC = 0 Then Exit Function
-
- ' 创建兼容DC和位图
- hMemDC = CreateCompatibleDC(hScreenDC)
- If hMemDC = 0 Then GoTo Cleanup
- hBitmap = CreateCompatibleBitmap(hScreenDC, Width, Height)
- If hBitmap = 0 Then GoTo Cleanup
- hOldBitmap = SelectObject(hMemDC, hBitmap)
-
- ' 复制屏幕区域
- result = BitBlt(hMemDC, 0, 0, Width, Height, hScreenDC, x, y, vbSrcCopy)
- If result = 0 Then GoTo Cleanup
-
- ' 获取位图信息
- GetObject hBitmap, Len(bmp), bmp
-
-
- ' 设置BITMAPINFOHEADER
- With bmpInfo
- .biSize = Len(bmpInfo)
- .biWidth = bmp.bmWidth
- .biHeight = -bmp.bmHeight ' 顶部到底部
- .biPlanes = 1
- .biBitCount = 24 ' 24位色
- .biCompression = BI_RGB
- .biSizeImage = ((bmp.bmWidth * 3 + 3) \ 4) * 4 * bmp.bmHeight ' 计算图像大小
- End With
-
- ' 获取像素数据
- ReDim pixelBytes(0 To bmpInfo.biSizeImage - 1)
- result = GetDIBits(hMemDC, hBitmap, 0, bmp.bmHeight, pixelBytes(0), bmpInfo, DIB_RGB_COLORS)
- If result = 0 Then GoTo Cleanup
-
- ' 构造BMP文件头
- With bmpFileHeader
- .bfType = &H4D42 ' "BM"
- .bfSize = Len(bmpFileHeader) + Len(bmpInfo) + bmpInfo.biSizeImage
- .bfOffBits = Len(bmpFileHeader) + Len(bmpInfo)
- End With
-
- ' 手动写入文件头(确保正确的字节顺序)
- ReDim bytes(0 To bmpFileHeader.bfSize - 1)
- ' 1. bfType (2字节)
- bytes(0) = &H42 ' "B"
- bytes(1) = &H4D ' "M"
- ' 2. bfSize (4字节,小端序)
- CopyMemory bytes(2), bmpFileHeader.bfSize, 4
- ' 3. bfReserved1/2 (4字节)
- bytes(6) = 0: bytes(7) = 0: bytes(8) = 0: bytes(9) = 0
- ' 4. bfOffBits (4字节,小端序)
- CopyMemory bytes(10), bmpFileHeader.bfOffBits, 4
-
- CopyMemory bytes(Len(bmpFileHeader)), bmpInfo, Len(bmpInfo)
- CopyMemory bytes(Len(bmpFileHeader) + Len(bmpInfo)), pixelBytes(0), bmpInfo.biSizeImage
-
- ' 保存为BMP文件,测试程序时使用,备注掉
-
- ' Dim FileNum As Integer
- ' Dim FilePath As String
- ' FilePath = "d:\test1.bmp"
- ' FileNum = FreeFile()
- ' Open FilePath For Binary Access Write As #FileNum
- ' Put #FileNum, 1, bytes()
- ' Close #FileNum
-
-
-
- ' 转换为Base64
- bufferSize = 0
- CryptBinaryToString VarPtr(bytes(0)), UBound(bytes) + 1, CRYPT_STRING_BASE64, vbNullString, bufferSize
- tempStr = Space$(bufferSize)
- retVal = CryptBinaryToString(VarPtr(bytes(0)), UBound(bytes) + 1, CRYPT_STRING_BASE64, tempStr, bufferSize)
-
-
-
- If retVal Then
- tempStr = Left$(tempStr, bufferSize - 1)
- tempStr = Replace$(tempStr, vbCrLf, "") ' 先处理Windows换行符
- tempStr = Replace$(tempStr, vbCr, "") ' 再处理Mac旧换行符
- tempStr = Replace$(tempStr, vbLf, "") ' 最后处理Unix换行符
- CaptureScreenRegionToBase64 = tempStr
- End If
- Cleanup:
- ' 清理资源
- If hMemDC <> 0 Then
- SelectObject hMemDC, hOldBitmap
- DeleteObject hBitmap
- DeleteDC hMemDC
- End If
- DeleteDC hScreenDC
- End Function
- '下面这个函数为您的插件提供帮助信息,请只修改和添加里面的描述信息,而不要修改函数本身
- Public Function Get_Plugin_Description(ItemName As String) As String
- Dim Description_Text As String
- Description_Text = ""
- Select Case ItemName
- Case ""
- Description_Text = "在这里写您的插件的说明信息"
- Case "CaptureBackgroundWindowToBase64"
- Description_Text = "CaptureBackgroundWindowToBase64,截取后台窗口区域图像并转为base64"
- Case "CaptureScreenRegionToBase64"
- Description_Text = "CaptureScreenRegionToBase64,截取屏幕区域图像并转为base64"
-
- '------------------------------------------------
- '为您的每个插件函数建立一个Case,就可以在按键精灵里显示插件的使用说明
- '------------------------------------------------
- End Select
- Get_Plugin_Description = Translate_Description(Description_Text)
- End Function
- '下面这个函数为您的插件提供显示模板信息,请只修改和添加里面的描述信息,而不要修改函数本身
- '描述信息中的$1 $2 ... 等内容再显示时将用第一个参数、第二个参数、... 代替
- Public Function Get_Plugin_Interpret_Template(ItemName As String) As String
- Dim Description_Text As String
- Description_Text = ""
- Select Case ItemName
- Case ""
- Description_Text = "在这里写您的插件的说明信息"
- Case "CaptureBackgroundWindowToBase64"
- Description_Text = "参数1为窗口句柄,参数2、3为截取图片左上角相对于后台窗口左上角的X/Y坐标,参数4、5为右下角坐标"
- Case "CaptureScreenRegionToBase64"
- Description_Text = "参数1、2为截取图片左上角的X/Y坐标,参数3、4为右下角坐标"
-
- '------------------------------------------------
- '为您的每个插件函数建立一个Case,就可以在按键精灵里显示插件的使用说明
- '------------------------------------------------
- End Select
- Get_Plugin_Interpret_Template = Translate_Description(Description_Text)
- End Function
复制代码
|