上周帮朋友修一张模糊的证件照,他想把人脸部分自动锐化,背景保持柔和。我一边写代码一边想:其实写图像算法没那么玄,关键是在动手前,把几个基本动作想清楚。
先盯住‘输入’和‘输出’长啥样
不急着写 for 循环。比如做灰度转换,输入是 RGB 三维数组(height × width × 3),输出是单通道二维数组(height × width)。画个草图,标好维度、数据范围(0–255 还是 0.0–1.0?)、边界怎么处理——这一步省了,后面八成要返工。
拆开“怎么做”,不是“用什么函数”
看到“高斯模糊”,别直接搜 cv2.GaussianBlur()。先问自己:每个像素的新值,怎么由它周围一圈像素算出来?权重怎么分配?中心点权重最大,离得越远越小,加起来得是 1。然后才去查核函数尺寸、标准差 σ 怎么设更合适。这种拆解,比抄参数有用得多。
拿最简例子手动推一遍
写边缘检测时,我习惯先挑一个 3×3 的小块图像,比如:
[[100, 120, 110],
[90, 130, 115],
[85, 125, 108]]用 Sobel 水平卷积核 [-1,0,1; -2,0,2; -1,0,1] 手动算中心点(130)的 Gx 值:(-1)×90 + 0×130 + 1×115 + (-2)×85 + 0×125 + 2×108 + (-1)×100 + 0×120 + 1×110 = … 算完再对照代码输出,错在哪一环一目了然。
边写边“打桩”,别等全写完再跑
写自适应阈值分割,我先让函数返回全 0 图像,确认能读图、显示、保存;再改成返回原图,验证流程通顺;接着加上均值计算,打印中间结果看看窗口大小是否合理;最后才加入比较逻辑。每步只动一小块,心里有底。
图像算法不是拼乐高,而是修水管——先看清水从哪来、往哪去,再一段段接,拧紧每一处接口。思路顺了,代码自然就稳了。