aardio 文档

aardio 范例: 图文识别 - 使用系统自带 OCR 组件(Windows.Media.Ocr)

相关范例 - 使用 dotNet.ocr 屏幕找字

//图文识别 - 使用系统自带 OCR 组件(Windows.Media.Ocr)
//相关范例 - 使用 dotNet.ocr 屏幕找字: https://www.aardio.com/zh-cn/docs/examples/Automation/ComputerVision/ocrUwp.html

import win.ui;
import win.dlg.message;
import fonts.fontAwesome;
/*DSG{{*/
var winform = win.form(text="dotNet.ocr 图文识别工具 - 调用系统自带组件,速度快,不限量,免费";right=1169;bottom=573)
winform.add(
bkplus={cls="bkplus";left=-17;top=516;right=1170;bottom=575;bgcolor=0xF5F5F5;db=1;dl=1;dr=1;z=1};
btnOcr={cls="plus";text="识别文本";left=844;top=532;right=947;bottom=562;align="left";color=0x3C3C3C;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF0F6';notify=1;textPadding={left=25};z=6};
btnOpen={cls="plus";text="打开图像文件";left=379;top=532;right=512;bottom=562;align="left";color=0x3C3C3C;db=1;dl=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF03E';notify=1;textPadding={left=25};z=4};
btnPaste={cls="plus";text="粘粘自剪贴板";left=246;top=532;right=365;bottom=562;align="left";color=0x3C3C3C;db=1;dl=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF0EA';notify=1;textPadding={left=25};z=5};
btnScreenClip={cls="plus";text="截屏";left=162;top=532;right=232;bottom=562;align="left";color=0x3C3C3C;db=1;dl=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF030';notify=1;textPadding={left=25};z=10};
comboLanguage={cls="combobox";left=690;top=535;right=828;bottom=561;db=1;dr=1;edge=1;items={};mode="dropdownlist";vscroll=1;z=8};
edit={cls="richedit";left=589;top=0;right=1168;bottom=515;autohscroll=false;aw=1;db=1;dr=1;dt=1;edge=1;link=1;multiline=1;vscroll=1;z=3};
lbLanguage={cls="static";text="语言:";left=616;top=530;right=679;bottom=560;align="right";center=1;db=1;dr=1;transparent=1;z=9};
lnkOptimize={cls="plus";text="AI 优化";left=950;top=532;right=1037;bottom=562;align="left";color=0x3498DB;db=1;disabled=1;dr=1;font=LOGFONT(h=-14);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome')};iconText='\uF0D0 ';notify=1;textPadding={left=18};z=11};
lnkTranslate={cls="plus";text="AI 翻译";left=1052;top=532;right=1139;bottom=562;align="left";color=0x3498DB;db=1;disabled=1;dr=1;font=LOGFONT(h=-14);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome')};iconText='\uF0DB';notify=1;textPadding={left=18};z=12};
picturebox={cls="plus";text="请复制图像到剪贴板 / 或拖放文件到此处";left=0;top=0;right=584;bottom=515;aw=1;bgcolor=0xFFFFFF;color=0x999999;db=1;dl=1;dt=1;edge=1;font=LOGFONT(h=-16);iconStyle={font=LOGFONT(h=-60;name='FontAwesome')};iconText='\uF03E';repeat="scale";textPadding={top=100};z=2};
splitter={cls="splitter";left=583;top=0;right=588;bottom=515;bgcolor=0xFFFFFF;db=1;dt=1;frame=1;z=7}
)
/*}}*/

var ocr = function(winform,language,imageBuffer){

    import dotNet.ocr; 
    var engine = dotNet.ocr();
    engine.language = language;

    var result = engine.detectBuffer(imageBuffer);

    if(result){
        // 移除成员函数,仅保留纯值
        result = table.parseValue(result)

        // 不需要记录每个字的位置
        for(k,v in result.blocks){
            v.wordRects = null;
        }

        winform.edit.text = result.text; 

        import JSON;
        winform.ocrResultData = JSON.stringify(result,false,false);

        winform.lnkTranslate.disabled = false;
        winform.lnkOptimize.disabled = false;
    } 
    else {
        winform.edit.text = "识别结果为空,请确保系统已安装 OCR 语言包(Win10/11 默认自带)";
    }

    winform.btnOcr.disabledText = null;  
}

winform.btnOcr.oncommand = function(id,event){
    if(winform.picturebox.backgroundBitmap){ 
        winform.edit.text = "识别中 ..."
        winform.btnOcr.disabledText = ['\uF254','\uF251','\uF252','\uF253','\uF250',text='识别中 ...']

        thread.invoke(ocr,winform,winform.comboLanguage.selText,winform.picturebox.backgroundBitmap.saveToBuffer("*.png"));
    }
    else {
        winform.msgErr("请先复制图像到剪贴板 / 或打开图像文件")
    } 
}

import fsys.dlg;
winform.btnOpen.oncommand = function(id,event){
    var path = fsys.dlg.open("图像文件|*.jpg;*.jpeg;*.jfif;*.bmp;*.gif;*.png;*.tif;*.tiff;*.webp||",,,winform)
    if(path){
        if(string.endsWith(path,".webp",true)){
            import gdip.webp;
        }
        winform.picturebox.background = path; 
        winform.picturebox.backgroundBitmap = gdip.bitmap(path);
        winform.picturebox.text = null;
        winform.picturebox.iconText = null;
    }
}

winform.lnkTranslate.oncommand = function(id,event){
    var text = string.trim(winform.edit.text);
    if(#text){
        import web.edgeTextToSpeech.translate; 
        var transForm = web.edgeTextToSpeech.translate(,text) 
        transForm.text = "OCRAPI 中英翻译 - 此页面支持英文划词速查";
        transForm.doModal();
    } 
    else {
        winform.msgErr("识别结果为空")
    } 
}

winform.onDropFiles = function(files){
    var path = files[1]
    if(path){
        if(string.endsWith(path,".webp",true)){
            import gdip.webp;
        }

        winform.picturebox.backgroundBitmap = gdip.bitmap(path);
        if(winform.picturebox.backgroundBitmap){
            winform.picturebox.background = path; 
        } 
    }
}

import win.clip.bitmap;
winform.btnPaste.oncommand = function(id,event){
    var bmp = win.clip.bitmap.read()
    if(bmp){ 
        winform.picturebox.backgroundBitmap = bmp;
        winform.picturebox.background = bmp;
        winform.picturebox.text = null;
        winform.picturebox.iconText = null;
    }
}

import win.clip.viewer;
winform.clipViewer = win.clip.viewer(winform);
winform.clipViewer.onDrawClipboard = function(){ 
    if(winform.screenclip){ 
        win.showForeground(winform.hwnd);
        winform.screenclip = false
    }
    winform.btnPaste.oncommand();
}
winform.btnPaste.oncommand()

winform.btnScreenClip.oncommand = function(id,event){
    winform.show(6/*_SW_MINIMIZE*/);
    winform.screenclip = true;

    import win.clip.screen;
    win.clip.screen();
}

winform.onActivate = function(state,hwndOther,minimized){
    if(state){
        winform.screenclip = false;     
    }
} 

winform.edit.enablePopMenu()

winform.splitter.split(winform.picturebox,winform.edit);

// 定义一个统一的按钮皮肤样式
var btnSkin = {
    color = {
        default = 0xFF3C3C3C; // 默认深灰色文本
        hover = 0xFF0078D4;   // 鼠标悬停变蓝色
        active = 0xFF005A9E;  // 鼠标按下变深蓝色
        disabled = 0xFFAAAAAA; // 禁用状态灰色
    };
    background = {
        hover = 0x1A0078D4;   // 悬停时淡淡的背景色
        active = 0x330078D4;  // 按下时稍深的背景色
    }
}

// 批量为所有按钮应用样式
for i,ctrl in [
    winform.btnPaste,
    winform.btnOcr,
    winform.btnOpen,
    winform.btnScreenClip
] {
    ctrl.skin(btnSkin);
}

winform.lnkOptimize.skin({
    color = {
        default = 0xFF3498DB;
        hover = 0xFF2980B9;
        active = 0xFF1F618D;
         disabled=0xFFAAAAAA;
    }
})

winform.lnkTranslate.skin({
    color = {
        default = 0xFF3498DB;
        hover = 0xFF2980B9;
        active = 0xFF1F618D;
         disabled=0xFFAAAAAA;
    }
})

if(!_WIN10_LATER){
    return winform.msgboxErr("本程序至少需要 Windows 10 以调用系统自带 OCR 组件");
}

import dotNet.ocr; 
var engine = dotNet.ocr();
winform.comboLanguage.items = engine.availableLanguages()
winform.comboLanguage.selIndex = winform.comboLanguage.find("zh-Hans-CN","zh-Hans","zh") || 1;
engine.close();

winform.lnkOptimize.oncommand = function(id,event){

    if(!winform.ocrResultData){
        return winform.msgboxErr("识别结果为空")
    }

    winform.btnOcr.disabled = true;
    winform.lnkTranslate.disabled = true; 
    winform.lnkOptimize.disabledText = ['\uF254','\uF251','\uF252','\uF253','\uF250']

    thread.invoke( 
        function(winform,text){

            import web.rest.aiChat;
            var aiClient = web.rest.aiChat(
                key =   '\0\1\96';
                url = "https://ai.aardio.com/api/v1/";//接口地址
                model = "prompt";
                temperature = 0.5;//温度
                maxTokens = 1024 //最大回复长度
            )

            //2. 第二步:创建消息队列,必须在这里保存对话,不然 AI 的回复没有上下文。
            //---------------------------------------------------------------------
            var msg = web.rest.aiChat.messages();

            //可调用 msg.system() 函数添加系统提示词。
            msg.system(`# 角色
你是一位 OCR 图文识别结果修复工程师。

# 任务

用户输入的文本是使用 OCR 图文识别工具的识别结果(JSON 数据 , text 为识别结果文本,blocks 为所有识别文本块的位置信息)。
你的任务是在尊重图文原意的基础上对识别结果进行评估与修复,纠正识别错误。
输出格式为纯文本,不使用 Markdown 标记(除非识别结果本身包含 Markdown 标记)。

你应当根据文本相关的文化与背景知识对识别结果的格式进行整理。
如果识别结果中出现与前后文本完全不相关的多余字符应当去除(较大可能可以判定为 OCR 工具将非字符图形误判为文字)。


# 要求  
无需解释你的思考过程,直接输入回复。
`)


            //添加用户提示词
            msg.prompt( '请修复 OCR 识别结果: \n\n```json\n' + winform.ocrResultData + '\n```\n' );

            winform.edit.text = "";

            var resp,err = aiClient.messages(msg,
                function(deltaText,reasoning){
                     if(deltaText) winform.edit.appendText(deltaText); 

                }
            );

            winform.btnOcr.disabled = false;
            winform.lnkTranslate.disabled = false; 
            winform.lnkOptimize.disabledText = null;
        },winform,text
    )
}

winform.show();
win.loopMessage();
Markdown 格式