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 如 1280×720 彩色三通道 uint8 cv2.imread NumPy 数组 shape = (720,1280,3) dtype = uint8 通道顺序 BGR 像素值 0~255 cvtColor 显示与保存 BGR → RGB plt.imshow cv2.imshow cv2.imwrite 单个像素的存储示意(BGR 三字节) B=42 G=138 R=76 → 一个像素 = 3 个 uint8 关键约定:OpenCV 读入为 BGR,Matplotlib 按 RGB 显示, 显示前需 cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 转换,否则颜色异常。

第一个脚本:读取并显示农田图像

准备一张农田照片,命名为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误读为灰度模式

完成以上步骤,你就拥有了一个可复现的农业机器视觉开发环境,并且亲手验证了“图像即数组”这一核心认知。后续的滤波去噪、颜色分割、轮廓提取,都将建立在这套环境和这个数组模型之上。