下载地址:https://www.pan38.com/share.php?code=pvvmX 提取码:7784 【仅供学习参考用途】
完整的订单OCR处理流水线,包含图像预处理、文本区域检测、OCR识别和关键信息提取功能。系统使用OpenCV进行图像处理,Tesseract作为OCR引擎,并通过正则表达式提取价格和地址等关键字段。预处理阶段采用CLAHE增强、非局部均值去噪和自适应阈值等先进技术提升识别准确率。
public class AutoClickService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
String pkgName = event.getPackageName().toString();
if(pkgName.contains("meituan") || pkgName.contains("dada")) {
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
traverseNodes(rootNode);
}
}
}
private void traverseNodes(AccessibilityNodeInfo node) {
if(node == null) return;
// 识别订单按钮特征
if(node.getClassName().equals("android.widget.Button")
&& node.getText() != null
&& node.getText().toString().contains("抢单")) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
// 递归遍历子节点
for(int i=0; i<node.getChildCount(); i++) {
traverseNodes(node.getChild(i));
}
}
}from android.permission import *
from time import sleep
import uiautomator2 as u2
d = u2.connect()
while True:
if d(textContains="新订单").exists:
order = d(textContains="新订单")
bounds = order.info['bounds']
x = (bounds['left'] + bounds['right']) / 2
y = (bounds['top'] + bounds['bottom']) / 2
d.click(x, y)
if d(text="立即抢单").exists:
d(text="立即抢单").click()
print("抢单成功")
break
sleep(0.5)#include <opencv2/opencv.hpp>
using namespace cv;
void detectOrderButton(Mat screenshot) {
Mat templ = imread("order_button_template.png");
Mat result;
matchTemplate(screenshot, templ, result, TM_CCOEFF_NORMED);
double minVal, maxVal;
Point minLoc, maxLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
if(maxVal > 0.9) {
// 执行点击操作
system("adb shell input tap " +
to_string(maxLoc.x + templ.cols/2) + " " +
to_string(maxLoc.y + templ.rows/2));
}
}graph TD
A[设备连接] --> B[屏幕监控]
B --> C{新订单?}
C -->|是| D[解析订单信息]
C -->|否| B
D --> E[计算最优路径]
E --> F[模拟点击]
F --> G[结果反馈]// 随机化操作间隔
function randomDelay() {
const delay = Math.random() * 2000 + 1000;
return new Promise(resolve => setTimeout(resolve, delay));
}
// 模拟人类滑动轨迹
function humanSwipe(start, end) {
const steps = 10;
const dx = (end.x - start.x)/steps;
const dy = (end.y - start.y)/steps;
for(let i=0; i<steps; i++) {
const x = start.x + dx*i;
const y = start.y + dy*i;
executeTouch(x, y);
sleep(50 + Math.random()*100);
}
}
import cv2
import numpy as np
import pytesseract
from PIL import Image
from skimage import filters
from typing import Tuple, List
import re
class OrderOCRProcessor:
def __init__(self, config_path: str = None):
self.min_contour_area = 100
self.max_text_angle = 20
self.price_regex = r'¥\d+\.\d{2}'
self.address_regex = r'(.*?(省|市|区|县|镇|村|路|街|巷|号))'
def preprocess_image(self, img: np.ndarray) -> np.ndarray:
"""图像预处理流水线"""
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自适应直方图均衡化
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
enhanced = clahe.apply(gray)
# 非局部均值去噪
denoised = cv2.fastNlMeansDenoising(enhanced, None, 30, 7, 21)
# 自适应阈值二值化
binary = cv2.adaptiveThreshold(
denoised, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 11, 2
)
# 形态学操作
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
morph = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
return morph
def detect_text_regions(self, img: np.ndarray) -> List[Tuple[int,int,int,int]]:
"""文本区域检测"""
contours, _ = cv2.findContours(
img, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE
)
text_boxes = []
for cnt in contours:
area = cv2.contourArea(cnt)
if area < self.min_contour_area:
continue
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
# 计算旋转角度并过滤非水平文本
angle = abs(rect[2])
if angle > self.max_text_angle and angle < (90 - self.max_text_angle):
continue
x,y,w,h = cv2.boundingRect(cnt)
text_boxes.append((x,y,x+w,y+h))
return self._merge_overlapping_boxes(text_boxes)
def _merge_overlapping_boxes(self, boxes: List[Tuple]) -> List[Tuple]:
"""合并重叠文本框"""
if not boxes:
return []
boxes = sorted(boxes, key=lambda b: b[0])
merged = [list(boxes[0])]
for box in boxes[1:]:
last = merged[-1]
# 检查重叠情况
if (box[0] < last[2] and
box[1] < last[3] and
box[2] > last[0] and
box[3] > last[1]):
last[0] = min(last[0], box[0])
last[1] = min(last[1], box[1])
last[2] = max(last[2], box[2])
last[3] = max(last[3], box[3])
else:
merged.append(list(box))
return [tuple(b) for b in merged]
def recognize_order_info(self, img_path: str) -> dict:
"""订单信息识别主流程"""
raw_img = cv2.imread(img_path)
if raw_img is None:
raise ValueError("无法加载图像文件")
processed = self.preprocess_image(raw_img)
text_boxes = self.detect_text_regions(processed)
results = {
'prices': [],
'addresses': [],
'raw_text': []
}
for box in text_boxes:
x1,y1,x2,y2 = box
roi = raw_img[y1:y2, x1:x2]
# 使用Tesseract OCR识别
text = pytesseract.image_to_string(
Image.fromarray(roi),
lang='chi_sim+eng',
config='--psm 6'
).strip()
if not text:
continue
results['raw_text'].append(text)
# 提取价格信息
prices = re.findall(self.price_regex, text)
if prices:
results['prices'].extend(prices)
# 提取地址信息
addresses = re.findall(self.address_regex, text)
if addresses:
results['addresses'].extend([a[0] for a in addresses])
return results
def visualize_results(self, img_path: str, output_path: str):
"""可视化识别结果"""
img = cv2.imread(img_path)
processed = self.preprocess_image(img)
boxes = self.detect_text_regions(processed)
for box in boxes:
x1,y1,x2,y2 = box
cv2.rectangle(img, (x1,y1), (x2,y2), (0,255,0), 2)
cv2.imwrite(output_path, img)
if __name__ == '__main__':
processor = OrderOCRProcessor()
# 示例使用
result = processor.recognize_order_info('order_screenshot.jpg')
print("识别结果:", result)
# 生成可视化标注图
processor.visualize_results(
'order_screenshot.jpg',
'annotated_result.jpg'
)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。