安卓开发入门:Java语言与实战技巧
2026/10/10 9:15:48
这是一道验证码的题,我在网上找了一种识别方法准确率不高,哪位大佬有其他方法欢迎留言评论
代码给大家做参考
from img import main import time import requests import base64 import json def get_xy(targets, arr): Position = { "0": {"x": 50,"y": 50}, "1": {"x": 150,"y": 50}, "2": {"x": 250,"y": 50}, "3": {"x": 50,"y": 150}, "4": {"x": 150,"y": 150}, "5": {"x": 250,"y": 150}, "6": {"x": 50,"y": 250}, "7": {"x": 150,"y": 250}, "8": {"x": 250,"y": 250}, } res = [] for target in targets: t = 0 for obj in arr: if target == obj.get(str(t)): res.append(Position.get(str(t))) break t += 1 if t == 9: return None return res class Session: def __init__(self): self.id = None self.session = requests.session() self.session.headers = { "accept": "application/json, text/javascript, */*; q=0.01", "accept-encoding": "gzip, deflate, br, zstd", "accept-language": "zh-CN,zh;q=0.9", "cache-control": "no-cache", "cookie": "Hm_lvt_434c501fe98c1a8ec74b813751d4e3e3=1779001012; Hm_lvt_f80b2b389f44bbfb3bfe1704817d44e0=1780731259,1783231638; sessionid=2op20261dehuwjd7asnghz331b4nwexr", "pragma": "no-cache", "priority": "u=1, i", "referer": "https://match.yuanrenxue.cn/match/8", "sec-ch-ua": "Not/A)Brand;v=99, Chromium;v=148", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "Windows", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36", "x-requested-with": "XMLHttpRequest" } self.sum = 0 def get_image(self): url = "https://match.yuanrenxue.cn/api2/8" params = { "t": int(time.time() * 1000) } res = self.session.get(url, params=params) targets = res.json().get("targets") image = res.json().get("image") self.id = res.json().get("id") open("img.webp", "wb").write(base64.b64decode(image.split(',')[1], validate=True)) return targets def check(self, click): url = "https://match.yuanrenxue.cn/api2/8" data = { "captcha_id": self.id, "clicks": json.dumps(click, separators=(',', ':')), } res = self.session.post(url, data=data) return res.status_code def func(self): count = 0 while True: count += 1 targets = session.get_image() arr = main() suc = get_xy(targets, arr) if suc: break print(f"经过{count}次成功 ", suc) session.check(suc) def get_data(self): for i in range(1, 6): session.func() url = "https://match.yuanrenxue.cn/api/question/8" params = { "page": i, "pageSize": "10" } if i == 5: self.session.headers["user-agent"] = 'yuanrenxue' res = self.session.get(url, params=params) # print(res.json()) ttt = res.json().get("data") print(f"第{i}页已完成", ttt) for item in ttt: self.sum += item # break if __name__ == '__main__': session = Session() session.get_data() print(session.sum)import os import cv2, numpy as np import pytesseract from PIL import Image # IMAGE_PATH = "da.jpg" # pytesseract.pytesseract.tesseract_cmd = r"D:\Program Files\Tesseract-OCR\tesseract.exe" def split_grid(path, save_dir, rows, cols): img = Image.open(path) w, h = img.size os.makedirs(save_dir, exist_ok=True) block_w = w // cols block_h = h // rows index = 0 for i in range(rows): for j in range(cols): left = j * block_w top = i * block_h right = left + block_w bottom = top + block_h crop = img.crop( (left, top, right, bottom) ) crop.save( f"{save_dir}/{index}.png" ) index += 1 def remove_lines(binary): """连通域形状分析去除细长干扰线""" inv = cv2.bitwise_not(binary) n, labels, stats, _ = cv2.connectedComponentsWithStats(inv, connectivity=8) h, w = binary.shape mask = np.full(h * w, 255, dtype=np.uint8).reshape(h, w) for i in range(1, n): area = stats[i, cv2.CC_STAT_AREA] cw = stats[i, cv2.CC_STAT_WIDTH] ch = stats[i, cv2.CC_STAT_HEIGHT] if cw <= 0 or ch <= 0: continue ratio = max(cw, ch) / min(cw, ch) fill = area / (cw * ch) if ratio > 12 or (ratio > 6 and fill < 0.25) or area < 8 or (fill < 0.12 and area < h * w * 0.02): mask[labels == i] = 0 return cv2.bitwise_not(cv2.bitwise_and(inv, inv, mask=mask)) def recognize(path): """预处理 → 去线 → Tesseract多模式投票 → 输出结果""" # 读取 img = cv2.imread(path) if img is None: print(f"❌ 找不到图片: {path}") return gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 小图放大 h, w = gray.shape if h < 64: s = 64 / h gray = cv2.resize(gray, (max(int(w * s), 24), 64), interpolation=cv2.INTER_CUBIC) # 去噪 + 增强 gray = cv2.bilateralFilter(gray, 5, 16, 16) gray = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)).apply(gray) # 二值化(OTSU + 自适应兜底) t, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) if t < 60: bs = max(9, min(h, w) // 6) | 1 binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, bs, 4) # 去干扰线 binary = remove_lines(binary) # 笔画修复 k = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2, 2)) binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, k) binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, k) # 裁剪文字区域 pts = cv2.findNonZero(cv2.bitwise_not(binary)) if pts is not None: x, y, rw, rh = cv2.boundingRect(pts) x = max(x - 6, 0) y = max(y - 6, 0) x2 = min(x + rw + 12, binary.shape[1]) y2 = min(y + rh + 12, binary.shape[0]) binary = binary[y:y2, x:x2] # 等比缩放到标准高度 ch, cw = binary.shape if ch > 0 and cw > 0: scale = min(64 / ch, 4.0) binary = cv2.resize(binary, (max(int(cw * scale), 16), int(ch * scale)), interpolation=cv2.INTER_CUBIC) binary = cv2.copyMakeBorder(binary, 12, 12, 12, 12, cv2.BORDER_CONSTANT, value=255) # 多 PSM 识别 + 投票 candidates = [] for psm in ["10", "8", "7", "6"]: try: data = pytesseract.image_to_data(binary, lang="chi_sim", config=f"--psm {psm}", output_type=pytesseract.Output.DICT) for i, txt in enumerate(data["text"]): txt = txt.strip() if txt and len(txt) <= 4: conf = float(data["conf"][i]) / 100.0 if data["conf"][i] != "-1" else 0.0 if conf > 0.05: candidates.append({"text": txt, "confidence": conf}) except Exception: pass if not candidates: print("⚠️ 未识别到文字") return # 多PSM一致加权 from collections import Counter mc, n = Counter(c["text"] for c in candidates).most_common(1)[0] if n >= 2: for c in candidates: if c["text"] == mc: c["confidence"] = min(c["confidence"] + 0.20, 1.0) # 排序取最佳 candidates.sort(key=lambda x: x["confidence"], reverse=True) best = candidates[0] return best["text"] def main(img): arr = [] split_grid(img,"tu",3,3) for file in os.listdir("tu"): txt = recognize(f"./tu/{file}") arr.append({str(file.split(".")[0]): txt}) return arr if __name__ == "__main__": img = "img.webp" arr = main(img) print(arr)