2. Python图像处理环境搭建
农业机器视觉的第一步不是写算法,而是让计算机“看见”图像。本节要完成三件事:搭好可复现的Python图像处理环境,安装OpenCV、NumPy、Matplotlib三个核心库,并写出第一个能读取、显示农田图像的脚本,同时理解图像在计算机中究竟是怎样一串数字。环境搭得稳,后面做作物识别、病虫害检测、果实计数才不会在“库版本冲突”上反复踩坑。
为什么必须用虚拟环境
Python的第三方库安装在全局环境里时,不同项目会互相干扰。比如A项目需要OpenCV 4.5,B项目需要OpenCV 4.9,全局只能留一个版本。虚拟环境为每个项目创建独立的库目录,项目之间互不影响。常用工具是Python自带的venv,无需额外安装。
假设本课程所有代码放在D:\agri_vision目录下。打开命令行(Windows用cmd或PowerShell,macOS/Linux用终端),依次执行:
cd /d D:\agri_vision
python -m venv venv
venv\Scripts\activate
macOS或Linux下激活命令为source venv/bin/activate。激活成功后,命令行提示符前会出现(venv)字样,这是判断虚拟环境是否生效的最直接标志。之后所有pip install都只装进这个目录,不会污染系统Python。
安装三个核心库
三个库分工明确:OpenCV负责图像读写与处理,NumPy负责数组运算(图像本质就是数组),Matplotlib负责在笔记本或脚本中绘图显示。安装命令:
pip install opencv-python numpy matplotlib
如果后续要做视频流或摄像头采集,可改装opencv-contrib-python,它包含更多扩展模块。安装完成后建议立即验证版本,避免装上了却导入失败:
python -c "import cv2, numpy, matplotlib; print(cv2.__version__, numpy.__version__, matplotlib.__version__)"
能打印出三个版本号即表示环境可用。若提示ModuleNotFoundError,多半是虚拟环境未激活或pip装到了别处,先确认提示符前的(venv)再重装。
图像在计算机中的表示
一张彩色农田图像在计算机里是一个三维数组,形状为(高度, 宽度, 3)。高度对应行数(纵向像素数),宽度对应列数(横向像素数),最后的3是颜色通道。每个像素由三个0~255的整数组成,分别表示蓝、绿、红分量。注意OpenCV默认按BGR顺序存储,而Matplotlib按RGB显示,这是初学者最常遇到的“颜色发蓝/发红”问题的根源。
灰度图则是二维数组,形状为(高度, 宽度),每个元素是0~255的亮度值。数据类型通常是uint8,即无符号8位整数,取值范围0~255。理解这一点非常关键:后续所有滤波、阈值分割、边缘检测,本质上都是对这些数字做运算。
第一个脚本:读取并显示农田图像
准备一张农田照片,命名为field.jpg,放在脚本同目录。新建read_field.py,写入以下代码:
import cv2
import matplotlib.pyplot as plt
# 1. 读取图像(默认彩色,BGR顺序)
img = cv2.imread("field.jpg")
if img is None:
raise FileNotFoundError("未找到 field.jpg,请检查路径")
# 2. 查看图像的基本属性
print("形状:", img.shape) # (高, 宽, 通道)
print("数据类型:", img.dtype) # uint8
print("像素总数:", img.size)
# 3. 转为RGB后用Matplotlib显示
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(8, 5))
plt.imshow(rgb)
plt.title("Field Image")
plt.axis("off")
plt.show()
# 4. 另存为灰度图,观察通道变化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imwrite("field_gray.jpg", gray)
print("灰度图形状:", gray.shape) # (高, 宽)
运行后应看到窗口弹出农田图像,控制台打印类似形状: (720, 1280, 3)、数据类型: uint8、像素总数: 2764800。像素总数等于720×1280×3,正好验证了“图像是三维数组”这一结论。灰度图的形状变为(720, 1280),少了一个维度,说明颜色通道被合并为单一亮度值。
cv2.imread返回None,九成是路径错误或文件名拼写不符。Windows下路径含中文时,可改用cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR)读取,避免编码问题。用像素值做一次简单判断
理解数组表示后,就能直接对像素做运算。农田图像中绿色植被通常G通道明显高于R、B通道。下面这段代码统计“偏绿像素”的比例,作为植被覆盖的粗略估计:
import numpy as np
b, g, r = cv2.split(img)
mask = (g.astype(int) > r.astype(int) + 20) & (g.astype(int) > b.astype(int) + 20)
ratio = np.count_nonzero(mask) / mask.size
print("偏绿像素比例: %.2f%%" % (ratio * 100))
这里先把uint8转成int再比较,是因为uint8相减可能溢出回绕,导致判断错误。这个例子说明:环境搭好后,图像处理就是数组运算,NumPy的布尔索引和统计函数可以直接用在图像上。示例中的20是经验阈值,实际应根据光照和作物类型调整,不能当作固定标准。
环境配置检查清单
| 检查项 | 判断方法 | 常见问题 |
|---|---|---|
| 虚拟环境已激活 | 提示符前有(venv) | 忘记activate,库装到全局 |
| 三库可导入 | 打印三个版本号 | 只装了opencv未装numpy |
| 图像读取成功 | img is not None | 路径错误、中文路径 |
| 颜色显示正常 | 草地呈绿色而非蓝色 | 未做BGR→RGB转换 |
| 数组形状正确 | 三维且第三维为3 | 误读为灰度模式 |
完成以上步骤,你就拥有了一个可复现的农业机器视觉开发环境,并且亲手验证了“图像即数组”这一核心认知。后续的滤波去噪、颜色分割、轮廓提取,都将建立在这套环境和这个数组模型之上。