尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python桌面截图文字识别:自适应分辨率与OCR实战
1. 桌面截图与文字识别的整体设计思路1.1 这个项目到底在解决什么问题很多人第一次接触桌面截图加文字识别这个需求脑子里冒出来的方案往往是“截个图然后手动打开某个识别工具把图拖进去”。偶尔用一次还行但如果每天要重复几十次比如从各种报表、聊天窗口、监控面板里提取文字手动操作的时间成本就非常可观了。这个项目的核心目标就是把“截取桌面画面”和“识别图中文字”这两步串成一条自动化的流水线让程序自己完成从抓屏到出文本的全过程。标题里有个关键词叫“自适应分辨率”这是整个项目里最容易被忽略、却最影响成败的一环。所谓自适应指的是程序不能假设用户的屏幕永远是 1920×1080也不能假设缩放比例永远是 100%。现实中有人用 2K 屏、有人用 4K 屏、有人笔记本外接显示器Windows 的显示缩放还可能是 125%、150% 甚至 175%。如果截图代码写死了坐标和尺寸换一台机器就全乱套。所以这个项目要做的是让程序在运行时主动去问系统“你的屏幕到底多大、缩放是多少”然后据此动态计算截图区域和后续识别所需的参数。它适合谁来参考我觉得有三类人比较对口。第一类是做自动化办公的开发者需要从桌面软件界面里批量提取文字数据第二类是做测试或运维的朋友想定时抓取某个监控窗口的内容做记录第三类就是单纯想练手的 Python 学习者这个项目麻雀虽小但把屏幕 API、图像处理、OCR 识别、坐标换算几个知识点都串起来了是个不错的综合练习。1.2 为什么选 Python 而不是别的语言做这类桌面自动化可选的语言其实不少C# 调 Windows API 很直接AutoHotkey 写起来也快但 Python 的优势在于生态。截图有mss、Pillow的ImageGrab图像预处理有OpenCV文字识别有pytesseract、PaddleOCR、EasyOCR一大堆现成库而且这些库的文档和社区案例都足够多遇到坑基本能搜到答案。更重要的是Python 写出来的脚本改起来快。今天想加个“只截取屏幕右下角区域”明天想加个“识别完自动存到表格”用 Python 都是几行代码的事。如果换成编译型语言光是改一个参数重新编译就够烦的。所以对于这种“需求会不断微调”的小工具Python 是性价比最高的选择。不过这里要提前说一个选型上的分水岭截图库和 OCR 库的搭配方式会直接决定你的程序在不同分辨率下稳不稳。我后面会详细拆开讲。1.3 整体流程的四个阶段把整个项目拆开其实就四个阶段我用一个生活化的类比来说明这就像你去复印店复印一本书的某一页。第一步你得先看清楚这本书摊开有多大获取屏幕尺寸和缩放第二步把要复印的那一页框出来确定截图区域第三步按下复印键得到一张纸执行截图并保存为图像第四步把纸上的字录入电脑OCR 识别。对应到代码里就是阶段一探测屏幕物理分辨率与系统缩放比例阶段二根据目标区域计算实际像素坐标阶段三调用截图库抓取指定区域并做预处理阶段四把处理后的图像交给 OCR 引擎拿到文字结果这四个阶段里第一阶段和第二阶段是“自适应”的关键也是最容易出 bug 的地方。第三阶段的预处理决定了识别准确率的上限第四阶段则是选型和调参的功夫。下面我逐个展开。2. 自适应分辨率的核心细节与实操要点2.1 物理分辨率、逻辑分辨率与缩放比例的关系很多人搞不清一个概念为什么我的屏幕明明是 2560×1440但程序读出来的却是 1707×960这就是缩放比例在作怪。操作系统为了让你在高分屏上看得清字会把界面元素放大比如设置 150% 缩放那么逻辑分辨率就是物理分辨率除以 1.5。用公式表达就是逻辑分辨率 物理分辨率 / 缩放比例拿 2560×1440、150% 缩放举例2560 / 1.5 ≈ 17071440 / 1.5 960。所以程序如果按逻辑分辨率去截图得到的图会比实际屏幕小一圈截出来的内容自然就错位了。这里有个关键点不同的截图库读到的分辨率口径不一样。Pillow的ImageGrab.grab()在 Windows 上默认抓的是逻辑分辨率下的画面而mss抓的是物理像素。这个差异如果不搞清楚你会遇到“截图区域明明算对了但截出来是模糊的或者缺一块”的诡异现象。我在实际项目里踩过的坑是一开始用ImageGrab配合写死的坐标在自己电脑上跑得好好的换到同事的 4K 笔记本上截出来的图只有左上角四分之一。后来才明白同事的缩放是 200%逻辑分辨率只有物理的一半坐标全对不上。2.2 用代码探测屏幕真实参数要拿到屏幕的物理分辨率和缩放比例Windows 下最靠谱的方式是调用系统 API。Python 里可以通过ctypes直接调user32和shcore里的函数。下面这段是我常用的探测代码import ctypes def get_screen_info(): user32 ctypes.windll.user32 # 设置进程为 DPI 感知避免系统自动缩放 try: ctypes.windll.shcore.SetProcessDpiAwareness(2) except Exception: user32.SetProcessDPIAware() # 物理分辨率 physical_width user32.GetSystemMetrics(0) physical_height user32.GetSystemMetrics(1) # 获取缩放比例 try: hdc user32.GetDC(0) dpi ctypes.windll.gdi32.GetDeviceCaps(hdc, 88) # LOGPIXELSX user32.ReleaseDC(0, hdc) scale dpi / 96.0 except Exception: scale 1.0 return physical_width, physical_height, scale这段代码里有两个细节值得说。第一SetProcessDpiAwareness(2)这行非常关键它告诉系统“我这个程序自己会处理缩放你别帮我缩放”。如果不加这行系统会把你的程序窗口和截图结果都按缩放比例处理一遍导致坐标计算全乱。参数 2 代表PROCESS_PER_MONITOR_DPI_AWARE意思是每个显示器独立处理 DPI多屏环境下更准确。第二GetDeviceCaps的第二个参数 88 是LOGPIXELSX的常量值返回的是每英寸逻辑像素数标准值是 96。用返回值除以 96 就得到缩放比例比如返回 144 就是 150% 缩放返回 192 就是 200%。注意SetProcessDpiAwareness必须在程序启动早期调用最好在导入其他图形库之前。如果先导入了Pillow或tkinter有些库会自己设置 DPI 感知导致你的设置失效。2.3 多显示器场景下的坐标陷阱单屏还好说一旦涉及多显示器坐标系统就变得复杂了。Windows 里每个显示器都有自己的坐标系主显示器的左上角是 (0,0)副显示器可能在主显示器的左边那它的坐标就是负的。mss这个库对多屏支持比较好它提供了一个monitors列表索引 0 是所有显示器拼起来的虚拟大屏索引 1 开始是各个独立显示器。你可以这样枚举import mss with mss.mss() as sct: for i, monitor in enumerate(sct.monitors): print(f显示器 {i}: 位置{monitor[left]},{monitor[top]} 尺寸{monitor[width]}x{monitor[height]})输出里索引 0 的那一项宽高就是所有屏幕拼起来的总尺寸。如果你要截取的内容可能出现在任意屏幕上用索引 0 的虚拟大屏坐标来定位是最省事的。但要注意虚拟大屏的坐标原点不一定在左上角如果副屏在主屏左边原点可能是负坐标。我个人的经验是如果项目只针对单屏直接用主显示器参数就行如果确实要多屏建议在配置里让用户指定“目标在第几号显示器”然后程序用该显示器的 left/top 做偏移量这样比用虚拟大屏更可控。2.4 缩放比例对截图坐标的换算假设你已经拿到了缩放比例 scale现在用户告诉你“我要截取屏幕上从 (100, 200) 开始、宽 800 高 600 的区域”这个坐标是用户按逻辑坐标给的因为用户看到的是缩放后的界面。那么实际截图时需要把逻辑坐标乘以 scale 换算成物理像素def logical_to_physical(x, y, w, h, scale): return int(x * scale), int(y * scale), int(w * scale), int(h * scale)反过来如果 OCR 识别出来的文字带有坐标信息比如某些 OCR 库会返回文字框位置你想把它映射回逻辑坐标做界面标注就要除以 scale。这个换算看起来简单但实际项目里最容易出错的地方是“混用”。比如截图用物理坐标但鼠标点击用逻辑坐标结果就是点偏了。我的建议是在程序里统一用一套坐标体系要么全物理、要么全逻辑在边界处做一次转换中间不要来回换。3. 截图与文字识别的完整实操流程3.1 环境准备与依赖安装先把环境搭起来。我用的组合是mss负责截图、Pillow负责图像处理、pytesseract负责 OCR。为什么选mss而不是Pillow的ImageGrab因为mss抓的是物理像素速度快而且对多屏和 DPI 的处理更透明配合前面说的 DPI 感知设置坐标计算最不容易出错。安装命令如下pip install mss pillow pytesseract opencv-python numpy这里要特别提醒pytesseract只是一个 Python 封装它本身不含 OCR 引擎你还需要单独安装 Tesseract 引擎。Windows 下可以去它的官方发布页下载安装包安装时记得勾选中文语言包如果你要识别中文。安装完后要么把安装目录加到系统 PATH要么在代码里用pytesseract.pytesseract.tesseract_cmd指定路径import pytesseract pytesseract.pytesseract.tesseract_cmd rC:\Program Files\Tesseract-OCR\tesseract.exe如果你要识别中文还需要确认语言包文件chi_sim.traineddata存在于 Tesseract 的tessdata目录下。没有的话识别中文会直接报错或者返回空。3.2 截图区域的动态计算现在把前面的知识串起来写一个能自适应的截图函数。核心思路是先探测屏幕参数再根据用户给的逻辑坐标换算成物理坐标最后用mss抓取。import mss import numpy as np from PIL import Image def capture_region(logical_x, logical_y, logical_w, logical_h): physical_w, physical_h, scale get_screen_info() # 逻辑坐标转物理坐标 px int(logical_x * scale) py int(logical_y * scale) pw int(logical_w * scale) ph int(logical_h * scale) # 边界保护防止超出屏幕 px max(0, min(px, physical_w - 1)) py max(0, min(py, physical_h - 1)) pw min(pw, physical_w - px) ph min(ph, physical_h - py) monitor {left: px, top: py, width: pw, height: ph} with mss.mss() as sct: img np.array(sct.grab(monitor)) # mss 返回的是 BGRA转成 RGB img_rgb img[:, :, :3][:, :, ::-1] return Image.fromarray(img_rgb)这段代码里有几个我特意加的细节。第一是边界保护用户给的坐标可能超出屏幕范围如果不做 clampmss会抛异常或者截出黑边。第二是颜色通道转换mss抓出来的 numpy 数组是 BGRA 四通道直接交给 OCR 会因为颜色通道顺序不对导致识别率下降所以要转成 RGB。提示如果你要截取的是整个屏幕直接把 monitor 设成sct.monitors[1]就行不用自己算坐标。但如果是局部区域一定要走上面的换算流程。3.3 图像预处理提升识别率截图拿到手别急着丢给 OCR。原始截图的识别率往往不理想尤其是深色背景上的浅色文字、或者有抗锯齿的字体。做几步预处理识别率能提升一大截。我常用的预处理流程是这样的import cv2 def preprocess_for_ocr(pil_img): img np.array(pil_img) # 转灰度 gray cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) # 放大图像小字体识别率低放大 2 倍 gray cv2.resize(gray, None, fx2, fy2, interpolationcv2.INTER_CUBIC) # 自适应二值化应对不均匀光照 binary cv2.adaptiveThreshold( gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 10 ) return Image.fromarray(binary)这里每一步都有讲究。转灰度是因为 OCR 引擎主要看形状和对比度彩色信息反而是干扰。放大 2 倍是因为 Tesseract 对小于 20 像素高的文字识别率会明显下降放大后相当于给它更多细节。自适应二值化比全局阈值好因为截图里可能有渐变背景或者局部阴影全局阈值会把某些区域整片变黑或变白。不过二值化不是万能的。如果原图文字本身就是深色背景浅色字二值化后可能变成白字黑底Tesseract 对反色文字的识别率会下降。这时候可以加一步判断如果二值化后白色像素占比超过 70%说明可能是反色再取一次反。if np.mean(binary) 178: # 白色偏多 binary cv2.bitwise_not(binary)这个 178 是我实测下来比较稳的阈值你也可以用binary.mean()动态判断。3.4 调用 OCR 并解析结果预处理完就可以识别了。pytesseract的基本调用很简单def ocr_image(pil_img, langchi_simeng): config --oem 3 --psm 6 text pytesseract.image_to_string(pil_img, langlang, configconfig) return text.strip()这里的config参数值得展开说。--oem 3表示用默认的 OCR 引擎模式兼容性最好。--psm 6表示“假设是一整块统一的文本”这个模式对截图这种规整排版的文字最友好。如果你的截图是零散的文字比如按钮上的字可以试--psm 11稀疏文本模式。如果是一行字用--psm 7。语言参数chi_simeng表示同时加载简体中文和英文中间用加号连接。如果你只识别英文用eng就行速度会快不少因为不用加载中文模型。识别结果是一个字符串行与行之间用换行分隔。如果你需要每个词的位置信息可以用image_to_datadata pytesseract.image_to_data(pil_img, langlang, output_typepytesseract.Output.DICT) for i, word in enumerate(data[text]): if word.strip(): print(f文字: {word} 位置: ({data[left][i]}, {data[top][i]}) 置信度: {data[conf][i]})这个在需要定位文字位置时很有用比如你想知道某个关键词出现在截图的哪个位置就可以遍历这个结果去匹配。3.5 把整个流程封装成可复用的类零散的函数不利于维护我习惯把它封装成一个类把屏幕参数在初始化时探测一次后续截图直接复用避免每次都调系统 API。class AdaptiveScreenOCR: def __init__(self, tesseract_pathNone, langchi_simeng): if tesseract_path: pytesseract.pytesseract.tesseract_cmd tesseract_path self.lang lang self.physical_w, self.physical_h, self.scale get_screen_info() def capture(self, x, y, w, h): px, py, pw, ph self._to_physical(x, y, w, h) monitor {left: px, top: py, width: pw, height: ph} with mss.mss() as sct: img np.array(sct.grab(monitor)) return Image.fromarray(img[:, :, :3][:, :, ::-1]) def _to_physical(self, x, y, w, h): px max(0, min(int(x * self.scale), self.physical_w - 1)) py max(0, min(int(y * self.scale), self.physical_h - 1)) pw min(int(w * self.scale), self.physical_w - px) ph min(int(h * self.scale), self.physical_h - py) return px, py, pw, ph def recognize(self, x, y, w, h, preprocessTrue): img self.capture(x, y, w, h) if preprocess: img preprocess_for_ocr(img) return ocr_image(img, self.lang)用起来就很清爽ocr AdaptiveScreenOCR(langchi_simeng) result ocr.recognize(100, 200, 800, 600) print(result)这个类的好处是屏幕参数只探测一次而且坐标换算逻辑集中在一处改起来方便。如果以后要支持多屏只需要在_to_physical里加上显示器偏移量就行。4. 常见问题与排查技巧实录4.1 识别结果乱码或为空这是最常见的问题原因通常有三类。第一类是语言包没装对比如你要识别中文但只装了英文包Tesseract 会把中文当成乱码。排查方法是命令行执行tesseract --list-langs看看输出里有没有chi_sim。没有的话就是语言包缺失。第二类是图像质量太差。截图区域太小、文字太模糊、对比度太低都会导致识别失败。这时候先别急着调 OCR 参数把预处理后的图像保存下来看一眼img.save(debug_preprocessed.png)我遇到过好几次是二值化参数不合适把文字给“化”没了。看到图就一目了然。第三类是--psm模式选错了。整块文本用了稀疏模式或者单行文字用了整块模式都会影响结果。这个只能多试几个模式对比。4.2 截图区域偏移或截到黑边偏移问题九成是缩放比例没处理对。排查步骤是先打印出get_screen_info()返回的 scale确认它和你系统设置里的缩放比例一致。如果系统是 150% 但代码返回 1.0说明 DPI 感知没设置成功检查SetProcessDpiAwareness是不是被其他库覆盖了。截到黑边通常是坐标超出屏幕范围。前面代码里的边界保护能解决大部分情况但如果你的目标区域本身就在屏幕边缘可能需要调整截图区域或者接受边缘有少量黑边后用裁剪去掉。还有一种情况是副屏坐标为负。如果你在多屏环境下用虚拟大屏坐标而副屏在主屏左边那么副屏的 left 是负数。mss能处理负坐标但你自己算边界保护时要注意别把负数 clamp 成 0否则会截错区域。4.3 识别速度慢Tesseract 识别一张 800×600 的图英文大概 0.3 到 0.5 秒中英混合可能 1 秒以上。如果你要频繁截图识别这个速度可能不够。优化方向有几个缩小截图区域只截真正需要的部分图像越小识别越快如果只识别英文把 lang 改成eng速度能快一倍降低预处理里的放大倍数从 2 倍改成 1.5 倍如果对准确率要求不高可以用--psm 7单行模式比整块模式快如果速度还是不够就得考虑换 OCR 引擎了。PaddleOCR 在中文场景下速度和准确率都比 Tesseract 好但依赖更重安装包大。EasyOCR 也不错支持 GPU 加速。这个就看项目需求权衡了。4.4 常见问题速查表问题现象可能原因排查方法解决方案识别结果为空语言包缺失tesseract --list-langs安装对应语言包识别结果乱码语言参数错误检查 lang 参数改成正确的语言代码截图区域偏移缩放比例未处理打印 scale 值设置 DPI 感知并换算坐标截图有黑边坐标超范围打印实际截图坐标加边界保护识别速度慢图像过大或语言过多计时各阶段耗时缩小区域、精简语言中文识别率低未放大或未二值化保存预处理图查看放大 2 倍并自适应二值化反色文字识别差二值化后反色检查白色像素占比超过阈值时取反4.5 几个我踩过的坑和独家技巧第一个坑是mss的实例不能跨线程复用。我一开始想用多线程加速批量截图结果发现多个线程共用一个mss.mss()实例会报错。后来改成每个线程自己创建实例问题解决。所以如果你要做并发截图记得每个线程独立创建mss对象。第二个坑是 Tesseract 的临时文件。pytesseract在识别时会在系统临时目录生成中间文件如果程序异常退出这些文件可能残留。长时间运行的程序建议定期清理临时目录或者在调用时指定--tessdata-dir到一个可控的目录。第三个技巧是关于识别区域的微调。有时候截图区域稍微大一点或小一点识别率差别很大。我的做法是先用一个宽松的区域截图识别一次然后根据识别出的文字位置反推精确区域再截一次。虽然多了一次识别但准确率提升明显。这个技巧在处理表格类界面时特别有用。第四个技巧是缓存屏幕参数。get_screen_info()里的系统调用虽然不慢但如果你每秒截图好几次累积起来也是开销。我的做法是在类初始化时探测一次如果用户中途改了缩放比例提供一个手动刷新参数的方法。毕竟缩放比例不会频繁变没必要每次都查。5. 性能优化与扩展方向5.1 减少不必要的全屏截图很多人图省事每次都截全屏再裁剪。全屏截图在 4K 屏上就是 800 多万像素光是内存拷贝就要几十毫秒再加上后续处理整个流程会明显变慢。正确的做法是只截取目标区域mss的grab方法支持直接指定区域效率比全屏截图高得多。如果你确实需要先看全屏再决定截哪里可以截一次全屏然后在内存里裁剪出多个区域分别识别避免重复截图。这个在需要识别多个分散区域时特别有效。5.2 用 OpenCV 做更精细的定位前面说的都是“用户指定区域”但有些场景下区域是动态的比如你要识别一个会移动的弹窗。这时候可以用 OpenCV 做模板匹配或者轮廓检测自动找到目标区域。模板匹配的思路是先截一张包含目标的图作为模板然后在后续截图中用cv2.matchTemplate找到模板位置再截取该位置附近的区域做识别。这个方法对固定样式的界面元素很有效但对会变形的元素就不行了。轮廓检测适合文字区域定位思路是先二值化再用cv2.findContours找到文字块的边界框然后合并相邻的框得到文本区域。这个方法不需要模板适应性更强但参数调起来比较麻烦。5.3 批量识别与结果结构化如果截图里是表格数据识别出来的文本是一堆散乱的行还需要做结构化解析。我的做法是先用image_to_data拿到每个词的坐标然后按 y 坐标聚类成行按 x 坐标排序成列最后拼成二维表格。这个逻辑写起来有点绕但一旦写好处理报表类截图就非常顺手。def parse_table(pil_img, langchi_simeng): data pytesseract.image_to_data(pil_img, langlang, output_typepytesseract.Output.DICT) items [] for i, word in enumerate(data[text]): if word.strip() and int(data[conf][i]) 30: items.append({ text: word, x: data[left][i], y: data[top][i], h: data[height][i] }) # 按 y 坐标分行 items.sort(keylambda d: d[y]) rows [] current_row [] last_y None for item in items: if last_y is None or abs(item[y] - last_y) item[h] * 0.6: current_row.append(item) else: rows.append(sorted(current_row, keylambda d: d[x])) current_row [item] last_y item[y] if current_row: rows.append(sorted(current_row, keylambda d: d[x])) return [[cell[text] for cell in row] for row in rows]这段代码的核心是“按 y 坐标聚类成行”阈值取行高的 0.6 倍是我实测下来比较稳的值。太小会把同一行拆开太大会把相邻行合并。5.4 定时任务与结果输出如果这个工具是长期运行的可以配合schedule库做定时截图识别import schedule import time def job(): result ocr.recognize(100, 200, 800, 600) with open(output.txt, a, encodingutf-8) as f: f.write(f{time.strftime(%Y-%m-%d %H:%M:%S)}\n{result}\n\n) schedule.every(10).minutes.do(job) while True: schedule.run_pending() time.sleep(1)输出格式可以根据需求改成 CSV、JSON 或者直接写数据库。如果要做成服务可以用Flask包一层 HTTP 接口让其他程序调用。5.5 换用 PaddleOCR 的时机Tesseract 在英文和规整印刷体上表现不错但中文场景下尤其是字体多样、背景复杂时识别率会明显下降。如果你发现调参调到极限还是达不到要求就该考虑换 PaddleOCR 了。PaddleOCR 的调用方式和 Tesseract 不同它返回的是带坐标的文本列表from paddleocr import PaddleOCR ocr_engine PaddleOCR(use_angle_clsTrue, langch) result ocr_engine.ocr(np.array(pil_img), clsTrue) for line in result[0]: text line[1][0] confidence line[1][1] box line[0] print(text, confidence, box)它的优势是中文识别率明显更高而且自带方向分类对倾斜文字也能处理。代价是安装包大、首次加载模型慢。我的建议是如果项目以英文为主Tesseract 够用如果中文为主且对准确率要求高直接上 PaddleOCR别在 Tesseract 上死磕。6. 一些实战中的经验体会这个项目我从最初写死坐标的版本到后来能自适应各种分辨率中间改了好几版。最大的体会是屏幕参数探测这一步绝对不能省。我见过太多人为了图快直接把坐标写死结果代码只能在作者自己的机器上跑。多花二十行代码做自适应能省掉后面无数次的“在我电脑上明明可以”。另一个体会是关于预处理的。一开始我觉得 OCR 引擎应该足够智能不需要预处理。但实测下来同样的图预处理前后识别率能差 30% 以上。尤其是放大这一步对小于 20 像素的文字效果立竿见影。所以别偷懒该做的预处理一步都别少。还有一点是关于错误处理。截图和 OCR 都是容易出异常的环节比如截图时目标窗口被最小化了或者 OCR 引擎崩溃了。如果不做异常捕获程序跑着跑着就挂了。我的做法是在关键步骤外面包一层 try-except出错时记录日志并返回空结果让程序能继续跑下去。对于长期运行的定时任务这个尤其重要。最后分享一个小技巧如果你不确定某个区域的识别效果可以写一个调试模式把截图、预处理后的图、识别结果三样东西一起输出到一个文件夹里。这样每次识别不理想时你能快速定位是截图问题、预处理问题还是 OCR 问题。这个调试模式在我调参阶段帮了大忙强烈建议你也加上。
RELATED

相关推荐

C语言多线程+Pipe实现单机聊天系统

C语言多线程+Pipe实现单机聊天系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/17 1:18:53
双节锂电池主动均衡设计:MP2642GR-Z与STM32G071RB协同方案

双节锂电池主动均衡设计:MP2642GR-Z与STM32G071RB协同方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/17 1:18:53
双节锂电池主动均衡设计:MP2642+PIC18LF4680硬件闭环方案

双节锂电池主动均衡设计:MP2642+PIC18LF4680硬件闭环方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/17 1:13:53
MORE NEWS

更多资讯

📰

基于SIFT与RANSAC的高分辨率图像复制-移动篡改检测实战

前几天有人给我发来一张无人机航拍图,画面里是一排整齐的建筑群,他说其中一栋楼疑似是从画面另一个位置复制过去的,问我能不能用程序找出来。那张图是六千多像素宽的高分辨率原图,肉眼看相似区域看到眼花。我当时手里的方案就是基…

📰

双串锂电池主动均衡设计:MP2642GR-Z与STM32F415RG协同实现高精度闭环控制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

VTK 9.1预编译包:Windows下DICOM体绘制快速启动指南

简介:本资源为VTK 9.1 x64预编译二进制库,面向科学计算、医学影像处理与三维可视化领域的C开发者及高校科研人员,解决VTK源码编译门槛高、依赖复杂、环境适配难等痛点,开箱即用,显著降低项目集成成本。压缩包共3975个文…

📰

VSCode配置C/C++开发环境:零基础手把手教程

简介:本资源是一份面向Windows平台初学者与转用者的VSCode C/C开发环境搭建实战指南,解决从零配置编辑器、编译器到调试运行的全流程痛点。内容覆盖VSCode安装与汉化、MinGW-w64编译器下载解压与PATH环境变量配置、C/C插件安装、tasks.json与c_cpp_prope…

📰

VSCode+MinGW-w64配置C/C++开发环境完整指南

简介:本资源是一份面向C/C初学者与Windows平台开发者的VSCode环境配置实战指南,聚焦解决新手在轻量级编辑器中搭建完整编译调试环境的核心痛点。文档以保姆级步骤详解VSCode安装、中文语言包配置、MinGW-w64编译器下载解压与PATH环境变量设置、C/C插件安…

📰

Netty连接重置(RST)故障定位与实战修复指南

1. 项目概述:这不是网络抖动,是连接被对方“硬杀”了“Connection reset by peer”——这行报错在Netty服务端日志里一出现,很多刚接触高并发网络编程的开发者第一反应是:“是不是客户端断网了?”“是不是防火墙拦了&a…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬