aardio 文档
aardio 范例: DeepSeek OCR - AI 图像识别,HF 接口
//DeepSeek OCR - AI 图像识别,HF 接口
import win.ui;
import win.ui.simpleWindow;
import fonts.fontAwesome;
import gdip.webp;//导入则 plus 控件可显示 WebP 图像
import inet.http; // 使 plus 控件支持远程图像 URL
/*DSG{{*/
var winform = win.form(text="DeepSeek OCR - AI 图像识别";right=1169;bottom=573;bgcolor=0xF5F5F5;border="none")
winform.add(
bkplus={cls="bkplus";left=0;top=516;right=1170;bottom=575;bgcolor=0xE8E8E8;db=1;dl=1;dr=1;z=1};
bkplus2={cls="bkplus";text="DeepSeek OCR 2";left=23;top=4;right=238;bottom=35;align="left";color=0xEEEEEE;z=19};
btnCopy={cls="plus";text="复制结果";left=1030;top=532;right=1140;bottom=562;align="left";color=0x3C3C3C;db=1;disabled=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF0C5';notify=1;textPadding={left=25};z=5};
btnOcr={cls="plus";text="识别文本";left=900;top=532;right=1010;bottom=562;align="left";bgcolor=0x3498DB;border={radius=4};color=0xFFFFFF;db=1;dr=1;font=LOGFONT(h=-13;weight=600);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=10}};iconText='\uF0F6';notify=1;textPadding={left=28};z=7};
btnOpen={cls="plus";text="打开图像文件";left=180;top=532;right=300;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=100;top=532;right=170;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=6};
btnScreenClip={cls="plus";text="截屏";left=20;top=532;right=90;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=11};
comboTask={cls="combobox";left=365;top=537;right=560;bottom=563;db=1;dl=1;edge=1;items={'\uD83D\uDCCB Markdown','\uD83D\uDCDD Free OCR','\uD83D\uDCCD Locate','\uD83D\uDD0D Describe','\u270F\uFE0F Custom'};mode="dropdownlist";z=13};
edit={cls="edit";left=589;top=40;right=1168;bottom=515;autohscroll=false;aw=1;db=1;dr=1;dt=1;edge=1;multiline=1;vscroll=1;z=3};
editPrompt={cls="edit";left=580;top=537;right=880;bottom=563;db=1;dr=1;edge=1;hide=1;z=15};
lbTask={cls="static";text="任务:";left=310;top=532;right=360;bottom=562;align="right";center=1;db=1;dl=1;transparent=1;z=12};
picturebox={cls="plus";text="请复制图像到剪贴板 / 或拖放文件到此处";left=0;top=40;right=584;bottom=515;bgcolor=0xFFFFFF;border={color=0xFFE0E0E0;width=1};color=0x999999;db=1;dl=1;dt=1;font=LOGFONT(h=-16);iconStyle={font=LOGFONT(h=-60;name='FontAwesome')};iconText='\uF03E';notify=1;repeat="scale";textPadding={top=100};z=2};
resultPicture={cls="plus";left=589;top=40;right=1168;bottom=515;aw=1;bgcolor=0xFFFFFF;border={color=0xFFE0E0E0;width=1};db=1;dr=1;dt=1;hide=1;repeat="scale";z=16};
splitter={cls="splitter";left=583;top=40;right=588;bottom=515;bgcolor=0xFFFFFF;db=1;dt=1;frame=1;z=8};
tabLayout={cls="plus";text="布局检测";left=689;top=7;right=789;bottom=37;align="left";color=0xEEEEEE;dr=1;dt=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=11;top=1}};iconText='\uF03E';notify=1;textPadding={left=28;bottom=1};z=18};
tabResult={cls="plus";text="识别结果";left=589;top=7;right=689;bottom=37;align="left";color=0x3498DB;dr=1;dt=1;font=LOGFONT(h=-13;weight=600);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=11;top=1}};iconText='\uF0F6';notify=1;textPadding={left=28;bottom=1};z=17};
titleBar={cls="bkplus";left=0;top=0;right=1170;bottom=40;bgcolor=0x2C3E50;dl=1;dr=1;dt=1;z=14};
titleIcon={cls="bkplus";text='\uF1C5';left=15;top=8;right=45;bottom=34;color=0x3498DB;dl=1;dt=1;font=LOGFONT(h=-18;name='FontAwesome');z=9};
titleText={cls="bkplus";text="DeepSeek OCR - AI 图像识别";left=50;top=10;right=300;bottom=32;color=0xFFFFFF;dl=1;dt=1;font=LOGFONT(h=-15;weight=700);z=10}
)
/*}}*/
// 初始化下拉框选中项
winform.comboTask.selIndex = 1; // 📋 Markdown
// 任务类型切换时显示/隐藏提示词输入框
winform.comboTask.onSelChange = function(){
var taskType = owner.selText;
// Locate 和 Custom 任务需要输入提示词
winform.editPrompt.show(taskType == "📍 Locate" || taskType == "✏️ Custom");
}
import win.ui.tabs;
var tabs = win.ui.tabs(winform.tabResult,winform.tabLayout);
tabs.panel = null;
// 结果标签页切换
tabs.onSelChange = function(tabIndex,tabButton,formPage){
showText = tabIndex == 1;
winform.edit.show(showText);
winform.resultPicture.show(!showText);
}
winform.editPrompt.setCueBannerText("请输入识别提示词",true);
winform.showResultPicture = function(){
tabs.selIndex = 2;
}
// OCR 识别核心函数(线程内执行)
var doOcr = function(winform, dataUrl, taskType, customPrompt){
import web.rest.gradioClient;
// 创建 Gradio 客户端,使用新的 Space ID
var gradio = web.rest.gradioClient("merterbak/DeepSeek-OCR-Demo", {
// proxy = "socks=127.0.0.1:1081" // 可选指定代理
});
winform.edit.text = "正在上传图像...";
// 图像数据格式
var imageData = {
url = dataUrl;
orig_name = "image.png";
meta = { _type = "gradio.FileData" };
};
winform.edit.text = "正在识别中,请稍候(需排队)...";
// 调用新的 /run API 端点
var result, err = gradio.xcall.run({
data = [
imageData, // image: 图像数据
null, // file_path: 文件路径(用于 PDF,这里不使用)
taskType, // task: 任务类型
customPrompt || "", // custom_prompt: 提示词
1 // page_num: 页码
]
});
if(result){
// 返回值结构:[value_14, value_17, value_23, value_19, value_21]
// value_14: Textbox(原始文本)
// value_17: Markdown(格式化结果)
// value_23: Textbox(另一个文本)
// value_19: Image(结果图像)
// value_21: Gallery(图片库)
var ocrText = result[1] || result[2] || result[3];
var layoutImage = result[4];
var gallery = result[5];
if(ocrText){
// 去掉 Reference 与 Detection 标签(DeepSeek OCR,Qwen-VL 的 OCR 定位标签 Special Tokenized Format )
ocrText = string.replace(ocrText, "\<\|<\a+>\|\>.+?\<\|/\1\|\>", "");
winform.edit.text = string.crlf(ocrText,'\r\n');
winform.btnCopy.disabled = false;
winform.showResultPicture();
}
else {
winform.edit.text = "识别结果为空";
}
// 处理布局检测图像
if(layoutImage){
var webpUrl = layoutImage.url;
if(webpUrl){
winform.resultPicture.background = webpUrl;//WebP 图像
winform.tabLayout.iconText = '\uF00C'; // 有结果时显示勾选图标
}
}
elseif(gallery && #gallery > 0){
// 尝试从 Gallery 获取第一张图
var firstItem = gallery[1];
if(firstItem){
var img = firstItem.image;
if(img){
var webpUrl = img.url;
if(webpUrl){
winform.resultPicture.background = webpUrl;
winform.tabLayout.iconText = '\uF00C';
}
}
}
}
else {
winform.resultPicture.background = null;
winform.resultPicture.text = "此任务无布局检测结果";
winform.resultPicture.iconText = '\uF05E';
winform.tabLayout.iconText = '\uF03E';
}
}
else {
winform.edit.text = "识别失败:" + (err || "未知错误");
}
winform.btnOcr.disabledText = null;
}
// 识别按钮点击事件
winform.btnOcr.oncommand = function(){
if(!winform.picturebox.backgroundBitmap){
return winform.msgbox("请先打开或拖放图像文件", "提示", "warn");
}
var taskType = winform.comboTask.selText;
var customPrompt = winform.editPrompt.text;
// 如果选择了 Locate 或 Custom 任务但没有输入提示词
if((taskType == "📍 Locate" || taskType == "✏️ Custom") && !#string.trim(customPrompt)){
return winform.msgbox("请输入提示词", "提示", "warn");
}
// 禁用按钮,显示加载动画
winform.btnOcr.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'};
winform.btnCopy.disabled = true;
winform.edit.text = "正在连接服务器...";
// 重置布局检测结果
winform.resultPicture.background = null;
winform.resultPicture.text = null;
winform.resultPicture.iconText = null;
tabs.selIndex = 1;
// 将位图转换为 data URL 并在新线程中执行 OCR
import inet.urlData;
var dataUrl = inet.urlData.fromBitmap(winform.picturebox.backgroundBitmap);
thread.invoke(doOcr, winform, dataUrl, taskType, customPrompt);
}
// 加载图像的通用函数
var loadImage = function(path){
if(string.endsWith(path, ".webp", true)){
import gdip.webp;
}
var bmp = gdip.bitmap(path);
if(bmp){
winform.picturebox.background = path;
winform.picturebox.backgroundBitmap = bmp; // 保存位图对象
winform.picturebox.text = null;
winform.picturebox.iconText = null;
winform.text = "DeepSeek OCR - " + io.splitpath(path).file;
}
else {
winform.msgboxErr("无法加载图像文件", "错误");
}
}
// 打开文件按钮
import fsys.dlg;
winform.btnOpen.oncommand = function(){
var path = fsys.dlg.open(
"图像文件|*.jpg;*.jpeg;*.jfif;*.bmp;*.gif;*.png;*.tif;*.tiff;*.webp||",
, , winform
);
if(path){
loadImage(path);
}
}
// 拖放文件支持
winform.onDropFiles = function(files){
var path = files[1];
if(path){
loadImage(path);
}
}
// 粘贴按钮
import win.clip.bitmap;
winform.btnPaste.oncommand = function(){
var bmp = win.clip.bitmap.read();
if(bmp){
winform.picturebox.background = bmp;
winform.picturebox.backgroundBitmap = bmp; // 直接保存位图对象
winform.picturebox.text = null;
winform.picturebox.iconText = null;
winform.text = "DeepSeek OCR - 剪贴板图像";
}
}
// 剪贴板监视器 - 自动导入图像
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(){
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.btnCopy.oncommand = function(){
var text = string.trim(winform.edit.text);
if(#text){
import win.clip;
win.clip.write(text);
// 显示复制成功提示
winform.btnCopy.text = "已复制 ✓";
winform.setTimeout(function(){
winform.btnCopy.text = "复制结果";
}, 1500);
}
}
winform.edit.text = /*
任务 (Task) 选项:
---------------------------------------------
- 📋 Markdown: 识别排版 | 自动识别表格、标题,输出格式化文档(推荐)。
- 📝 Free OCR: 纯文本 | 提取所有文字,不保留排版格式。
- 📍 Locate: 视觉定位 | 输入物体名称(如"红色按钮"),返回坐标并画框。
- 🔍 Describe: 看图说话 | 分析统计图/流程图含义,而非单纯识字。
- ✏️ Custom: 自定义 | 输入自定义提示词,灵活控制识别行为。
使用说明:
---------------------------------------------
1. 通过截屏、粘贴或打开文件加载图像
2. 选择合适的任务类型
3. Locate 和 Custom 任务需要在右侧输入提示词
4. 点击「识别文本」开始识别
*/
// 右键菜单
winform.edit.enablePopMenu();
// 分割条
winform.splitter.split(winform.picturebox, [winform.edit,winform.resultPicture]);
// 设置选项卡交互样式
tabs.skin({
color = {
default = 0xFFEEEEEE;
hover = 0xFF3498DB;
};
checked = {
color = { default = 0xFFDB9834; hover = 0xFF3498DB; };
}
})
//winform.tabLayout.iconText = '\uF00C'; // 有结果时显示勾选图标
// 按钮统一样式
var btnSkin = {
color = {
default = 0xFF3C3C3C;
hover = 0xFF0078D4;
active = 0xFF005A9E;
disabled = 0xFFAAAAAA;
};
background = {
hover = 0x1A0078D4;
active = 0x330078D4;
}
}
for i, ctrl in [
winform.btnPaste,
winform.btnOpen,
winform.btnScreenClip,
winform.btnCopy
] {
ctrl.skin(btnSkin);
}
// 识别按钮特殊样式
winform.btnOcr.skin({
background = {
default = 0xFF3498DB;
hover = 0xFF2980B9;
active = 0xFF1F618D;
disabled = 0xFFBDC3C7;
};
color = {
default = 0xFFFFFFFF;
disabled = 0xFF7F8C8D;
}
});
// 复制按钮样式
winform.btnCopy.skin({
color = {
default = 0xFF27AE60;
hover = 0xFF229954;
active = 0xFF1E8449;
disabled = 0xFFAAAAAA;
};
background = {
hover = 0x1A27AE60;
active = 0x3327AE60;
}
});
// 无边框窗口样式
win.ui.simpleWindow(winform);
winform.show();
win.loopMessage();
Markdown 格式